>_ DOCS / REFERENCE
ERROR
CODES.
Every P402 error response includes a machine-readable code field. Use it in your error handler to distinguish billing errors from provider failures.
Response Format
// All P402 error responses follow this structure:
{
"error": {
"code": "SESSION_BUDGET_EXCEEDED", // Machine-readable constant
"message": "Human-readable description",
"request_id": "req_01jx...", // Use this when contacting support
// Optional context fields:
"session_remaining_usd": 0.00,
"retry_after": 5, // Seconds (rate limit errors)
"details": { ... } // Validation errors
}
}Auth
UNAUTHORIZED
401
Missing or invalid API key.
Provide a valid Bearer token in the Authorization header.
FORBIDDEN
403
Valid key but insufficient permissions.
Check key scopes or upgrade your plan.
API_KEY_REVOKED
401
The API key has been revoked.
Generate a new key in Dashboard → Settings → API Keys.
Billing Guard
RATE_LIMIT_EXCEEDED
429
Too many requests per minute.
Respect the Retry-After header. Implement exponential backoff.
DAILY_SPEND_LIMIT_EXCEEDED
402
Daily spend cap reached.
Wait for daily reset (00:00 UTC) or raise your cap in billing settings.
CONCURRENCY_LIMIT_EXCEEDED
429
Too many simultaneous in-flight requests.
Queue requests client-side using a semaphore.
ANOMALY_DETECTED
402
Spend velocity anomaly detected by Sentinel AI.
Review the anomaly in Dashboard → Intelligence and resume manually.
REQUEST_COST_EXCEEDED
402
Single request cost exceeds per-request cap.
Reduce prompt length or set a higher max_cost_usd.
SESSION_BUDGET_EXCEEDED
402
Session has no remaining budget.
Fund the session (POST /sessions/:id/fund) or create a new one.
BUDGET_RESERVATION_FAILED
402
Concurrent requests exhausted session budget atomically.
Fund the session or retry after a short backoff.
Sessions
SESSION_NOT_FOUND
404
Session ID does not exist or belongs to another tenant.
Verify the session ID. Check it belongs to your account.
SESSION_EXPIRED
410
Session TTL has elapsed.
Create a new session. Expired sessions cannot be reactivated.
SESSION_CLOSED
410
Session was explicitly closed.
Create a new session.
Routing
NO_PROVIDER_AVAILABLE
503
No healthy provider found for the request.
Check /api/health. Retry after backoff.
PROVIDER_TIMEOUT
504
Selected provider did not respond in time.
Retry. P402 auto-retries once on timeout.
PROVIDER_ERROR
502
Upstream provider returned an error.
Retry. If persistent, the provider may be degraded.
MODEL_NOT_FOUND
404
Requested model does not exist or is unavailable.
Use GET /api/v2/models to list available models.
CONTEXT_TOO_LONG
422
Prompt exceeds the selected model's context window.
Reduce prompt length or specify a model with a larger context.
Input
INVALID_INPUT
400
Request body failed schema validation.
Check the error.details field for the specific field and constraint.
MISSING_FIELD
400
A required field is missing.
Add the missing field to the request body.
INVALID_MODE
400
mode must be cost | quality | speed | balanced.
Use a valid routing mode.
x402
INVALID_SIGNATURE
400
EIP-712 signature verification failed.
Check domain parameters, type hash, and nonce format.
REPLAY_DETECTED
400
The nonce has already been used.
Generate a fresh nonce (crypto.randomBytes(32)).
PAYMENT_EXPIRED
400
validBefore timestamp has passed.
Sign a new authorization with a future validBefore.
AMOUNT_MISMATCH
400
Authorization amount ≠ paymentRequirements.maxAmountRequired.
Ensure value in the authorization matches maxAmountRequired.
GAS_PRICE_TOO_HIGH
503
Base gas price exceeds configured safety limit.
Retry when gas normalises. P402 rejects settlement above 50 gwei.
AP2 Mandates
MANDATE_NOT_FOUND
404
Mandate ID not found.
Verify mandate ID and tenant ownership.
MANDATE_INACTIVE
403
Mandate status is not active.
Check mandate status — may be exhausted, expired, or revoked.
MANDATE_EXPIRED
403
Mandate valid_until has passed.
Issue a new mandate.
MANDATE_BUDGET_EXCEEDED
402
Amount would exceed mandate's max_amount_usd.
Issue a new mandate with a higher budget.
MANDATE_CATEGORY_DENIED
403
Request category not in mandate's allowed_categories.
Update the mandate constraints or issue a new mandate.
Internal
INTERNAL_ERROR
500
Unexpected server error.
Retry with exponential backoff. Contact support if persistent.
DATABASE_ERROR
503
Database temporarily unavailable.
Retry after backoff. Check status.p402.io.
Retry Guide
Error Type
Retry?
Strategy
4xx (client errors)
No
Fix the request. Retrying the same request will get the same error.
RATE_LIMIT_EXCEEDED (429)
Yes
Wait for Retry-After seconds, then retry.
PROVIDER_TIMEOUT (504)
Yes
Immediate retry once. P402 will select a different provider.
PROVIDER_ERROR (502)
Yes
Exponential backoff: 1s, 2s, 4s. P402 avoids degraded providers.
DATABASE_ERROR (503)
Yes
Exponential backoff. Check status.p402.io.
INTERNAL_ERROR (500)
Yes
Retry up to 3 times with backoff. Contact support if persistent.