API keys
In brief: Issuing, rotating, revoking Verify API keys. Sandbox vs live prefixes.
Every Verify API call is authenticated with a bearer API key. Same
key works for the dashboard's "send verification" form; under the
hood, the dashboard hits the same /v2/verify/* endpoints you'd
call directly.
Where to manage keys
/verify-app/api-keys in the dashboard.
The page shows two tabs:
- Sandbox: keys for the sandbox environment.
- Live: only visible after upgrading to live.
Issuing a key
- Click Issue API key.
- Give it a label (e.g. "Production checkout", "Staging", "Ops dashboard"). Labels are for your reference only; pick something you'll recognise later.
- Click Issue.
The dialog shows the full secret exactly once. It looks like:
sk_sandbox_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
Or for live:
sk_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
Copy it now and store it somewhere safe: a password manager, your deployment platform's secret store (Vercel, AWS Secrets Manager, GitHub Actions secrets, etc.). We do not store the secret in plaintext; we store a SHA-256 hash, so if you lose the secret there is no way to recover it. You'll have to issue a new key.
Key prefix vs full secret
After you close the dialog, the keys table shows only the prefix:
sk_sandbox_a1b2c3d4...
That's enough for you to identify which key is which. It's not enough to authenticate; the prefix is logged in audit trails and shown to your team, but the full secret never leaves your hands.
Using a key
Send it as a bearer token on every request:
Authorization: Bearer sk_sandbox_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
A typical call:
curl -X POST https://app.certivus.com/v2/verify/age \
-H "Authorization: Bearer sk_sandbox_..." \
-H "Content-Type: application/json" \
-d '{
"subject": {
"email": "test@example.com",
"first_name": "Alex",
"last_name": "Smith",
"dob": "1990-05-12"
},
"age_threshold": 18
}'
See Sending a verification for the full request / response shape.
Sandbox vs live keys
| Sandbox | Live | |
|---|---|---|
| Prefix | sk_sandbox_ | sk_live_ |
| Mode (auto-set on every check) | sandbox | live |
| Cost | Free | Per the rate card |
| Provider | Stub (canned results) | Certivus |
| Visible to | All team members | All team members |
A key created in sandbox cannot be "promoted" to live. After upgrade, you issue separate live keys. This is intentional: it prevents accidentally shipping a sandbox key to production.
Rotating a key
Best practice: rotate keys every 90 days, or immediately if you suspect leak (e.g. you spotted a key in a public Git commit).
To rotate:
- Issue a new key. Copy + store the secret.
- Roll it out: update your secret store, deploy, verify the new key works.
- Revoke the old key. From the keys table, click the menu → Revoke. Confirm in the dialog.
A revoked key returns INVALID_API_KEY on every subsequent call.
The revocation is immediate; there is no grace period.
Revoking a key
Same flow as rotation, just without issuing a replacement.
You'd revoke without rotating when:
- You decommission an integration that was using the key.
- You stop using a vendor / contractor who had access.
- You're cleaning up old keys you no longer recognise.
Revoked keys remain in the table (greyed out) for audit. They cannot be reactivated; issue a new key if you need that integration back.
Common errors
| Error | What it means | Fix |
|---|---|---|
MISSING_API_KEY | No Authorization header sent | Add Authorization: Bearer sk_… |
INVALID_API_KEY | Key not found or revoked | Check you copied the full secret. Re-issue if revoked. |
ACCOUNT_SUSPENDED | Account on hold (overdue billing, manual hold) | Contact support. |
QUOTA_EXCEEDED | Free-tier or plan quota hit | Upgrade plan or wait for monthly reset. |
KEY_MODE_MISMATCH | Sandbox key sent to live endpoint or vice versa | Use the right prefix (sk_sandbox_ for testing, sk_live_ for production). |
Security notes
- Never commit a key to Git. Use environment variables or a secret store.
- Never send a key from a browser. Front-end JavaScript means anyone with devtools can grab it. Always proxy through your own back-end.
- Don't share keys across customers. If you operate multiple brands / clients, issue separate keys per brand so revocation doesn't take everyone down.
- Watch the dashboard for unusual activity. If a key starts hitting the API from an unexpected source, revoke immediately.
Didn't find what you needed?
Contact support