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.
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.
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.
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"
}'| Field | Type | Notes | |
|---|---|---|---|
| model | string | req | nano-banana-v2, nano-banana-pro |
| prompt | string | req | Generation prompt |
| aspect_ratio | string | 1:1, 16:9, 9:16, 4:3 | |
| resolution | string | 1K, 2K, 4K | |
| callback_url | string | HTTPS 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.
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"
}'| Field | Type | Notes | |
|---|---|---|---|
| model | string | req | Same live models as text to image |
| prompt | string | req | Edit / restyle instruction |
| url | string | req | HTTPS source. Alias: image_url |
| image_url | string | Same as url | |
| callback_url | string | Optional 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.
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>
{
"id": "job_…",
"status": "queued",
"model": "nano-banana-pro"
}Errors
Every error is JSON: { "error": { "status", "code", "message" } }
| Status | Code | When | |
|---|---|---|---|
| 400 | invalid_json | Body is not JSON | |
| 400 | invalid_request | Missing model, prompt, or url | |
| 401 | unauthorized | Missing or unknown API key | |
| 402 | insufficient_funds | Balance is $0.00 | |
| 404 | job_not_found | No accepted job with that id | |
| 405 | method_not_allowed | Wrong HTTP method | |
| 422 | model_unavailable | Omni / Veo / Gemini — not served yet | |
| 429 | rate_limited | Account RPM | |
| 500 | internal_error | Unexpected 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.
omni
Not served yet. Same envelope when it ships.
veo
Not served yet. Same envelope when it ships.
gemini
Not served yet. Same envelope when it ships.