Error Handling

Understand error responses and how to handle them.

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.codeRetry?Action
platform_invalid_requestNoFix the request body and re-send. The message includes the bad field.
platform_invalid_api_keyNoThe key is wrong, revoked, or expired. Mint a new one.
platform_api_key_revokedNoGet a new key. The old one cannot be reused.
platform_api_key_expiredNoGet a new key.
platform_forbiddenNoThe key does not own the resource.
email_verification_requiredAfter verifyResend verify email, have a human click it, then retry. Only hit at billing path; trial generation does not require verify.
free_credits_exhaustedAfter top-upCall POST /v1/platform/agent/billing/session, forward the URL to a human, retry once creditBalance > 0.
payment_requiredAfter paymentEither pay with USDC via x402 (X-Payment header on retry) or top up via the billing session URL.
x402_payment_failedYes (with delay)The on-chain payment may not have settled. Retry after 5–10 s.
platform_workspace_suspendedNoContact support.
platform_workspace_not_foundNoWorkspace does not exist. Check the API key or workspace ID.
workspace_not_foundNoBilling guard could not find the workspace. Mint a fresh API key or contact support.
platform_not_foundNoResource does not exist or you don't own it.
platform_conflictNoResolve the duplicate slug, duplicate email, or already-linked organization and retry with different input.
platform_rate_limit_exceededYesExponential backoff. See Rate Limiting.
platform_credits_exhaustedAfter top-upPre-flight credit check failed. Use topUp.endpoint from the response or call POST /v1/platform/agent/billing/session.
platform_insufficient_creditsAfter top-upLegacy insufficient-credit code. Treat the same as platform_credits_exhausted.
platform_internal_errorYesRetry 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

CodeHTTP StatusMeaning
platform_invalid_request400 or 422Invalid request body or parameters
platform_invalid_api_key401Missing or invalid API key
platform_api_key_revoked401API key has been revoked
platform_api_key_expired401API key has expired
platform_forbidden403API key doesn't have access to this resource
email_verification_required403Workspace email is unverified and the call requires it (billing/payment path only). Trial generation works without verification.
free_credits_exhausted403Free credits used up and no payment method registered
payment_required402Credits exhausted; pay with USDC via x402 or register a payment method
x402_payment_failed402USDC payment verification failed
platform_workspace_suspended403Workspace is suspended
platform_workspace_not_found404Workspace does not exist
workspace_not_found403Workspace could not be resolved in the billing guard
platform_not_found404Resource doesn't exist
platform_conflict409Duplicate slug, duplicate email, already-linked organization, or another uniqueness conflict
platform_rate_limit_exceeded429Rate limit exceeded
platform_credits_exhausted402Insufficient credits at pre-flight generation check
platform_insufficient_credits402Legacy insufficient-credit code
platform_internal_error500Something went wrong on our end

HTTP Status Codes

CodeMeaningWhen
200OKRequest succeeded
201CreatedResource created successfully
400Bad RequestInvalid request body or parameters
422Unprocessable EntityValidation failed for a syntactically valid request
401UnauthorizedMissing, invalid, revoked, or expired API key
402Payment RequiredInsufficient credits
403ForbiddenWorkspace suspended or access denied
404Not FoundResource doesn't exist
409ConflictResource already exists (e.g. duplicate slug)
429Too Many RequestsRate limit exceeded
500Internal Server ErrorSomething 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:

  1. Call POST /v1/platform/agent/verify-email/resend to send a fresh verification link.
  2. Have a human (the workspace owner) click the link in the email.
  3. 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:

  1. Pay with USDC: Send USDC to the payTo address on the specified network, then retry with the X-Payment header. The current x402 requirement credits a $0.01 deposit to the workspace. If the request costs more than the resulting balance, the retry can still fail with platform_credits_exhausted.
  2. Register a card: Call POST /v1/platform/agent/billing/session to 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.code for programmatic error handling.
  • Log error.message for debugging. It may contain specific field-level details.
  • Implement retry logic with exponential backoff for 429 and 5xx errors.
  • Do not blindly retry 4xx errors. Branch by error.code: 402 can be retried after top-up, email_verification_required after verification, and 429 after backoff. Other 4xx errors usually require changing the request.