Reference / v1

Puzzle API

Create a puz_live_ key in the console, then POST jobs. Production host is https://api.puzzle.team. This app serves the same error contract at /api/v1 so a key you just created can be verified here.

Confirmed balance starts at $0.00. A valid key with no credit returns 402 — that is expected, not a broken endpoint.

Authentication

Send the key as a Bearer token. Keys are SHA-256 hashed at rest; plaintext is shown once in the console. Missing or unknown keys return 401.

example
Authorization: Bearer puz_live_…

Balance

Returns confirmed credit on the ledger. Crypto hashes you log in the console stay pending until ops confirms them. USD wires and contracts are posted by Puzzle onto this same number — they never appear as a self-serve form.

GET/v1/balance
example
curl -sS "https://api.puzzle.team/v1/balance" \
  -H "Authorization: Bearer $PUZZLE_API_KEY"
{
  "balance": 0,
  "currency": "USD",
  "status": "unsettled"
}

Text to image

Asynchronous when funded. Until credit is confirmed the API rejects the job with 402 after validating the key and body. Live: nano-banana-v2, nano-banana-pro.

POST/v1/text-generations
curl -sS -X POST "https://api.puzzle.team/v1/text-generations" \
  -H "Authorization: Bearer $PUZZLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "nano-banana-pro",
    "prompt": "A cyan puzzle piece, studio light",
    "aspect_ratio": "1:1",
    "resolution": "1K"
  }'
FieldTypeNotes
modelstringreqnano-banana-v2, nano-banana-pro
promptstringreqGeneration prompt
aspect_ratiostring1:1, 16:9, 9:16, 4:3
resolutionstring1K, 2K, 4K
callback_urlstringHTTPS webhook, HMAC-signed when accepted (queued)

Image to image

Same envelope as text generations, plus a source image URL. Same live models, same 402 until funded. Accepts url or image_url.

POST/v1/url-generations
example
curl -sS -X POST "https://api.puzzle.team/v1/url-generations" \
  -H "Authorization: Bearer $PUZZLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "nano-banana-pro",
    "prompt": "Restyle as cyan studio light",
    "url": "https://example.com/source.png"
  }'
FieldTypeNotes
modelstringreqSame live models as text to image
promptstringreqEdit / restyle instruction
urlstringreqHTTPS source. Alias: image_url
image_urlstringSame as url
callback_urlstringOptional HTTPS webhook, signed when accepted

Jobs

Poll after a job is accepted. With a $0.00 balance nothing is accepted, so this path returns 404 job_not_found. Console → Run history is empty for the same reason.

GET/v1/jobs/:id
example
curl -sS "https://api.puzzle.team/v1/jobs/job_…" \
  -H "Authorization: Bearer $PUZZLE_API_KEY"
{
  "id": "job_…",
  "status": "queued",
  "model": "nano-banana-pro",
  "kind": "text"
}

Webhooks

Optional callback_url on create, or the HTTPS URL saved in console → webhooks. Delivered when a job is accepted (queued), not on a 402. X-Puzzle-Signature: sha256=<hex>

example
{
  "id": "job_…",
  "status": "queued",
  "model": "nano-banana-pro"
}

Errors

Every error is JSON: { "error": { "status", "code", "message" } }

StatusCodeWhen
400invalid_jsonBody is not JSON
400invalid_requestMissing model, prompt, or url
401unauthorizedMissing or unknown API key
402insufficient_fundsBalance is $0.00
404job_not_foundNo accepted job with that id
405method_not_allowedWrong HTTP method
422model_unavailableOmni / Veo / Gemini — not served yet
429rate_limitedAccount RPM
500internal_errorUnexpected server failure

Coming soon

These model ids return 422 model_unavailable. Nano Banana 2 and Pro are live on the contract — they still need a confirmed balance before a job is accepted.

422

omni

Not served yet. Same envelope when it ships.

422

veo

Not served yet. Same envelope when it ships.

422

gemini

Not served yet. Same envelope when it ships.