Errors
The API returns three different error shapes depending on which surface you hit. Parse defensively.
Integration endpoints
Anything you call with an API key returns a plain message:
{
"message": "API key is not authorized for this issuer"
}
| Status | Cause |
|---|---|
400 | request rejected — missing metadata.redirectUri, offer too large for by_value |
401 | missing key, malformed key, wrong secret, expired key |
403 | key valid but scoped to a different issuer, verifier or organization |
404 | issuer, verifier, profile or record not found; diagnostics disabled |
422 | schema validation failed, returned as a Zod error envelope |
Wallet protocol endpoints
The token, credential, nonce and PAR endpoints follow OAuth 2.0 error conventions:
{
"error": "invalid_proof",
"error_description": "Proof JWT signature did not verify"
}
error | Typical status |
|---|---|
invalid_request, invalid_credential_request, invalid_encryption_parameters | 400 |
unknown_credential_configuration, unknown_credential_identifier | 400 |
unsupported_credential_format, unsupported_credential_type, unsupported_grant_type | 400 |
invalid_client, invalid_grant | 400 – 401 |
invalid_token | 401 or 403 |
invalid_proof, invalid_nonce | 403 |
These are returned to the wallet, not to you — they surface in the diagnostics timeline.
Unexpected failures
An unhandled server error returns a wrapped body, and in production the message is always generic:
{
"error": {
"code": "INTERNAL_ERROR",
"message": "Internal server error",
"timestamp": "2026-08-11T09:00:00.000Z",
"requestId": "01J…"
}
}
INTERNAL_ERROR is the only code in this shape — quote requestId when you report it.