Errors

All endpoints return errors as RFC 7807 application/problem+json:

{
  "type": "https://docs.flexgalaxy.ai/dev/wes-contract/errors.html#cross-warehouse-credential",
  "title": "Credential not authorized for this warehouse",
  "status": 403,
  "detail": "Credential WH-Tokyo-01/AcmeWES attempted to post for WH-Tokyo-02.",
  "instance": "/wes/v1/realtime/movements",
  "trace_id": "01J7Y6K1NQ3W2C0X4V0R5T6E7N"
}

trace_id is propagated end-to-end via the W3C traceparent header. Include it in every support request.

Status table

Status

Meaning

Partner action

400 Bad Request

Malformed request — invalid JSON, missing required field, unknown enum value.

Fix the request shape. Do not retry as-is.

401 Unauthorized

Missing or invalid credential — cert not in registry, expired API key, bad HMAC signature.

Check certificate, key rotation, secret rotation, environment config.

403 Forbidden

Credential valid but not authorized for the resource or warehouse.

Check partner-registry warehouse scoping; never bypass with a more-privileged credential.

404 Not Found

The referenced cursor / job / window / mapping does not exist.

Verify the identifier; treat as terminal — do not retry.

409 Conflict

State conflict — e.g. a fresh confirmation for an already-RECONCILED window, or an ack for a cursor the planner has already advanced past.

Inspect the referenced state. For confirmation conflicts, route through supervisor discrepancy resolution.

422 Unprocessable Entity

Schema-valid but business-invalid — unknown SKU, wrong UoM, unknown location, malformed document_ref.

Fix the underlying data, not the request shape.

429 Too Many Requests

Rate limited.

Honor Retry-After. Back off exponentially.

500 Internal Server Error

Platform-side failure.

Retry with exponential backoff. Open a support ticket including trace_id if persistent.

503 Service Unavailable

Receiving side is in maintenance or temporarily offline.

Retry with exponential backoff. Honor Retry-After if present.

Idempotency notes on errors

  • A 200 OK with replay: true is not an error — it is the expected response to a retry of an already-applied request. See Idempotency and ordering.

  • A 409 for a window key collision is also not the same as a replay. Two different correlation_ids for the same window key is a planner-side rule violation; the supervisor workflow exists for this case.

  • A 422 on a movement does not roll back other items in the same batch. Each item’s status is reported individually in the response.

Batch responses

Endpoints that accept arrays return a per-item result. A batch of 100 movements with one bad SKU returns 200 OK with 99 entries marked ACCEPTED and one marked REJECTED. The HTTP status is 200 because the batch was processed; the per-item status carries the actual outcome.

{
  "results": [
    { "correlation_id": "...", "status": "ACCEPTED" },
    { "correlation_id": "...", "status": "ACCEPTED", "replay": true },
    { "correlation_id": "...", "status": "REJECTED",
      "reason": "Unknown SKU 'SKU-FOO-001'." }
  ],
  "summary": { "accepted": 2, "rejected": 1 }
}

A request that is itself malformed (bad JSON, missing required envelope field) returns 400 for the whole request — no per-item processing happens.

Retry strategy

Status class

Retry?

Strategy

2xx

n/a

Done.

4xx except 429

No.

Fix the input and resubmit with a fresh correlation_id only if the original was logically wrong. If the original was correct and the receiver was wrong, escalate — do not loop.

429

Yes

Honor Retry-After.

5xx

Yes

Exponential backoff. Cap at 24h before DLQ.

Retrying a 4xx (other than 429) wastes resources on both sides and risks corrupting your idempotency state. The planner / executor will not change its answer on retry of the same (partner_id, correlation_id).