Guides
Errors
The API returns conventional HTTP status codes with a consistent JSON
envelope. Codes are stable strings — branch on error.code, not
on the human-readable error.message.
Response envelope
{
"error": {
"code": "insufficient_credits",
"message": "Balance 12 credits, need 45. Top up at https://app.dessert.dev/billing",
"doc_url": "https://docs.dessert.dev/credits-balance"
}
}
| Field | Description |
| error.codestring | Stable machine-readable code. Use this for control flow. |
| error.messagestring | Human-readable explanation. Safe to log or surface in dev tools; don't show end users. |
| error.doc_urlstring | Deep link into these docs for the most relevant section. May be omitted. |
HTTP status codes
| Status | Meaning |
| 200 | Success. |
| 202 | Accepted. Used by /v1/ads/generate and /v1/brands — work continues in the background. |
| 400 | Bad request. Schema validation failed. Fix the request before retrying. |
| 401 | Unauthorized. Missing, malformed, or revoked API key. |
| 402 | Payment required. Out of credits and auto-recharge couldn't cover the gap. |
| 403 | Forbidden. Account is suspended or the brand isn't yours. |
| 404 | Resource not found, or not visible from this account. |
| 425 | Too early. The brand is still onboarding — retry after the scrape window. |
| 429 | Rate limited. Back off and retry. |
| 500 | Internal error. Bug on our side. Safe to retry with an Idempotency-Key. |
| 502 | Upstream error. A downstream service (orchestrator, scraper) failed. Safe to retry. |
| 503 | Service unavailable. The embedding index or another component is warming up. Retry in 30s. |
Error codes
Authentication
| Code | Status | Fix |
| missing_authorization | 401 | Send the Authorization: Bearer … header. |
| invalid_authorization_scheme | 401 | Header must start with Bearer (with a space). |
| invalid_key_format | 401 | API keys start with dsrt_live_. |
| invalid_api_key | 401 | The key is unknown or has been rotated. Issue a new one in app.dessert.dev. |
Account & onboarding
| Code | Status | Fix |
| brand_onboarding_in_progress | 425 | Wait 15–60 minutes, then poll GET /v1/brands. |
| account_suspended | 403 | Email support@dessert.dev. |
| account_not_ready | 403 | Account is in an unexpected state. Contact support. |
Generate ads
| Code | Status | Fix |
| invalid_count | 400 | Set count to a positive integer. |
| invalid_format | 400 | Use "full" or "static". |
| no_brand_selected | 400 | Create a brand with POST /v1/brands, or pass brand_id. |
| brand_not_found | 404 | The brand_id doesn't belong to this account. |
| insufficient_credits | 402 | Top up at app.dessert.dev/billing or enable auto-recharge. |
| orchestration_failed | 502 | Retry — the orchestrator was momentarily unreachable. |
Deliveries
| Code | Status | Fix |
| delivery_not_found | 404 | Bad ID, or the delivery belongs to a different account. |
| upstream_error | 502 | Retry. Persistent failures are an outage — check our status page. |
Brands
| Code | Status | Fix |
| invalid_website | 400 | Pass a valid http(s):// URL. |
| scraper_failed | 502 | Retry; if it persists, the website may be blocking our crawler. |
Styles
| Code | Status | Fix |
| missing_query | 400 | Provide a non-empty ?q= parameter. |
| style_search_unavailable | 503 | The embedding index is warming up. Retry in 30s. |
Retry guidance
- 4xx (except 425, 429): the request is wrong. Don't retry — fix the request first.
- 425, 429: retry with backoff. The error message will hint at the wait time.
- 5xx: retry with exponential backoff. Use an
Idempotency-Key on /v1/ads/generate to avoid double-charging.