Get started

Errors

All errors share a single envelope shape and an HTTP status code that follows standard semantics. Use the type field for programmatic branching, the code field for fine-grained handling, and the message field only for human-facing logs.

Error envelope#

Every 4xx and 5xx response carries a JSON body with an error object. The envelope is stable — additional fields may be added over time but existing ones will not change shape.

json
{
  "error": {
    "type": "validation_error",
    "code": "missing_field",
    "message": "Field 'pickup_address' is required.",
    "field": "pickup_address",
    "request_id": "req_01HW8Q..."
  }
}

HTTP status codes#

CodeNameMeaning
200OKRequest succeeded.
201CreatedA new resource (e.g. shipment) was created.
204No ContentRequest succeeded; no body is returned.
400Bad RequestThe request body was malformed or failed validation.
401UnauthorizedSecret Key is missing, invalid, or revoked.
403ForbiddenThe key is valid but lacks permission for this resource.
404Not FoundThe referenced resource does not exist.
409ConflictThe request conflicts with the current state (e.g. duplicate idempotency key).
422Unprocessable EntityThe request is syntactically valid but semantically rejected.
429Too Many RequestsRate limit exceeded — retry with backoff.
500Internal Server ErrorSomething went wrong on our side. Safe to retry idempotent operations.
503Service UnavailableTemporary outage or maintenance. Retry with backoff.

Idempotency#

All POST endpoints accept an Idempotency-Key header. Sending the same key with the same request body within 24 hours returns the original response without creating a duplicate resource. Sending the same key with a different body returns 409 Conflict.

http
Idempotency-Key: 9c3a1f2b-7b1c-4e0f-9b1a-2f3e5c8a4d10

Rate limits#

Each Secret Key is limited to 120 requests per minute per environment. Exceeding the limit returns 429 Too Many Requests with a Retry-After header indicating how many seconds to wait before retrying.

Always log the request_id
Every error response includes a request_id. Include it when reporting issues to Shop.mn — it is the fastest way for our team to trace the request through our logs.