Delegated access to Zev products
Errors
Every delegated-access error carries a machine reason. Branch on it: reconfirm, reconnect, respect the user's choice, contact ZevAuth support, fix the integration, or retry later.
Every delegated-access error carries a reason, a stable machine word from one vocabulary:
- In a JSON body (token, revoke, authorize-url):
reasonand the same value aserror_reason, next toerroranderror_description. - On a redirect to your callback:
error_reason, next toerror,error_descriptionandstate.
error and error_description keep their usual meaning. New reasons may be
added; treat one you do not know by its error. Most support questions are
answered on Common scenarios.
What to do, by reason
| Do this | Reasons |
|---|---|
Reconfirm: authorize with prompt=reconfirm | high_risk_expired |
| Reconnect: send the user through authorize again | grant_revoked, refresh_reused, refresh_revoked, refresh_expired, refresh_invalid, code_invalid, code_used, code_expired, no_scopes, test_grant_expired |
| Respect the user’s choice: do not retry automatically | user_denied, account_mismatch, account_unavailable, not_a_test_member |
| Contact ZevAuth support; do not retry | unknown_partner, approval_pending, approval_suspended, app_suspended, partner_suspended, tenant_suspended, tenant_unverified, grant_suspended, scope_not_approved, high_risk_scope_not_approved, scope_not_grantable, scope_suspended, test_apps_not_allowed |
| Fix your integration | missing_param, redirect_uri_mismatch, unsupported_response_type, missing_state, invalid_state, missing_pkce, pkce_method_unsupported, invalid_pkce_challenge, pkce_mismatch, redirect_mismatch, client_mismatch, invalid_prompt, invalid_login_hint, scope_missing, scope_unknown, scope_not_for_test_apps, tenant_not_live, test_grant_limit, grant_not_found, invalid_request |
| Retry later, with backoff | rate_limited, product_unavailable, server_error |
A few deserve a sentence:
account_mismatch: you sent alogin_hint, and the user did not continue with that ZevID account, or a connection came back for another account and we revoked it. Tell the user to continue with the ZevID account they use with you. Never attach the connection to a different user. See The flow.not_a_test_member: someone outside your team tried your test environment. See Test environments.test_grant_expired: a test connection reached the end of its life. Reconnect to keep testing.test_grant_limit: your test environment already has 25 connections. Disconnect one, or wait for one to end.client_mismatch: a code or refresh token from your test environment was used with your live key, or the reverse. They never cross.
Authorize
Until we know the redirect_uri is yours, there is nowhere safe to send the
user. So two cases show a page; everything else redirects back to your
callback:
https://app.example.com/zev/callback
?error=invalid_scope
&error_description=The+permission+zevcloud.services.read+is+paused+for+this+app.
&error_reason=scope_suspended
&state=...
Check state before acting on an error, exactly as you do on success.
| Shown as a page | What to do |
|---|---|
resource or redirect_uri missing | Fix the link your app builds. |
redirect_uri not registered for this product | Register it exactly in the console under Delegated access. |
A missing or invalid key is refused before either, with a JSON 401.
Token and revoke
Errors follow RFC 6749, with the HTTP status:
{
"error": "invalid_grant",
"error_description": "The user's confirmation for this connection's high-risk permissions expired. Send the user through authorize with prompt=reconfirm.",
"reason": "high_risk_expired"
}
| Status | error | Usual reasons |
|---|---|---|
| 400 | invalid_request | A required field is missing. |
| 400 | unsupported_grant_type | grant_type is authorization_code or refresh_token. |
| 400 | invalid_grant | See the table above. |
| 401 | Missing, invalid or revoked API key. Token and revoke need your secret key. | |
| 403 | A configuration problem on ZevAuth’s side, not yours. Retry later; contact support if it persists. | |
| 404 | grant_not_found | Revoke only: the connection is not yours, or the id is wrong. |
| 429 | rate_limited | Wait for Retry-After seconds. See Rate limits. |
| 503 | temporarily_unavailable | ZevID could not be reached. Retry with backoff. |
Calls to the product
Each product defines its own errors, and its guide is the source of truth for
them. For ZevCloud (for example grant_expired, team_suspended,
github_access_required, project_limit_reached), see
ZevCloud’s error table.
ZevCloud’s grant_expired is the same ending we report as
test_grant_expired. Two matter for every partner:
| Status | Code | What to do |
|---|---|---|
| 403 | high_risk_confirmation_required | Send the user through prompt=reconfirm. |
| 403 | scope_paused | The permission is paused. Do not retry. |
| 401 | The access token is expired, stale or revoked. Refresh once; if that fails with invalid_grant, branch on its reason. |
Updated at, Wednesday, October 21, 2026