Skip to content

    Pre-launch API. The concepts described here are settled, but the API shape is not: request and response fields, parameters and defaults can still change. Build against it, and talk to your Luigi's Box contact before you put an integration into production.

    Errors and rate limits

    View source

    Every non-2xx response from every Luigi’s Box AI endpoint has the same body.

    {
    "reason": "Invalid filter expression.",
    "exception_details": {},
    "request_id": "01JQ8H3Z9K2F7M4N6P8R0S2T4V"
    }
    FieldMeaning
    reasonA human-readable, actionable message. Show it to a developer, not to a shopper.
    exception_detailsMachine-readable context. {} when there is nothing to add.
    request_idCorrelation ID, matching the X-Request-Id response header.

    Log request_id. Luigi’s Box support uses it to find the request.

    When the problem is a specific value, exception_details.validation_errors lists every field-level problem in the request:

    {
    "reason": "Request validation failed",
    "exception_details": {
    "validation_errors": [
    {
    "loc": ["query", "size"],
    "msg": "Input should be less than or equal to 100",
    "type": "less_than_equal"
    },
    {
    "loc": ["body", "objects", 0, "@id"],
    "msg": "Field required",
    "type": "missing"
    }
    ]
    },
    "request_id": "01JQ8H3Z9K2F7M4N6P8R0S2T4V"
    }
    • loc is the path to the offending value from the request root.
    • type is a stable machine code — safe to branch on.
    • msg explains the problem in words — safe to log, not to branch on.
    StatusMeaningWhat to do
    400Malformed request — unparseable body, bad encodingFix the request; do not retry
    401Missing, expired or wrong-audience tokenGet a fresh token and retry once
    403Authenticated, but not permitted on this resourceCheck the permission and the resource you named
    404Not found — or not visible to your credentialsSee the note below
    409Conflict with the resource’s current stateRe-read the resource and retry with what you find
    422Validation failedRead validation_errors; do not retry unchanged
    429Rate limit exceededBack off — see below
    502An upstream step failedRetry with backoff
    503Temporarily unavailableRetry with backoff
    RetryDo not retry
    429, after the interval it tells you400, 422 — the request itself is wrong
    502, 503, with exponential backoff403, 404 — permissions do not change on retry
    401, exactly once, with a new token409 without re-reading the resource first

    Add jitter to the backoff, so that a fleet of workers does not retry at the same instant.

    Rate-limited endpoints report your budget on every response, not only on a 429:

    HeaderMeaning
    RateLimit-LimitRequests allowed in the current window
    RateLimit-RemainingRequests left in it
    RateLimit-ResetSeconds until the window resets

    Exceeding the limit gives you 429 with the standard error body and a Retry-After header in seconds:

    HTTP/1.1 429 Too Many Requests
    Retry-After: 42
    RateLimit-Limit: 100
    RateLimit-Remaining: 0
    RateLimit-Reset: 42

    Honour Retry-After. It is an upper bound on the wait; a client that respects it does not retry into the same window.

    RateLimit-Remaining on successful responses shows a job approaching its budget before it starts receiving 429.

    If the limits do not fit your traffic, contact Luigi’s Box — they are set per account and can be raised.

    A 403 that is not about permissions is usually bot control — most often a server-side integration attempting the browser token flow, or a page origin that was never registered for its publishable key.

    Some discovery responses can carry a debug object describing ranking decisions. It is gated on a permission granted only to Luigi’s Box staff, and its contents carry no compatibility guarantee. Passing debug=true without that permission is ignored.