Developers
API overview & authentication
Base URL, API keys, scopes, errors, rate limits and pagination.
The REST API exposes everything the dashboard does. All requests and responses use JSON over HTTPS.
Base URL: https://your-domain/api/v1
API keys
Create keys in the dashboard under Developer mode → API keys. A key looks like caf_ followed by 40 characters and is shown once — store it in a secret manager.
Send it in the Authorization header (or X-API-Key):
curl https://your-domain/api/v1/forms \
-H "Authorization: Bearer caf_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
API keys are for server-side use. Browsers on other origins are blocked by CORS, so a key can’t be used from a web page.
Scopes
| Scope | Allows |
|---|---|
forms:read | List and read forms, versions |
forms:write | Create, update, publish, close, duplicate and delete forms |
responses:read | List, read and export responses, analytics, file downloads |
responses:write | Submit responses, override approvals, delete responses |
API keys can never manage API keys, webhooks, billing or the admin console — those require a signed-in session.
Errors
Errors always have the same shape:
{
"error": {
"code": "validation_failed",
"message": "Some fields are invalid.",
"details": [
{ "path": "experience[1].years", "code": "required", "message": "This field is required." }
]
}
}
| Status | code | Meaning |
|---|---|---|
| 400 | bad_request | Malformed request |
| 401 | unauthorized | Missing, invalid, expired or revoked credentials |
| 402 | plan_limit | Your plan doesn’t include this (or a limit is reached) |
| 403 | forbidden | Missing scope, or not allowed for API keys |
| 404 | not_found | Doesn’t exist or isn’t yours |
| 409 | conflict | The form changed since you loaded it (see revision) |
| 410 | gone | Form closed, full or disabled |
| 413 | payload_too_large | Body or file too large |
| 415 | unsupported_media_type | File format not allowed or content mismatch |
| 422 | validation_failed | Field errors in details |
| 429 | rate_limited | Slow down; see Retry-After header |
Rate limits
Each API key has a per-minute budget (Free 30, Pro 600 by default). When exceeded you get 429 with a Retry-After header in seconds. Public endpoints are also limited per IP address.
Pagination
List endpoints accept limit. Forms and admin lists use page; responses use a cursor: pass the next_cursor you received as before to get the next page.
IDs and timestamps
IDs are 24-character hex strings. Timestamps are ISO 8601 in UTC, e.g. 2026-10-18T09:24:11.502Z.