Authentication
The Capturia API is authenticated via Bearer key, server-side. One critical rule: never expose a key in a browser.
Key format
All keys issued since 2026-05 follow the cap_live_<64 hex> format. The legacy format cap_<64 hex> is accepted until 2027-05-03 (a dashboard banner flags legacy keys).
| Format | Regex | Example |
|---|---|---|
| Current format | cap_live_[0-9a-f]{64} | cap_live_a1b2c3d4e5f6...0123456789abcdef |
| Legacy format (deprecated 2027-05-03) | cap_[0-9a-f]{64} | cap_a1b2c3d4e5f6...0123456789abcdef |
Authorization header
All requests to /v1/* must include a Bearer header. No querystring or cookie fallback.
Authorization: Bearer cap_live_<your-key>Missing header
No Authorization header in the request. Status: 401 missing_api_key.
Invalid key
Unknown key, malformed, or unrecognized hash. Generic status 401 invalid_api_key (so no part of the key leaks which is at fault).
Expired key
The key passed its expiration date. Status 401 expired_api_key. Generate a new key via the dashboard.
Revoked key
The key was explicitly revoked (admin action or roll). Status 401 revoked_api_key. The request_id lets our support find the revocation event.
Scopes and presets
A key holds scopes (technical permissions). For convenience, the UI offers 5 presets grouping scopes by use case.
| Preset | Use case | Included scopes |
|---|---|---|
| Lead capture | Push leads from an external funnel (Make, Zapier, code) | leads:capture |
| Read only | BI, reporting, external dashboards | *:read |
| Read & write | External CRM sync (HubSpot, Salesforce) | *:read*:writeleads:capture |
| Full integration | No-code platforms, native integrations | * |
| Custom | Minimal permissions, tailored selection | free selection |
Individual scopes
contacts:read— Read contactscontacts:write— Create/update contactspipeline:read— Read pipelinepipeline:write— Update pipelineconversations:read— Read conversationsbookings:read— Read appointmentsbookings:write— Create/update appointmentsquotes:read— Read quotesquotes:write— Create/update quotestags:read— Read tagstags:write— Create/update tagsautomations:read— Read automationsautomations:trigger— Trigger automationsemail:send— Send emailemail:read— Read email conversationswebhooks:manage— Manage webhooksleads:capture— Capture external leads (CASL gated)events:ingest— Push inbound eventscampaigns:launch— Launch SMS campaigns (two-step confirmation)
CASL / Law 25 terms
The leads:capture scope is gated behind an attestation you accept when creating the key. This attestation formally commits you: every lead pushed via this endpoint has given explicit consent to receive commercial SMS messages. Capturia keeps a timestamped record (IP, browser, version).
Plan and features
Every request is also validated against the account's plan. If access is not included in your plan, the request is rejected with 403 feature_not_available — even if the key is valid and holds the required scope. The public API and the AI assistant connector are two distinct accesses, each validated against its own plan feature (the error's details.feature field names the missing one). The rejection comes from the plan, not the key: generating a new key or changing its scopes won't help. Contact your Capturia advisor to upgrade your plan.
Brute force and invalid keys
10 consecutive attempts with an invalid key from the same IP in 5 minutes → IP block for 5 minutes (429 too_many_attempts with Retry-After: 300). This policy protects keys against enumeration.
Security best practices
Never in the frontend. The API is server-to-server. A key exposed in a browser is an immediate leak.
Store as an environment variable (never committed to the repo).
One key per integration — don't use the same key for Zapier and your custom code. If a key leaks, you can revoke one integration without breaking others.
Regular rotation — use the Roll flow to renew without interruption (12h overlap).
No public CORS — you cannot call the API from a browser, this is intentional.