API reference
Errors & limits
The error envelope, every status code you can expect, and how to handle them.
The envelope
Every error returns the same shape:
{
"detail": {
"error": "tier_required",
"message": "API access is available on the Platinum and Enterprise tiers."
}
}
Branch on detail.error, which is stable. Show detail.message to humans; it is written for that and may be reworded.
Status codes
| Status | When | Retry? |
|---|---|---|
400 |
Malformed request or a rejected value | No, fix the request |
401 |
Missing, invalid, revoked or expired credential | No, mint a new key |
402 |
Quota exceeded for your tier | No, upgrade or reduce row_count |
403 |
Authenticated, but not permitted | No |
404 |
No such resource, or one you cannot see | No |
422 |
Failed schema validation (bad types, out-of-range) | No |
429 |
Rate limited | Yes, with backoff |
500 |
Something broke on our side | Yes, once |
503 |
Backend briefly saturated | Yes, honour Retry-After |
Common error codes
detail.error |
Meaning |
|---|---|
tier_required |
Your tier does not include this feature |
session_required |
Requires an interactive login; an API key will not do |
invalid_token |
Credential not accepted |
not_author |
You can only modify your own content |
project_not_found |
No such project, or not visible to you |
schema_not_found |
The named schema does not exist on the target |
table_not_found |
A requested table is not in the introspected schema |
invalid_interval |
Schedule interval outside 15 minutes to 30 days |
too_many_keys |
20 active API keys already |
cascade_not_acknowledged |
A truncate would cascade; set truncate_cascade: true to confirm |
backend_saturated |
Connection pool exhausted; retry after the header value |
Two responses that are not what they look like
200 with pushed_to_db: false. The request succeeded; the write did not. Every row may have hit a constraint. Always read the field:
curl -s … | jq -e '.pushed_to_db == true'
403 session_required on /api/admin/*. Not a permissions bug. Those routes refuse API keys entirely, including the platform owner's own key.
404 vs 403
Resources you cannot see return 404, not 403, so ids cannot be probed for existence. Org-level endpoints return 403 when you are not a member, because membership is not a secret from you.
Rate limits and backpressure
Rate limits are per account. On 429, back off exponentially.
503 is different: it means the connection pool is momentarily exhausted, and the response carries Retry-After in seconds. Honour it. This is normal under burst load, not an outage, stagger CI schedules rather than firing every pipeline at midnight.
Quotas
| Tier | Rows per request | Rows per month |
|---|---|---|
| Hobby | 5,000 | 5,000 |
| Pro | 100,000 | 100,000 |
| Business / Platinum | 500,000 | 500,000 |
| Enterprise | 10,000,000 | effectively unlimited |
A 402 body includes your tier and the cap that was hit. Bonus-row balance is drawn down before a request is refused.
OpenAPI
The machine-readable spec is live:
- Swagger UI, click Authorize, paste a key, try any endpoint
- ReDoc
- openapi.json, for generating clients
Operator routes are absent from the spec by design. They remain gated regardless.