dashboard
The methods of pd.dashboard. Inputs and outputs are described in Conventions; every method can also fail as described in Errors.
Methods
pd.dashboard.getAnalytics(input, init?)
Generation and publishing aggregates over a window
GET /api/workspaces/{workspaceId}/analytics
Requires analytics.read. Counts, sums and averages over work already recorded in the last days days; nothing is estimated. A figure with no data behind it is null, not 0. generation covers the generation and translation jobs created in the window; workflow covers review and publishing durations.
Input
| Name | In | Type | Required | Description |
|---|---|---|---|---|
workspaceId |
path | string (uuid) |
yes | Id of the workspace the request works in. The caller must be a member of it, or hold an API key issued by it. For anyone else, an unknown id and an id they do not belong to both answer 404 RESOURCE_NOT_FOUND, so membership cannot be probed. |
days |
query | integer |
no | Length of the window in days, counted back from now. From 1 to 365, default 30. Default: 30. |
init |
init | { signal?: AbortSignal; timeoutMs?: number } |
no | The second argument: signal aborts the call, timeoutMs overrides the client's per-attempt timeout. |
Returns 200 OK
| Field | Type | Required | Description |
|---|---|---|---|
windowDays |
integer |
yes | Length of the window the figures cover, in days, ending now; echoes the days query parameter. |
generation |
object |
yes | Article generation and translation jobs created in the window. |
generation.total |
integer |
yes | Generation jobs created in the window, whatever their status, queued and running ones included. |
generation.completed |
integer |
yes | Of those, the jobs that finished successfully. |
generation.failed |
integer |
yes | Of those, the jobs that ended in failure. |
generation.cancelled |
integer |
yes | Of those, the jobs that were cancelled. |
generation.successRate |
number | null |
yes | completed over completed plus failed, from 0 to 1; cancelled and unfinished jobs are left out. Null until a run has finished. |
generation.averageDurationMs |
integer | null |
yes | Mean time from start to completion of the completed runs, in milliseconds; null with none. |
generation.creditsConsumed |
integer |
yes | Credits charged for the jobs created in the window. |
workflow |
object |
yes | Review and publishing figures over the articles of the workspace. |
workflow.published |
integer |
yes | Articles created in the window that carry a publishedAt date. |
workflow.averageApprovalMs |
integer | null |
yes | Mean time, in milliseconds, from an article's creation to an approved review recorded in the window; null with none. |
workflow.averagePublishMs |
integer | null |
yes | Mean time, in milliseconds, from creation to publishedAt over the articles counted in published; null with none. |
Errors 400 invalid input, 401 missing or invalid key, 403 the key's roles lack the permission, 404 not found, 429 rate limited or out of quota. See Errors.
Example
import { PrismDraft } from "@prism-draft/sdk";
const pd = new PrismDraft({ apiKey: process.env.PRISMDRAFT_API_KEY! });
const result = await pd.dashboard.getAnalytics({
workspaceId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
});
console.log(result);
pd.dashboard.getTrends(input, init?)
Credits used and articles created or published, per day or week
GET /api/workspaces/{workspaceId}/trends
Requires analytics.read. Every bucket in the window is present, zero when nothing happened. Buckets are UTC days up to 31 days, Monday-starting weeks beyond. credits and operations come from the usage records; articles are counted by creation date and by publishedAt.
Input
| Name | In | Type | Required | Description |
|---|---|---|---|---|
workspaceId |
path | string (uuid) |
yes | Id of the workspace the request works in. The caller must be a member of it, or hold an API key issued by it. For anyone else, an unknown id and an id they do not belong to both answer 404 RESOURCE_NOT_FOUND, so membership cannot be probed. |
days |
query | integer |
no | Length of the window in days, ending today in UTC. From 7 to 365, default 30. Up to 31 days gives one bucket per day, more gives one per week. Default: 30. |
init |
init | { signal?: AbortSignal; timeoutMs?: number } |
no | The second argument: signal aborts the call, timeoutMs overrides the client's per-attempt timeout. |
Returns 200 OK
| Field | Type | Required | Description |
|---|---|---|---|
bucket |
"day" | "week" |
yes | day up to 31 days, week beyond. |
days |
integer |
yes | Length of the window in days, ending today (UTC); echoes the days query parameter. |
points |
object[] |
yes | Every bucket in the window, oldest first. Weekly buckets start on a Monday, so the first can begin before the window does. |
points[].start |
string |
yes | The bucket's first day, YYYY-MM-DD in UTC. |
points[].credits |
integer |
yes | Credits charged by the usage records written in the bucket. |
points[].operations |
integer |
yes | Usage records (billable operations) written in the bucket. |
points[].articlesCreated |
integer |
yes | Articles created in the bucket. |
points[].articlesPublished |
integer |
yes | Articles whose publishedAt date falls in the bucket. |
Errors 400 invalid input, 401 missing or invalid key, 403 the key's roles lack the permission, 404 not found, 429 rate limited or out of quota. See Errors.
Example
import { PrismDraft } from "@prism-draft/sdk";
const pd = new PrismDraft({ apiKey: process.env.PRISMDRAFT_API_KEY! });
const result = await pd.dashboard.getTrends({
workspaceId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
});
console.log(result);
pd.dashboard.getArticleCounts(input, init?)
Article counts by status
GET /api/workspaces/{workspaceId}/article-counts
Requires articles.read. Counts every article of the workspace straight from the database, not capped by list paging: in total, by status, by project, and by status within each project. Absent keys mean zero.
Input
| Name | In | Type | Required | Description |
|---|---|---|---|---|
workspaceId |
path | string (uuid) |
yes | Id of the workspace the request works in. The caller must be a member of it, or hold an API key issued by it. For anyone else, an unknown id and an id they do not belong to both answer 404 RESOURCE_NOT_FOUND, so membership cannot be probed. |
init |
init | { signal?: AbortSignal; timeoutMs?: number } |
no | The second argument: signal aborts the call, timeoutMs overrides the client's per-attempt timeout. |
Returns 200 OK
| Field | Type | Required | Description |
|---|---|---|---|
total |
integer |
yes | Articles in the workspace, across every project and status. |
byStatus |
Record<string, integer> |
yes | Article count per status (DRAFT, QUEUED, PROCESSING, NEEDS_REVIEW, CHANGES_REQUESTED, APPROVED, PUBLISHED), keyed by status; a status with no articles is absent. |
byProject |
Record<string, integer> |
yes | Article count per project, keyed by project id; a project with no articles is absent. |
byProjectStatus |
Record<string, Record<string, integer>> |
yes | Per project id, per status: only the statuses present. |
Errors 400 invalid input, 401 missing or invalid key, 403 the key's roles lack the permission, 404 not found, 429 rate limited or out of quota. See Errors.
Example
import { PrismDraft } from "@prism-draft/sdk";
const pd = new PrismDraft({ apiKey: process.env.PRISMDRAFT_API_KEY! });
const result = await pd.dashboard.getArticleCounts({
workspaceId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
});
console.log(result);
pd.dashboard.listJobs(input, init?)
Running jobs, and those that failed recently
GET /api/workspaces/{workspaceId}/jobs
Requires articles.read. Returns two lists, each bounded by limit: the generation and translation jobs running now, queued ones included, and the jobs that failed and were created within the last failedWithinDays days. Completed and cancelled jobs are not listed.
Input
| Name | In | Type | Required | Description |
|---|---|---|---|---|
workspaceId |
path | string (uuid) |
yes | Id of the workspace the request works in. The caller must be a member of it, or hold an API key issued by it. For anyone else, an unknown id and an id they do not belong to both answer 404 RESOURCE_NOT_FOUND, so membership cannot be probed. |
limit |
query | integer |
no | Most jobs returned in each of active and failed. From 1 to 100, default 50. Default: 50. |
failedWithinDays |
query | integer |
no | How far back to look for failed jobs, in days, by the time the job was created. From 1 to 90, default 7. Default: 7. |
init |
init | { signal?: AbortSignal; timeoutMs?: number } |
no | The second argument: signal aborts the call, timeoutMs overrides the client's per-attempt timeout. |
Returns 200 OK
| Field | Type | Required | Description |
|---|---|---|---|
active |
object[] |
yes | Jobs running now, queued ones included, newest first, up to limit. |
active[].id |
string (uuid) |
yes | Id of the generation job. |
active[].articleId |
string (uuid) |
yes | Id of the article the job writes or translates. |
active[].articleTitle |
string |
yes | Current title of that article. |
active[].projectId |
string (uuid) |
yes | Id of the project the article belongs to. |
active[].status |
string |
yes | One of QUEUED (accepted, not started yet), TRANSLATING, VALIDATING, RESEARCHING, OUTLINING, WRITING, GENERATING_IMAGE_PROMPTS, GENERATING_IMAGES, PROCESSING_MEDIA, FINALIZING (the stage a running job is in) or FAILED. Jobs in active carry a running status, jobs in failed carry FAILED; COMPLETED and CANCELLED jobs are never listed here. |
active[].currentStep |
string | null |
yes | The pipeline step: validate, research, outline, write, image-prompts, images, media-processing, translate or finalize. |
active[].progress |
integer |
yes | Percent complete, from 0 to 100, as of the current step. |
active[].reservedCredits |
integer |
yes | Credits earmarked for the job when it was started. |
active[].consumedCredits |
integer |
yes | Credits charged for the job; 0 until it has been settled. |
active[].errorCode |
string | null |
yes | Machine-readable code of the failure; null unless the job failed. |
active[].errorMessage |
string | null |
yes | Human-readable reason for the failure; null unless the job failed. |
active[].createdAt |
string (date-time) |
yes | When the job was queued. |
active[].completedAt |
string (date-time) | null |
yes | When the job reached a final status; null while it is running. |
failed |
object[] |
yes | Jobs that failed and were created within failedWithinDays, newest first, up to limit. |
failed[].id |
string (uuid) |
yes | Id of the generation job. |
failed[].articleId |
string (uuid) |
yes | Id of the article the job writes or translates. |
failed[].articleTitle |
string |
yes | Current title of that article. |
failed[].projectId |
string (uuid) |
yes | Id of the project the article belongs to. |
failed[].status |
string |
yes | One of QUEUED (accepted, not started yet), TRANSLATING, VALIDATING, RESEARCHING, OUTLINING, WRITING, GENERATING_IMAGE_PROMPTS, GENERATING_IMAGES, PROCESSING_MEDIA, FINALIZING (the stage a running job is in) or FAILED. Jobs in active carry a running status, jobs in failed carry FAILED; COMPLETED and CANCELLED jobs are never listed here. |
failed[].currentStep |
string | null |
yes | The pipeline step: validate, research, outline, write, image-prompts, images, media-processing, translate or finalize. |
failed[].progress |
integer |
yes | Percent complete, from 0 to 100, as of the current step. |
failed[].reservedCredits |
integer |
yes | Credits earmarked for the job when it was started. |
failed[].consumedCredits |
integer |
yes | Credits charged for the job; 0 until it has been settled. |
failed[].errorCode |
string | null |
yes | Machine-readable code of the failure; null unless the job failed. |
failed[].errorMessage |
string | null |
yes | Human-readable reason for the failure; null unless the job failed. |
failed[].createdAt |
string (date-time) |
yes | When the job was queued. |
failed[].completedAt |
string (date-time) | null |
yes | When the job reached a final status; null while it is running. |
Errors 400 invalid input, 401 missing or invalid key, 403 the key's roles lack the permission, 404 not found, 429 rate limited or out of quota. See Errors.
Example
import { PrismDraft } from "@prism-draft/sdk";
const pd = new PrismDraft({ apiKey: process.env.PRISMDRAFT_API_KEY! });
const result = await pd.dashboard.listJobs({
workspaceId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
});
console.log(result);
pd.dashboard.listAudit(input, init?)
Audit trail entries, filtered and paged
GET /api/workspaces/{workspaceId}/audit
Requires audit.read. The audit trail records what members, API keys, the system and Stripe did in the workspace; it is append-only and read only here. Entries come newest first, optionally narrowed by exact action, acting user and time window. total counts every matching entry, so pages are walked with limit and offset.
Input
| Name | In | Type | Required | Description |
|---|---|---|---|---|
workspaceId |
path | string (uuid) |
yes | Id of the workspace the request works in. The caller must be a member of it, or hold an API key issued by it. For anyone else, an unknown id and an id they do not belong to both answer 404 RESOURCE_NOT_FOUND, so membership cannot be probed. |
limit |
query | integer |
no | Most entries to return. From 1 to 100, default 30. Default: 30. |
offset |
query | integer |
no | Entries to skip, newest first, for paging with limit. Default 0. Default: 0. |
action |
query | string |
no | Only entries of this action, matched exactly, e.g. api_keys.created. Omit for every action. |
actorId |
query | string |
no | Only entries written by this user (a user id). Entries by API keys, the system or Stripe have no user and never match. Omit for every actor. |
from |
query | string (date-time) |
no | Only entries written at or after this UTC ISO 8601 datetime. Omit for no lower bound. |
to |
query | string (date-time) |
no | Only entries written at or before this UTC ISO 8601 datetime. Omit for no upper bound. |
init |
init | { signal?: AbortSignal; timeoutMs?: number } |
no | The second argument: signal aborts the call, timeoutMs overrides the client's per-attempt timeout. |
Returns 200 OK
| Field | Type | Required | Description |
|---|---|---|---|
entries |
object[] |
yes | One page of the matching entries, newest first: at most limit, after skipping offset. |
entries[].id |
string (uuid) |
yes | Id of the audit entry. |
entries[].action |
string |
yes | What happened, as <resource>.<verb>, e.g. api_keys.created, articles.published or credits.adjusted. |
entries[].resourceType |
string |
yes | Kind of record the action touched, e.g. credit_wallet or usage_quota. |
entries[].resourceId |
string | null |
yes | Id of the record the action touched; null when the action has no single target. |
entries[].actorName |
string | null |
yes | The acting user's name; null for an API key, the system or Stripe, and once the user is deleted. |
entries[].actorType |
string |
yes | Who acted: user (a signed-in person), api_key, system (a background job) or stripe (a verified Stripe webhook). |
entries[].result |
string |
yes | success, or failure for an attempt that did not succeed. |
entries[].metadata |
unknown |
yes | What the entry recorded about the action; an object whose keys depend on action. |
entries[].createdAt |
string (date-time) |
yes | When the entry was written; entries are never changed afterwards. |
total |
integer |
yes | Entries matching the filters, ignoring the page. |
Errors 400 invalid input, 401 missing or invalid key, 403 the key's roles lack the permission, 404 not found, 429 rate limited or out of quota. See Errors.
Example
import { PrismDraft } from "@prism-draft/sdk";
const pd = new PrismDraft({ apiKey: process.env.PRISMDRAFT_API_KEY! });
const result = await pd.dashboard.listAudit({
workspaceId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
});
console.log(result);
pd.dashboard.getCreditBurn(input, init?)
Credit consumption over recent days
GET /api/workspaces/{workspaceId}/credit-burn
Requires credits.read. The rate the low-balance warning extrapolates from: the credits charged to generation jobs created in the last days days, divided by the days actually observed. A workspace younger than the window is divided by its age (at least one day), and sufficientHistory is false below three days of history.
Input
| Name | In | Type | Required | Description |
|---|---|---|---|---|
workspaceId |
path | string (uuid) |
yes | Id of the workspace the request works in. The caller must be a member of it, or hold an API key issued by it. For anyone else, an unknown id and an id they do not belong to both answer 404 RESOURCE_NOT_FOUND, so membership cannot be probed. |
days |
query | integer |
no | Length of the window in days, counted back from now. From 1 to 90, default 30. Default: 30. |
init |
init | { signal?: AbortSignal; timeoutMs?: number } |
no | The second argument: signal aborts the call, timeoutMs overrides the client's per-attempt timeout. |
Returns 200 OK
| Field | Type | Required | Description |
|---|---|---|---|
consumed |
integer |
yes | Credits charged for the generation jobs created within the requested window. |
days |
integer |
yes | Days actually observed: fewer than the window for a young workspace. |
perDay |
number |
yes | Average credits consumed per day: consumed divided by the days observed, not rounded. |
sufficientHistory |
boolean |
yes | False with under three days of history, when a runway estimate means nothing. |
Errors 400 invalid input, 401 missing or invalid key, 403 the key's roles lack the permission, 404 not found, 429 rate limited or out of quota. See Errors.
Example
import { PrismDraft } from "@prism-draft/sdk";
const pd = new PrismDraft({ apiKey: process.env.PRISMDRAFT_API_KEY! });
const result = await pd.dashboard.getCreditBurn({
workspaceId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
});
console.log(result);