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):

HTTP code Meaning
402 INSUFFICIENT_BALANCE The request cost exceeds your credit balance. No job is created and nothing is charged.
422 VALIDATION_ERROR The request body or parameters failed validation. No credits charged.
429 RATE_LIMITED Per-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:

Workflow Class Credits
model-generator generator 5
background-generator generator 5
complementary-garment-generator generator 5
product-to-model-direct compose 10
product-to-model-phased compose 10
background-swap-with-image edit 5
background-swap-with-spec edit 5
model-swap-with-image edit 5
try-on 10
extract 1
look 10 (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.