Character API Overview
Turn a folder of photos into a consistent, reusable character kit
Overview
The Character API turns a folder of photographs into a consistent character kit. You post up to 20 reference photos of one person and get back a character sheet — a split-screen full-body + close-up reference of that person.
Optionally (include_outfits: true) the finished sheet also fans out into
five outfit variants of the same person — six images instead of one, at six
times the cost.
Base URL: https://api.goodtake.ai/v1
You do not write a prompt, choose a model, or pick a size. That is the point — the prompt is authored and tuned server-side, and it is never accepted from, or returned to, the caller.
Endpoints
| Method | Path | Purpose |
|---|---|---|
POST | /character | Create a character from reference photos. Returns 202. |
GET | /character/{id} | Poll a character: status, sheet, outfits, reference outcomes. |
GET | /character | List your organization's characters (paginated). |
POST | /character/{id}/regenerate | Re-run the character from its stored references. Returns 202. |
GET | /character/pricing | Price both run shapes without creating anything. |
Cost
A default POST /character produces one billed generation; with
include_outfits: true it produces six. Prices are derived from live
pricing settings rather than hardcoded — at current settings:
| Run | Images | Credits | Approx. |
|---|---|---|---|
| Sheet only (default) | 1 | 6 | ~$0.18 |
With outfits (include_outfits: true) | 6 | 36 | ~$1.08 |
GET /character/pricing returns both prices in one response, so a create form
can re-price a checkbox without a second round trip:
curl -s https://api.goodtake.ai/v1/character/pricing \
-H "Authorization: Bearer $GOODTAKE_API_KEY" | jq .{
"credits_per_character": 6,
"image_count": 1,
"credits_with_outfits": 36,
"image_count_with_outfits": 6,
"outfit_count": 5,
"model": "dola-seedream-5-0-pro-260628"
}credits_per_character is the default run — the sheet alone. Read
credits_with_outfits when you intend to send include_outfits: true.
Each character also reports estimated_cost (the quote for its own run) next
to cost_credits (the actual charge so far — a running sum across the run's
generations, final only once the status is terminal).
POST /character/{id}/regenerate is a new run and is billed again at the
same price. It reuses the character's original include_outfits choice.
The model field is informational
Responses report the model a character was generated on, but that is a fact about the run, not a contract — we tune the product by changing it. Do not branch on it, pin to it, or assume today's value. A character keeps the model it was created with for the whole of its life, regenerates included, so the field is stable per character — just not across characters created weeks apart.
Relationship to the Image API
A character's generations are ordinary generations. They appear in
GET /image/generations and are individually readable
at GET /image/generations/{id} — you are billed for them, so hiding them
would be worse than showing them.
Their prompt field comes back empty. That is intentional: it is the only
thing keeping the compiled sheet and outfit prompts off the wire.
There is no SSE endpoint for characters. A character is one to six ordinary generations, so if you want a live stream you can subscribe per image using the generation ids from the character resource. What the character resource adds is the aggregate, which is a poll.
Errors
| Status | When |
|---|---|
400 | Malformed body, 0 or >20 image_urls, a non-http(s) scheme, or a URL resolving to an internal address. |
401 | Missing or invalid API key. |
402 | Insufficient credits (on regenerate; on create it surfaces as a character warning). |
404 | Unknown character id, or one belonging to another organization — we do not distinguish, deliberately. |
409 | Regenerate while a run is already open. |
422 | Regenerate on a character with no usable reference images. |
503 | The generation model is disabled or unavailable. |