Get started
Errors & rate limits
Every response is wrapped in a consistent envelope:
Success
{
"success": true,
"data": { /* ... */ }
}Error
{
"success": false,
"statusCode": 403,
"code": "INSUFFICIENT_SCOPE",
"message": "This credential is missing the render:write scope",
"path": "/v1/templates/tpl_123/render",
"timestamp": "2026-09-08T12:00:00.000Z"
}Common error codes you may need to handle:
| Param | Type | Notes |
|---|---|---|
| 403 INVALID_API_KEY | Key is missing, malformed, or revoked. | |
| 403 SUBSCRIPTION_SUSPENDED | The key's workspace subscription is suspended. | |
| 403 WORKSPACE_MISMATCH | The request targets a workspace other than the key's own. | |
| 403 INSUFFICIENT_SCOPE | The key doesn't have the scope the endpoint requires. | |
| 403 EMBED_MISMATCH | An embed session token was used against a different embed id. | |
| 429 ThrottlerException | Rate limit exceeded — see below. | |
| 409 (unique constraint) | Postgres conflict — code is the violated constraint's name. |
Rate limits are per workspace and scale with your plan (requests/minute). Each plan's limit is reported back on GET /v1/me under plan.limits.rate_per_minute. Exceeding it returns 429:
429 Too Many Requests
{
"success": false,
"statusCode": 429,
"message": "ThrottlerException: Too Many Requests",
"path": "/v1/templates/tpl_123/render",
"timestamp": "2026-09-08T12:00:00.000Z"
}Rate-limit buckets are keyed per workspace for API keys — one noisy integration can't exhaust a teammate's allowance on a session-authenticated request.