The error envelope#
Every error has the same shape:
{ "ok": false, "error": "Token missing required scope: verify:write", "code": "forbidden_scope" }
Use code in your integration logic; error is a human-readable message that may change.
Error codes#
| HTTP | code | Meaning |
|---|---|---|
| 401 | unauthorized | Missing, invalid, expired or revoked token |
| 403 | forbidden_scope | The token lacks the required scope |
| 403 | forbidden | The token's role permissions or workspace profile deny the request (for example listing employees from an institution workspace) |
| 404 | not_found | The verification or resource does not exist — or belongs to another organization |
| 404 | student_not_found | POST /student-documents: no such student in the token's institution |
| 405 | method_not_allowed | Wrong HTTP method |
| 422 | invalid_request | Missing or invalid parameters, unsupported request field, unsupported target |
| 422 | invalid_type | Unsupported document_type |
| 422 | student_not_validated | The student must be validated before a document can be issued |
| 422 | unprocessable | A downstream service could not fulfil the request |
| 429 | rate_limited | Per-token rate limit exceeded |
Rate limits#
- 120 requests per 600 seconds, per token. The counter is fail-closed: if it cannot be evaluated, the request is refused.
- A
429response carriesRetry-After: 600. Back off for the indicated time before retrying.
Good practices#
- Cache
GET /settingsand directory listings; do not poll them on every user action. - Handle
401by asking the user to sign in again (add-ons) or by rotating the token (integrations). - Treat
404 not_foundon a public ID you did not issue as expected: the API never confirms other tenants' credentials.