PrismDraft SDK

usage

The methods of pd.usage. Inputs and outputs are described in Conventions; every method can also fail as described in Errors.

Methods

pd.usage.listTransactions(input, init?)

The credit ledger, newest first

GET /api/workspaces/{workspaceId}/transactions

Requires credits.read. The credit ledger is append-only: every credit and debit is a row, and rows are never updated or deleted. amount is signed against the available credits and type says what the row records. Returns up to limit rows, at most 200, and has no 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 ledger rows to return, newest first. From 1 to 200, default 50. The route has no offset, so rows older than the newest limit cannot be reached. Default: 50.
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
transactions object[] yes Ledger rows, newest first, up to limit.
transactions[].id string (uuid) yes Id of the ledger row.
transactions[].workspaceId string (uuid) yes Id of the workspace whose wallet the row belongs to.
transactions[].walletId string (uuid) yes Id of the credit wallet the row changed.
transactions[].type "purchase" | "consumption" | "refund" | "reservation" | "reservation_release" | "reservation_capture" | "manual_adjustment" | "expiration" | "signup_grant" | "subscription_grant" | "platform_gift" yes What the ledger row records, with the sign of amount. purchase (+): a credit pack paid for, added when Stripe confirms the payment. consumption (-): a direct debit for work with no prior reservation. refund (-): credits taken back after Stripe refunded a pack purchase; metadata.shortfall holds what had already been spent and could not be reclaimed. reservation (-): credits earmarked for a running operation; the total balance does not change. reservation_release (+): an earmark lifted, so the credits are available again; also written, for the full hold, just before a reservation_capture. reservation_capture (-): the actual charge for the work, never more than the hold. manual_adjustment (+ or -): an Owner's correction, with metadata.reason. expiration: positive when a stale reservation is lifted, negative when plan credits expire at renewal or when the subscription ends. signup_grant (+): the one-time grant at sign-up. subscription_grant (+): the plan credits for one paid subscription invoice. platform_gift (+): credits the PrismDraft team gave the workspace, with metadata.reason.
transactions[].amount integer yes Signed change to the available credits: positive when credits were added or made available again, negative for debits and new reservations. Summing amount over the ledger gives the available credits.
transactions[].balanceAfter integer yes The wallet's total balance after this row, not its available credits: a reservation row leaves it unchanged.
transactions[].referenceType string | null yes What referenceId points at, e.g. credit_reservation, article_generation_job, article_asset, stripe_checkout_session, subscription_invoice or plan_credits; null when the row refers to nothing, as with a manual adjustment.
transactions[].referenceId string | null yes Id of the record named by referenceType; null when there is none.
transactions[].stripeEventId string | null yes Id of the Stripe event that caused the row (evt_…), set on purchases, refunds and subscription grants; unique, so a replayed event cannot credit twice. Null otherwise.
transactions[].metadata unknown yes A JSON object the writer attached, e.g. reason on an adjustment; {} when none.
transactions[].createdBy string | null yes Id of the user who caused the row; null for system and Stripe movements and for API keys.
transactions[].createdAt string (date-time) yes When the row was written; rows are never updated afterwards.

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.usage.listTransactions({
  workspaceId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
});
console.log(result);

pd.usage.get(input, init?)

Usage records, filterable by window, project, user, operation and provider

GET /api/workspaces/{workspaceId}/usage

