JSON-RPC Error Codes
All errors follow the JSON-RPC 2.0 error response format:
{
"jsonrpc": "2.0",
"id": "1",
"error": {
"code": -32000,
"message": "Human-readable error message.",
"data": {}
}
}Error Code Reference
| Code | Meaning | Description |
|---|---|---|
-32700 |
Parse error | Invalid JSON payload. The request body could not be parsed. |
-32600 |
Invalid request | Missing jsonrpc: "2.0" or method field. |
-32601 |
Method not found | Unsupported method. Supported methods are initialize, notifications/initialized, ping, tools/list, and tools/call. |
-32602 |
Invalid params | Tool name is missing from params.name in a tools/call request. |
-32001 |
Authentication error | Missing, invalid, or expired API key. See Authentication. |
-32029 |
Rate limit exceeded | Too many requests. See rate limits below. |
-32000 |
Tool execution error | The tool ran but encountered an error (e.g., brand not found, insufficient credits). |
Rate Limits
Rate limits are applied per API key using a sliding window algorithm.
| Scope | Limit | Window | Applies To |
|---|---|---|---|
| General | 60 requests | 1 minute | All tool calls |
| Mutating | 10 requests | 1 minute | run_workflow, cancel_workflow_run |
Both limits are checked independently. A tools/call to run_workflow counts against both the general and mutating limits.
Rate Limit Response
When a rate limit is exceeded, the API returns error code -32029:
{
"jsonrpc": "2.0",
"id": null,
"error": {
"code": -32029,
"message": "Rate limit exceeded. Too many requests.",
"data": {
"retryAfter": 12
}
}
}Rate Limit Headers
Rate limit responses include the following HTTP headers:
| Header | Description | Example |
|---|---|---|
X-RateLimit-Limit |
Maximum requests allowed in the window | 60 |
X-RateLimit-Remaining |
Requests remaining in the current window | 0 |
X-RateLimit-Reset |
ISO 8601 timestamp when the window resets | 2026-02-18T12:01:00.000Z |
Retry-After |
Seconds to wait before retrying (only present when limited) | 12 |
Handling Rate Limits
- Check the
Retry-Afterheader (orerror.data.retryAfter) for the number of seconds to wait. - Implement exponential backoff for retries.
- Avoid tight polling loops — when polling
get_run_status, use 5-10 second intervals. - If you consistently hit the mutating limit, batch workflow operations or wait for runs to complete before starting new ones.