Agent Decision Table
When you receive an error, branch on error.code first (it is stable and
machine-readable). Use this table to decide what to do next:
error.code | Retry? | Action |
|---|---|---|
platform_invalid_request | No | Fix the request body and re-send. The message includes the bad field. |
platform_invalid_api_key | No | The key is wrong, revoked, or expired. Mint a new one. |
platform_api_key_revoked | No | Get a new key. The old one cannot be reused. |
platform_api_key_expired | No | Get a new key. |
platform_forbidden | No | The key does not own the resource. |
email_verification_required | After verify | Resend verify email, have a human click it, then retry. Only hit at billing path; trial generation does not require verify. |
free_credits_exhausted | After top-up | Call POST /v1/platform/agent/billing/session, forward the URL to a human, retry once creditBalance > 0. |
payment_required | After payment | Either pay with USDC via x402 (X-Payment header on retry) or top up via the billing session URL. |
x402_payment_failed | Yes (with delay) | The on-chain payment may not have settled. Retry after 5–10 s. |
platform_workspace_suspended | No | Contact support. |
platform_workspace_not_found | No | Workspace does not exist. Check the API key or workspace ID. |
workspace_not_found | No | Billing guard could not find the workspace. Mint a fresh API key or contact support. |
platform_not_found | No | Resource does not exist or you don't own it. |
platform_conflict | No | Resolve the duplicate slug, duplicate email, or already-linked organization and retry with different input. |
platform_rate_limit_exceeded | Yes | Exponential backoff. See Rate Limiting. |
platform_credits_exhausted | After top-up | Pre-flight credit check failed. Use topUp.endpoint from the response or call POST /v1/platform/agent/billing/session. |
platform_insufficient_credits | After top-up | Legacy insufficient-credit code. Treat the same as platform_credits_exhausted. |
platform_internal_error | Yes | Retry with exponential backoff (start at 1 s, max 3 retries). |
Error Response Format
All platform API errors return a consistent JSON envelope:
{
"error": {
"code": "platform_invalid_request",
"message": "Validation failed: questionText is required",
"status": 422
}
}The error.code is a machine-readable identifier you can use in your error handling logic.
Validation failures usually return HTTP 422. Some malformed requests can
return HTTP 400 with the same platform_invalid_request code.
Error Codes
| Code | HTTP Status | Meaning |
|---|---|---|
platform_invalid_request | 400 or 422 | Invalid request body or parameters |
platform_invalid_api_key | 401 | Missing or invalid API key |
platform_api_key_revoked | 401 | API key has been revoked |
platform_api_key_expired | 401 | API key has expired |
platform_forbidden | 403 | API key doesn't have access to this resource |
email_verification_required | 403 | Workspace email is unverified and the call requires it (billing/payment path only). Trial generation works without verification. |
free_credits_exhausted | 403 | Free credits used up and no payment method registered |
payment_required | 402 | Credits exhausted; pay with USDC via x402 or register a payment method |
x402_payment_failed | 402 | USDC payment verification failed |
platform_workspace_suspended | 403 | Workspace is suspended |
platform_workspace_not_found | 404 | Workspace does not exist |
workspace_not_found | 403 | Workspace could not be resolved in the billing guard |
platform_not_found | 404 | Resource doesn't exist |
platform_conflict | 409 | Duplicate slug, duplicate email, already-linked organization, or another uniqueness conflict |
platform_rate_limit_exceeded | 429 | Rate limit exceeded |
platform_credits_exhausted | 402 | Insufficient credits at pre-flight generation check |
platform_insufficient_credits | 402 | Legacy insufficient-credit code |
platform_internal_error | 500 | Something went wrong on our end |
HTTP Status Codes
| Code | Meaning | When |
|---|---|---|
200 | OK | Request succeeded |
201 | Created | Resource created successfully |
400 | Bad Request | Invalid request body or parameters |
422 | Unprocessable Entity | Validation failed for a syntactically valid request |
401 | Unauthorized | Missing, invalid, revoked, or expired API key |
402 | Payment Required | Insufficient credits |
403 | Forbidden | Workspace suspended or access denied |
404 | Not Found | Resource doesn't exist |
409 | Conflict | Resource already exists (e.g. duplicate slug) |
429 | Too Many Requests | Rate limit exceeded |
500 | Internal Server Error | Something went wrong on our end |
Common Errors
Invalid API Key
{
"error": {
"code": "platform_invalid_api_key",
"message": "Invalid or missing API key",
"status": 401
}
}Check that your Authorization header uses the correct format: Bearer tf_platform_...
Workspace Suspended
{
"error": {
"code": "platform_workspace_suspended",
"message": "Workspace is suspended",
"status": 403
}
}Contact support to reactivate your workspace.
Email Verification Required
{
"error": {
"code": "email_verification_required",
"message": "Email verification is required before adding billing or paying with USDC. Check your inbox or call POST /v1/platform/agent/verify-email/resend.",
"status": 403
}
}This error is only returned at the billing path, after trial credits are exhausted and the agent attempts to top up via Stripe or USDC. Trial credits work without verification.
If the agent receives this error:
- Call
POST /v1/platform/agent/verify-email/resendto send a fresh verification link. - Have a human (the workspace owner) click the link in the email.
- Retry the original billing call.
See the Agent Onboarding guide for the full flow.
Free Credits Exhausted
{
"error": {
"code": "free_credits_exhausted",
"message": "Your free credits have been exhausted. Register a payment method or purchase additional credits to continue. Call POST /v1/platform/agent/billing/session to get started.",
"status": 403
}
}New workspaces receive $1.00 in free credits. Once exhausted, register a payment method via
POST /v1/platform/agent/billing/session and purchase additional credits to continue.
Payment Required (x402)
{
"error": {
"code": "payment_required",
"message": "Credits exhausted. Pay with USDC via x402 or register a payment method.",
"x402": {
"scheme": "exact",
"network": "eip155:8453",
"price": "$0.01",
"payTo": "0x...",
"description": "TutorFlow API request payment",
"mimeType": "application/json",
"resource": "POST /v1/platform/evaluations"
},
"billingSessionUrl": "POST /v1/platform/agent/billing/session",
"status": 402
}
}When you receive a 402 response, you have two options:
- Pay with USDC: Send USDC to the
payToaddress on the specified network, then retry with theX-Paymentheader. The current x402 requirement credits a$0.01deposit to the workspace. If the request costs more than the resulting balance, the retry can still fail withplatform_credits_exhausted. - Register a card: Call
POST /v1/platform/agent/billing/sessionto get a checkout URL for card-based payment.
Credits Exhausted
{
"error": {
"code": "platform_credits_exhausted",
"message": "Insufficient credits to start this request. Need 150 credits, have 45. Top up via POST /v1/platform/agent/billing/session, or use x402 deposit top-up if enabled.",
"creditBalance": 45,
"requiredCredits": 150,
"topUp": {
"endpoint": "POST /v1/platform/agent/billing/session",
"minimumUsd": 5,
"maximumUsd": 5000
},
"status": 402
}
}This is the normal pre-flight generation failure when the workspace balance cannot cover the estimated request cost. Top up, then retry the same request.
Rate Limit Exceeded
{
"error": {
"code": "platform_rate_limit_exceeded",
"message": "Rate limit exceeded",
"status": 429
}
}Wait and retry with exponential backoff. See Rate Limiting.
Best Practices
- Always check
error.codefor programmatic error handling. - Log
error.messagefor debugging. It may contain specific field-level details. - Implement retry logic with exponential backoff for
429and5xxerrors. - Do not blindly retry
4xxerrors. Branch byerror.code:402can be retried after top-up,email_verification_requiredafter verification, and429after backoff. Other4xxerrors usually require changing the request.