Skip to content
JARAI Developers

Error Handling

The JARAI Partner API uses a consistent error envelope across all endpoints. This guide covers the envelope format, all error codes, retry strategies, and how to use correlation IDs for debugging.

Error Envelope

All non-2xx responses return a JSON body with this structure:

{
  "error": "ERROR_CODE",
  "message": "Human-readable description of the error.",
  "retryAfterSeconds": 42
}
FieldTypeDescription
errorstringMachine-readable error code (e.g. RATE_LIMIT_EXCEEDED).
messagestringHuman-readable explanation.
retryAfterSecondsinteger or nullPresent on 429 responses. Number of seconds to wait before retrying.

Correlation IDs

Every API response includes an X-Correlation-Id header. Include this value when contacting JARAI support — it allows the operations team to trace your request through the system.

# The correlation ID is in the response headers
curl -v https://apim-jarai-prd.azure-api.net/v1/accounts \
-H "X-API-Key: jarai_your_api_key_here" 2>&1 | grep X-Correlation-Id

Global Errors

These errors can occur on any endpoint:

StatusError CodeDescription
401UNAUTHORIZEDAPI key is missing, invalid, or revoked.
403PARTNER_NOT_ACTIVEPartner account is not in Active status.
403PERMISSION_DENIEDAPI key lacks the required scope for this endpoint.
413Request body exceeds the size limit.
429RATE_LIMIT_EXCEEDEDRequest rate or daily quota exceeded. Includes retryAfterSeconds.
500INTERNAL_ERRORUnexpected server error.
503SERVICE_UNAVAILABLESystem is temporarily unavailable for maintenance.

Production Trigger Errors

POST /v1/accounts/{accountId}/productions

StatusError CodeDescriptionRetry?
400INVALID_REQUESTMissing required field or malformed JSON body.No — fix request
403INSUFFICIENT_SCOPEaccountId not in caller’s permitted accounts.No
403ACCOUNT_NOT_ACTIVEAccount status is not Active or Pilot.No
409BUDGET_GATE_1_FAILEDAccount monthly AI spend ceiling exceeded.No — wait for next month or top up
409BUDGET_GATE_2_FAILEDCustomer monthly AI spend ceiling exceeded.No — wait for next month
409CONCURRENCY_LIMIT_REACHEDAccount or customer concurrent production ceiling reached.Yes — wait for in-flight productions to finish
409SENSITIVITY_RULE_SUPPRESSEDContent sensitivity rule suppressed this topic.No — adjust topic
422SUBJECT_OVERRIDE_MISSINGContent theme title template requires a subject override.No — include subject

Production Status Errors

GET /v1/productions/{productionId}, GET /v1/accounts/{accountId}/productions

StatusError CodeDescription
404NOT_FOUNDProduction does not exist or is outside your permitted accounts.

Cancellation Errors

DELETE /v1/productions/{productionId}

StatusError CodeDescription
403CANCELLATION_NOT_PERMITTEDCannot cancel non-API-triggered productions.
404NOT_FOUNDProduction does not exist or is outside your permitted accounts.
409ALREADY_TERMINALProduction is already Published or Failed.
409CANCEL_IN_PROGRESSAnother cancel request is already processing. Retry after a few seconds.

Deliverable Errors

GET /v1/productions/{productionId}/deliverables

StatusError CodeDescription
404NOT_FOUNDProduction does not exist or is outside your permitted accounts.

Performance Errors

GET /v1/productions/{productionId}/performance

StatusError CodeDescription
404NOT_FOUNDProduction does not exist or is outside your permitted accounts.
409PERFORMANCE_DATA_NOT_READYProduction not yet Published; no performance data available.

Account Query Errors

GET /v1/accounts, GET /v1/accounts/{accountId}, GET /v1/accounts/{accountId}/avatars, GET /v1/accounts/{accountId}/platforms

StatusError CodeDescription
404NOT_FOUNDAccount does not exist or is outside your permitted accounts.

Webhook Management Errors

POST/GET/DELETE /v1/webhooks*

StatusError CodeDescription
400INVALID_REQUESTeventTypes absent or empty.
404NOT_FOUNDSubscription does not exist or belongs to a different partner.
409SUBSCRIPTION_NOT_ACTIVECannot ping a non-Active subscription.
409SUBSCRIPTION_NOT_FAILEDCannot reinstate a subscription that is not in Failed status.
422HTTPS_REQUIREDEndpoint URL scheme is not HTTPS.
422INVALID_ENDPOINT_URLEndpoint URL resolves to a private/localhost address or is malformed.
422INVALID_EVENT_TYPEEvent type not in the valid vocabulary.

Registration Errors

POST /v1/partners/register, GET /v1/partners/verify

StatusError CodeDescription
400INVALID_REQUESTMissing required field or invalid email format.
400TOKEN_MISSINGVerification token query parameter absent.
400TOKEN_INVALIDJWT signature invalid or malformed.
400TOKEN_EXPIREDJWT exceeded 24-hour validity window.
409EMAIL_ALREADY_REGISTEREDA partner with this email already exists.
409ALREADY_VERIFIEDPartner is already Active.
429RATE_LIMIT_EXCEEDEDMore than 5 registration attempts from this IP in 10 minutes. retryAfterSeconds: 600.

Key Rotation Errors

POST /v1/partners/keys/rotate

StatusError CodeDescription
403SELF_SERVE_ROTATION_DISABLEDSelf-serve key rotation is disabled for your partner account.
409NO_ACTIVE_KEYNo active API key exists for your partner.
409ROTATION_IN_PROGRESSA rotation is already in progress. Retry in a few seconds.

Request History Errors

GET /v1/partner/requests

StatusError CodeDescription
400INVALID_LIMITlimit parameter outside 1–100 range.
422DATE_RANGE_TOO_WIDEfrom/to window exceeds 30 days.
422INVALID_DATE_FORMATfrom or to is not a valid ISO 8601 datetime.
422INVALID_STATUS_CLASSstatus parameter is not 2, 4, or 5.

Usage Analytics Errors

GET /v1/partner/usage

StatusError CodeDescription
422INVALID_MONTHS_PARAMmonths parameter outside 1–12 range.

Retry Strategy

When you receive a retryable error, follow these guidelines:

  1. 429 responses: always respect retryAfterSeconds. Do not retry before the indicated time.
  2. 5xx responses: retry once after 5 seconds with exponential backoff. If the second attempt also fails, wait 30 seconds before a third attempt.
  3. 409 CONCURRENCY_LIMIT_REACHED: wait for an in-flight production to complete (poll or use webhooks), then retry.
  4. 409 CANCEL_IN_PROGRESS / ROTATION_IN_PROGRESS: retry after 5–10 seconds.

Do not retry 400, 403, or 422 errors — these indicate a client-side issue that requires a code or configuration change.

Next Steps