Requires analytics.read. Returns two views of the usage records that match the filters: summary groups them by operation type, provider and model, and records lists the newest ones up to limit. Usage records say what providers were asked to do, with an estimated provider cost in USD micros; they are kept apart from the credits charged. In summary, credits and estimatedProviderCostMicros are bigint sums and arrive as decimal strings. costKnown false means the model has no known rate, so a cost of 0 is absence of data, not a free call.

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.
from query string (date-time) no Start of the window, inclusive: a UTC ISO 8601 datetime such as 2026-10-01T00:00:00Z. Omit for no lower bound.
to query string (date-time) no End of the window, inclusive: a UTC ISO 8601 datetime. Omit for no upper bound.
projectId query string (uuid) no Only records written for this project. Omit for every project.
userId query string no Only records of operations started by this user (a user id). Omit for every user.
type query "article_generation" | "article_translation" | "image_generation" | "image_regeneration" | "ai_edit" | "research" | "fact_check" | "embedding" no Only records of this operation type (see type on a record). Accepts every type except site_analysis. Omit for all types.
provider query string no Only records served by this provider, matched exactly, e.g. openai. Omit for all providers.
limit query integer no Most records to return in records, newest first. From 1 to 200, default 50. summary is not limited by it. Default: 50.
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
summary object[] yes Totals per operation type, provider and model over every record that matches the filters; not limited by limit.
summary[].type "article_generation" | "article_translation" | "image_generation" | "image_regeneration" | "ai_edit" | "research" | "fact_check" | "embedding" | "site_analysis" yes The operation that was paid for. article_generation: writing an article or its outline. article_translation: translating an article. image_generation: images made with an article. image_regeneration: one image regenerated on its own. ai_edit: an AI edit or suggestion, including category and idea suggestions. research: web research searches. fact_check: fact-checking an article's claims. embedding: embedding a knowledge source for search. site_analysis: analysing a website for a project.
summary[].provider string yes Name of the provider the group's calls went to.
summary[].model string | null yes Model the group's calls used; null for records with no model.
summary[].operations integer yes Number of usage records in the group.
summary[].inputTokens integer yes Sum of prompt tokens over the group.
summary[].outputTokens integer yes Sum of output tokens over the group.
summary[].images integer yes Sum of images generated over the group.
summary[].credits integer | string yes Credits charged over the group. A bigint sum: the wire carries a decimal string, e.g. "3", so parse it before doing arithmetic.
summary[].estimatedProviderCostMicros integer | string yes USD times 1,000,000, a bigint sum: the wire carries a decimal string, e.g. "1500".
summary[].costKnown boolean yes False when the model has no known rate: a cost of 0 is then absence of data.
records object[] yes The most recent matching usage records, newest first, at most limit (default 50). No offset: older ones are reached by narrowing from and to.
records[].id string (uuid) yes Id of the usage record.
records[].workspaceId string (uuid) yes Id of the workspace that paid for the operation.
records[].projectId string (uuid) | null yes Id of the project the operation ran in; null when it belongs to none.
records[].userId string | null yes Id of the user who triggered the operation; null when it was not started by a user or the user was deleted.
records[].type "article_generation" | "article_translation" | "image_generation" | "image_regeneration" | "ai_edit" | "research" | "fact_check" | "embedding" | "site_analysis" yes The operation that was paid for. article_generation: writing an article or its outline. article_translation: translating an article. image_generation: images made with an article. image_regeneration: one image regenerated on its own. ai_edit: an AI edit or suggestion, including category and idea suggestions. research: web research searches. fact_check: fact-checking an article's claims. embedding: embedding a knowledge source for search. site_analysis: analysing a website for a project.
records[].provider string yes Name of the provider that served the call, e.g. openai.
records[].model string | null yes Model that served the call; null when none applies.
records[].quantity integer yes How much the operation used, counted in unit. For article_generation it is the number of articles written (0 for a run that produced none, such as an outline-only leg).
records[].unit "tokens" | "images" | "requests" | "bytes" yes What quantity counts: model tokens, generated images, provider requests, or bytes.
records[].inputTokens integer yes Prompt tokens sent to the model; 0 for calls that are not token-priced.
records[].outputTokens integer yes Tokens the model returned; 0 for calls that are not token-priced.
records[].imageCount integer yes Images generated by the call; 0 for other operations.
records[].durationMs integer yes Wall-clock duration of the call in milliseconds; 0 when it was not measured.
records[].estimatedProviderCostMicros integer yes Estimated cost the provider charged, in millionths of a US dollar (USD times 1,000,000). 0 for a model with no known rate, which means unknown rather than free. Kept apart from credits, which is what the customer paid.
records[].credits integer yes Credits this operation cost the workspace; 0 when it was free of charge.
records[].referenceType string | null yes What referenceId points at, e.g. article_generation_job; null when nothing.
records[].referenceId string | null yes Id of the record named by referenceType; null when there is none.
records[].metadata unknown yes A JSON object the writer attached, e.g. leg: "outline"; {} when none.
records[].createdAt string (date-time) yes When the operation was recorded.

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.usage.get({
  workspaceId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
});
console.log(result);

pd.usage.listPayments(input, init?)

Checkout and payment history

GET /api/workspaces/{workspaceId}/payments

