Reten Docs

Error Handling

Error format, status codes, and solutions for the integration API.

When a request to the integration API fails, the response includes a JSON body with information about the error.

Error format

{
  "statusCode": 401,
  "error": "Unauthorized",
  "message": "Invalid or revoked API key"
}
FieldTypeDescription
statusCodenumberHTTP status code
errorstringError name
messagestringDetailed description of the problem
codestringPresent only on errors a client has to branch on. It is a stable UPPER_SNAKE value: branch on code, never on the text of message, which may change. Today the only one is DEFAULT_ROOT_CONFIRMATION_REQUIRED (see Publish Config). It is not the Code column of the table below, which is the HTTP error name

Error codes

StatusCodeDescriptionSolution
401UnauthorizedInvalid, revoked or expired API key, or its owner is inactiveCheck that the key is copied exactly and is still active in Settings → API Keys; if it was revoked or expired, create a new one
403ForbiddenThe key does not have the required permission, or a project key names another project in x-project-idConfirm that the key has the necessary permissions: activity:view for queries, activity-result:submit for submitting results, commerce:batch-upsert / operator:batch-upsert / route:batch-upsert for the batch upserts. With a project key, omit x-project-id or send the key's own project
400Bad RequestValidation error in the request body, missing x-api-key header (Missing required header: x-tenant-id), an x-project-id that is not a valid UUID, or a result without activity_id submitted without a projectCheck that the body complies with the documented format: data types and required fields. If you send x-project-id, use a project UUID; with a tenant key or a user token, send it to submit a result without activity_id
404Not FoundResource not found, or the project named in x-project-id does not existConfirm that the activity_id or other identifier exists in the tenant, and that the project in x-project-id belongs to the key's tenant
422Unprocessable EntityThe body is valid but cannot be processed: the activity does not accept a result in its current state or day, or the result type is not active or needs data that is missingVerify that the activity is in a state that accepts a result (READY, DISPATCHED, RETRYING or COMPLETED) and that its day has not been closed by the end-of-day cutoff; use an active result code and send future_scheduled_at (today or later) when its type requires it
429Too Many RequestsToo many requests in a short timeWait before retrying, and spread the requests over time

Common errors and diagnostics

401 — Unrecognized key

{
  "statusCode": 401,
  "error": "Unauthorized",
  "message": "Invalid or revoked API key"
}

Possible causes:

  • The key was revoked from the administration panel
  • The key has an expired expiration date
  • Formatting error (spaces, extra characters)
  • The key's owner is inactive — in that case the message is API key owner is inactive or not found
  • The API could not validate the key at that moment — in that case the message is API key validation failed; retry the request

A request that carries no key does not receive this 401. The API only reads x-api-key as a key when its value starts with rtn_sk_; any other value counts as no key. Without a key and without x-tenant-id, the API responds 400 Bad Request with Missing required header: x-tenant-id; with x-tenant-id but no credentials, it responds 401.

Project errors

On GET /api/integration/activities/tasks and POST /api/integration/activity-results/tasks, x-project-id is optional: both are project-optional endpoints. When the header is sent, the API checks it before the permissions and the body. The 400 of a result without activity_id is not part of that check: it comes after the body is validated, so an error in the body is reported first. How each key chooses its project is explained in Key scope.

StatusWhenmessage
400A result without activity_id is submitted without a project: a tenant key or a user token that does not send x-project-idFalta el header obligatorio x-project-id: un resultado sin activity_id necesita proyecto.
400x-project-id is not a valid UUID (tenant key or user token)El header x-project-id debe ser un UUID válido.
403A project key sends an x-project-id that is not its own projectLa API key pertenece a un proyecto distinto del que declara el header x-project-id.
404The project in x-project-id does not exist or belongs to another tenantEl proyecto no existe.

403 — Insufficient permission

{
  "statusCode": 403,
  "error": "Forbidden",
  "message": "Required permissions: activity:view"
}

Possible causes:

  • The key does not include the required permission for the endpoint
  • Ask the key's owner to edit its permissions with PUT /api/api-keys/:id/permissions or from Settings → API Keys

400 — Validation error

The API responds 400 when the body does not match the documented format.

Possible causes:

  • Missing required fields: occurred_at and task_result.result always; commerce_external_id only when activity_id is absent (standalone executions)
  • Invalid date format (must be ISO 8601)
  • activity_id is not a valid UUID
  • Fields that are not part of the documented body

422 — Non-processable state

{
  "statusCode": 422,
  "error": "Unprocessable Entity",
  "message": "La actividad no está en un estado válido para registrar resultado."
}

Possible causes:

  • The linked activity is not in a state that accepts a result. READY, DISPATCHED and RETRYING accept one; COMPLETED also does, and submitting again updates the activity's existing result; CANCELED and FAILED do not — message above
  • The activity's execution date has already crossed the end-of-day cutoff — La actividad corresponde a un día ya cerrado y no admite registrar resultado. Past that cutoff, an auto-close runs and may register the result (as NOT_EXECUTED). Standalone executions (STANDALONE, without activity_id) are exempt from this rule and the previous one
  • The result code in task_result.result does not exist or is not active — El tipo de resultado seleccionado no está activo. See List Configurations to get valid codes
  • The result type requires task_result.future_scheduled_at and it was not sent — Este tipo de resultado requiere una fecha comprometida.
  • task_result.future_scheduled_at falls on a day before today, in the tenant's time zone — La fecha programada no puede ser en el pasado.