Skip to content

Errors and credits

Every error response — for every endpoint — uses the same structured envelope:

{
"error": {
"code": "INSUFFICIENT_BALANCE",
"message": "Account balance is below the cost of this request.",
"request_id": "01JREQREQREQREQREQREQREQ00"
}
}
  • code — a stable, machine-readable string. Branch on this, not on the message text.
  • message — a human-readable explanation; wording may change.
  • request_id — the 26-char ULID for this request, also returned on the 202 success envelope and recorded in your usage log. Quote it in support requests.

The codes you’ll encounter on a dispatch (see the per-endpoint responses in the API reference):

HTTPcodeMeaning
402INSUFFICIENT_BALANCEThe request cost exceeds your credit balance. No job is created and nothing is charged.
422VALIDATION_ERRORThe request body or parameters failed validation. No credits charged.
429RATE_LIMITEDPer-credential rate limit exceeded. Back off and retry.

Credits gate every dispatch. The cost is a flat, per-dispatch amount that is deducted synchronously when you call a workflow endpoint and echoed back as credits_cost in the 202 response. Authoritative, live costs are served by GET /v1/operations (each entry carries name, op_class, credits_cost, and an enabled flag) — query it rather than hard-coding prices. The current defaults:

WorkflowClassCredits
model-generatorgenerator5
background-generatorgenerator5
complementary-garment-generatorgenerator5
product-to-model-directcompose10
product-to-model-phasedcompose10
background-swap-with-imageedit5
background-swap-with-specedit5
model-swap-with-imageedit5
try-on10
extract1
look10 (placeholder; defaults to the try-on cost pending a pricing decision)

Reads (GET /v1/jobs*, GET /v1/renders*, catalog, etc.) and uploads do not cost credits.

Credits are charged at dispatch, before the engine runs. If the job later fails — or if the gateway accepted the request but studio never returned a job — the charge is automatically refunded. A background reconciler sweeps for any orphaned charge and refunds it, so a failed render never costs you credits. You can confirm a refund in your usage log: the row’s status moves to REFUNDED and credits_refunded reflects the amount returned.

  • GET /v1/credits — your current balance, plan, today’s spend (daily_spend_today), the daily cap (daily_spend_cap_credits, 0 means unlimited), the monthly quota (monthly_credit_quota, 0 means pay-as-you-go), and your per-minute rate limit (rate_limit_per_min).
  • GET /v1/usage — a paginated log of your requests, one row per call, with credits_charged, credits_refunded, the resolved status (PENDING | SUCCESS | FAILED | REFUNDED), the request_id, and the linked job_id.

Requests are rate-limited per credential. The ceiling is your rate_limit_per_min, visible on GET /v1/credits. Exceeding it returns 429 with code RATE_LIMITED; retry after a short backoff. Daily and monthly spend caps (daily_spend_cap_credits, monthly_credit_quota) bound total consumption over longer windows — both reported on GET /v1/credits.