Requires billing.read. Lists the workspace's credit-pack checkouts, newest first, at most 50. Pending, expired and failed checkouts are listed too; only completed ones added credits. Subscription payments are not here: they are the invoices of GET /api/workspaces/{workspaceId}/subscription. Card details and Stripe customer identifiers are never returned.

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
payments object[] yes Credit-pack checkouts, newest first, at most 50, whatever their status. Subscription payments appear as invoices in the subscription read.
payments[].id string (uuid) yes Id of the checkout session record.
payments[].packageName string | null yes Name of the credit pack that was bought; null if the pack no longer exists.
payments[].priceCents integer | null yes The pack's current price in the smallest unit of currency; null if the pack no longer exists.
payments[].currency string | null yes Lower-case ISO 4217 code of the pack's price; null if the pack no longer exists.
payments[].creditAmount integer yes Credits the purchase adds, fixed when the checkout was opened.
payments[].status "pending" | "completed" | "expired" | "failed" yes pending: the Stripe Checkout session was opened and no outcome has arrived. completed: Stripe confirmed the payment and the credits were added. expired: the session lapsed unpaid. failed: the payment did not go through.
payments[].createdAt string (date-time) yes When the checkout was opened.
payments[].completedAt string (date-time) | null yes When Stripe confirmed the payment; null until then.

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.usage.listPayments({
  workspaceId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
});
console.log(result);

pd.usage.listQuotas(input, init?)

Quota limits and current consumption

GET /api/workspaces/{workspaceId}/quotas

Requires billing.read. Lists the quotas configured for the workspace with what has been used against each. Quotas are entitlements kept apart from the credit balance: a workspace holding credits is still refused with 429 QUOTA_EXCEEDED once a quota is used up. A metric with no entry is unlimited. The limits a plan sets (users, projects, ai_operations) are listed here too. Entries do not say which period they count over.

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
quotas object[] yes One entry per configured quota. A metric with no entry has no limit. The period a quota counts over (month or total) is not part of the entry.
quotas[].metric "articles" | "images" | "ai_operations" | "storage_bytes" | "users" | "projects" | "api_requests" yes What the quota limits. articles: articles generated. images: images generated, with an article or on their own. ai_operations: AI calls counted against the plan's monthly allowance (set by the plan): AI edits, idea, brief, category, internal-link and social-post generation, and generation runs that stop at the outline for review. storage_bytes: bytes of stored article assets. users: members of the workspace (set by the plan). projects: projects in the workspace (set by the plan). api_requests: requests authenticated with the workspace's API keys.
quotas[].limit integer yes The configured limit, in the metric's own unit (a count; bytes for storage_bytes). 0 blocks the metric entirely.
quotas[].used integer yes Consumption counted against the limit now, in the same unit.
quotas[].remaining integer yes limit less used, never below 0.

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.usage.listQuotas({
  workspaceId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
});
console.log(result);

pd.usage.setQuota(input, init?)

Set or clear a quota

PUT /api/workspaces/{workspaceId}/quotas

Requires billing.manage. Sets the limit of one metric for a period, or removes it when limitValue is null, which leaves the metric unlimited. users, projects and ai_operations belong to the workspace's plan, which rewrites them on every subscription event, so they are refused with 400. Records a billing.quota_changed audit entry and returns the full quota list, as the read route does.

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.
body body object yes
body.metric body "articles" | "images" | "ai_operations" | "storage_bytes" | "users" | "projects" | "api_requests" yes What to limit: articles, images, storage_bytes or api_requests. users, projects and ai_operations are set by the workspace's plan and are refused with 400.
body.period body "month" | "total" no What the quota counts over: month since the start of the current UTC month, or total over all time. Defaults to month. storage_bytes is always counted as stored now, whatever the period. Default: "month".
body.limitValue body integer | null yes The limit, in the metric's unit (a count; bytes for storage_bytes). 0 blocks the metric entirely. Null removes the quota for this metric and period, which leaves it unlimited.
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
quotas object[] yes One entry per configured quota. A metric with no entry has no limit. The period a quota counts over (month or total) is not part of the entry.
quotas[].metric "articles" | "images" | "ai_operations" | "storage_bytes" | "users" | "projects" | "api_requests" yes What the quota limits. articles: articles generated. images: images generated, with an article or on their own. ai_operations: AI calls counted against the plan's monthly allowance (set by the plan): AI edits, idea, brief, category, internal-link and social-post generation, and generation runs that stop at the outline for review. storage_bytes: bytes of stored article assets. users: members of the workspace (set by the plan). projects: projects in the workspace (set by the plan). api_requests: requests authenticated with the workspace's API keys.
quotas[].limit integer yes The configured limit, in the metric's own unit (a count; bytes for storage_bytes). 0 blocks the metric entirely.
quotas[].used integer yes Consumption counted against the limit now, in the same unit.
quotas[].remaining integer yes limit less used, never below 0.

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.usage.setQuota({
  workspaceId: "3f0c5a1e-8b2d-4c6e-9a7f-1d2e3f4a5b6c",
  body: {
    metric: "articles",
    limitValue: 1,
  },
});
console.log(result);