Errors
Most LogirAI endpoints return JSON with a success flag. Carrier-facing webhooks use carrier-specific envelopes — those exceptions are called out at the end of this page.
Standard error envelope
{
"success": false,
"error": "Validation failed",
"details": {
"consignee_rut": ["format invalid"],
"weight_kg": ["must be > 0"]
}
}| Field | Type | Notes |
|---|---|---|
success | false | Always present on errors. |
error | string | Machine code in snake_case. This is the stable contract — branch on it. |
details | object | Field-level errors when applicable. Keys match request fields. |
| extras | varies | Some errors include extra context, e.g. country on unsupported_country. |
Stable contract
The error field is a snake_case machine code intended for branching, not a human message to render verbatim. A few newer endpoints (e.g. inbound-batches) also include an upper-case code field — when present it duplicates error semantically. Branch on error for portability.
HTTP status codes
| Status | Meaning | Typical causes |
|---|---|---|
200 OK | Success (or carrier-acked failure for webhooks). | — |
201 Created | Resource created. | Manifest uploaded, shipment created. |
400 Bad Request | Validation failure. | Missing required fields, malformed UUID, schema mismatch. |
401 Unauthorized | Missing or invalid credentials. | Wrong or missing Authorization: Bearer <api_password>. See Authentication. |
403 Forbidden | Authenticated but not allowed. | Endpoint not enabled for your company's country (see unsupported_country). |
404 Not Found | Resource not visible to caller. | Guide ID does not exist or is filtered out by scope. |
409 Conflict | State machine violation. | Trying to advance a guide past a terminal status, duplicate manifest upload. |
422 Unprocessable Entity | Semantic validation failure: the rows are well-formed but wrong for this client. | Cainiao identifiers missing on a Cainiao manifest, or present on someone else's. Atrex XML response referencing HAWBs not in the manifest. |
429 Too Many Requests | Rate limit hit. | See Rate Limits. |
500 Internal Server Error | Bug or unhandled upstream failure. Logged with a request_id. | — |
503 Service Unavailable | Upstream dependency down. | South Post, iFlow, or Ocasa unreachable on proxy endpoints. |
Validation errors
Validation errors return 400 { error: "validation_failed", details: { ... } }. The details object is keyed by field name and each field maps to an array of messages.
{
"success": false,
"error": "validation_failed",
"details": {
"consignee_rut": ["format invalid"],
"fob_usd": ["must be > 0"]
}
}Common error codes
These are the error values you'll most likely see. The list is non-exhaustive — new codes may be added in minor releases. Branch on the codes you care about and treat unknowns as a generic failure.
Auth & access
error | HTTP | Where |
|---|---|---|
missing_api_key | 401 | Public endpoints when Authorization is absent or malformed. |
invalid_api_key | 401 | Token does not match any known companies.api_password. |
missing_token | 401 | JWT-protected endpoints with no Bearer token. |
forbidden | 403 | Authenticated but the role / scope cannot reach the resource. |
forbidden_country | 403 | Operator's country scope does not include this resource. |
unsupported_country | 403 | Your company has no country served by this endpoint (none of your allowed_countries is supported here). |
country_not_allowed | 403 | The country derived from the manifest destination is not in your allowed_countries. Echoes the derived country. Ask LogirAI ops to widen your allowlist. |
client_code_not_allowed | 403 | You sent client_code from a client token. Only a courier token may post on behalf of a client. |
client_not_resolved | 403 | client_code matches no active client company. Echoes the code you sent. |
Validation & input
error | HTTP | Where |
|---|---|---|
validation_failed | 400 | Generic schema/zod failure. details carries the per-field errors. On JSON pre-alerts this is also where a bad flight_number (a carrier name instead of a number) or a scheduled_arrival before its departure land. |
manifest_validation_failed | 400 | Row gate on a JSON pre-alert: at least one guide row is incomplete or fails its country's rules. All-or-nothing — nothing was created. invalid_rows[] lists every problem so you can fix them in one pass. |
cainiao_fields_missing | 422 | A Cainiao / AliExpress manifest without extra_data.cainiao_cop_no + cainiao_waybill on every row. |
cainiao_fields_not_allowed | 422 | cainiao_* identifiers on a manifest that does not belong to a Cainiao / AliExpress client — usually a mis-routed integration. |
company_is_courier | 400 | A courier token with no client_code, so no client company owns the manifest. |
tracking_prefix_missing | 400 | The owning company has no tracking prefix configured. Contact LogirAI ops. |
invalid_body | 400 | Body could not be parsed as JSON or violates top-level shape. |
invalid_query | 400 | Query string parameters failed validation. |
unsupported_transport_mode | 400 | transport_mode is not one of air / ground (sea not yet implemented). |
destination_unresolved | 400 | air with an unmapped destination_airport, or ground with no destination_country. The server cannot derive the country. |
no_parser_for_format | 400 | Multipart upload whose country has no onboarded parser yet (PE/AR formats are added per client). Use the JSON endpoint meanwhile. |
manifest_file_required | 400 | Multipart upload arrived without manifest_file. |
excel_parse_error | 400 | Excel manifest unreadable — bad format, encrypted, or corrupted. |
mawb_not_found_in_file | 400 | Excel doesn't contain a recognizable MAWB. |
no_rows_parsed | 400 | Manifest file has no parseable guide rows. |
invalid_document / invalid_document_type | 400 | CUIT/RUT/document number failed validation. |
schema_mismatch | 400 | Carrier webhook payload does not match the expected envelope. |
Domain & state
error | HTTP | Where |
|---|---|---|
mawb_already_exists | 409 | Same MAWB has already been ingested for this company. The response includes the existing manifest_id. |
not_found | 404 | The MAWB or tracking_code is unknown or doesn't belong to your company. |
country_mismatch | 409 | Resource belongs to a different country than the request claims. |
Internal & upstream
error | HTTP | Where |
|---|---|---|
internal_error / internal_server_error | 500 | Unhandled failure — escalate with the response timestamp. |
unavailable / upstream_unavailable | 503 | An upstream dependency is unreachable. Retry with backoff. |
unexpected_payload | 500 | Internal invariant broke. |
Diagnosing failures
When opening a support ticket, include:
- The full response body (status + JSON envelope).
- The request timestamp (UTC).
- For webhook deliveries: the
X-Logir-Delivery-Idheader value (theevt_*ID).
LogirAI ops can correlate these against server logs.
Retrying safely
| Operation | Retry-safe? | Notes |
|---|---|---|
POST /api/public/pre-alerts/v1/upload | No | Duplicate uploads with the same MAWB return mawb_already_exists (409) along with the existing manifest_id. Confirm the prior call succeeded before retrying. |
GET /api/public/pre-alerts/v1/* | Yes | All read endpoints are safe to retry. |
For non-idempotent writes, use the response (or a follow-up GET) to confirm state before retrying. Exponential backoff with jitter is recommended starting at 500 ms.