sangtao.ai
API key

Overview

API conventions

Errors

Every error answers in one shape:

json
{
  "success": false,
  "errorCode": "INVALID_DPI",
  "error": "dpi must be between 1 and 1200.",
  "details": [
    {
      "field": "dpi",
      "code": "INVALID_DPI",
      "message": "dpi must be between 1 and 1200.",
      "params": { "min": 1, "max": 1200 }
    }
  ],
  "requestId": "4bf92f3577b34da6a3ce929d0e0e4736"
}
  • successboolean

    false on every error.

  • errorCodestring

    The code to branch on. Every error has one.

  • errorstring

    A sentence for people — in English when the request carries an X-Api-Key header. It may be reworded — do not match on it.

  • detailsobject[]

    Errors only: what went wrong, field by field.

    Show child attributes
    • fieldstring

      The request field at fault, when there is one.

    • codestring

      The error code for this field.

    • messagestring

      A sentence for people.

    • paramsobject

      The numbers in the message (min, max, retryAfter…), to build your own sentence.

  • requestIdstring

    Errors only: the same value as the X-Request-Id header.

Every code, with its HTTP status, its English message and whether a retry can help, is listed by GET /v2/errors (no key needed) — and on Error codes.

Request ID

Every response carries an X-Request-Id header; an error repeats it as requestId. Quote it when you report a problem — it finds your call in our logs.

Rate limits

6,000 requests per minute per API key; uploading reference images (POST /images/presign) at most 30 a minute. Every response says where you stand:

HeaderMeaning
X-RateLimit-LimitRequests allowed per minute
X-RateLimit-RemainingRequests left in this minute
X-RateLimit-ResetWhen the count starts again, in Unix seconds
Retry-AfterOn a 429 only: seconds to wait

Over the limit, the call answers 429 with errorCode RATE_LIMITED. Wait Retry-After seconds, then send it again.

Pagination

Lists take page (from 1) and pageSize — limit is accepted as the same thing. The total is in the X-Total-Count header.

ListDefault pageSizeMaxNo page or pageSize sent
GET /characters50200Everything
GET /user-assets50200Everything
GET /jobs10100The first 10
GET /account/transactions20100The first 20

GET /jobs gives its total in the body (total) instead of the header.

Idempotency

POST /images/generations and POST /publishing/posts take a key, in the Idempotency-Key header or the idempotencyKey body field, kept for 24 hours:

You sendYou get
The same key, the same bodyThe earlier job or post, with idempotentReplay: true — nothing made or charged again
The same key, another body422 IDEMPOTENCY_KEY_REUSED
Header and body field with different keys422 VALIDATION_ERROR
No keyA new job or post, every time
One new key per operation (a UUID, say). Send an old key again only when retrying that exact request.

IDs

Every id is an opaque string with a prefix — sa_… (a social account), pp_… (a post’s network), tx_… (a transaction), acct_… (an account). Store it and send it back as it is; do not compare, sort or compute on it.