--- title: Requests and responses description: The conventions every Luigi's Box AI endpoint shares — base URL, versioning, headers, pagination, sorting, partial updates, and the OpenAPI contract you can generate a client from. slug: api-basics/requests-and-responses docKind: reference hub: luigisbox-ai --- The Luigi's Box AI API is one host, and the conventions on this page hold across every endpoint on it. ## Base URL ```text https://api..luigisbox.ai//v1/ ``` - `` is the zone your account runs in, for example `eu1`. Examples here use `eu1`. - `` is the product prefix: `discovery`, `index`, `catalog`, `ledger`, `events`, `platform`. One host, one path prefix per product. - `v1` is the URL namespace, not a stability promise. It only changes for a breaking revision, and a new version runs alongside the old one. While the API is pre-launch, the shape inside `v1` can still change — see the notice at the top of every page. ```text https://api.eu1.luigisbox.ai/discovery/v1/search https://api.eu1.luigisbox.ai/index/v1/lbc_8w3k2p/index/ https://api.eu1.luigisbox.ai/catalog/v1/lbc_8w3k2p/sources/feeds https://api.eu1.luigisbox.ai/platform/v1/channels ``` Tokens are minted on a separate host, `https://auth..luigisbox.ai`. See [Authentication](/authentication/overview/). ## Timestamps Every timestamp field ends in `_at` and is UTC ISO-8601: ```json { "created_at": "2026-03-14T09:21:07Z" } ``` ## Headers ### On the request | Header | When | Purpose | |---|---|---| | `Authorization: Bearer ` | Always | Your access token | | `Content-Type: application/json` | On requests with a body | | | `X-Lbx-Visitor-Id` | Required on discovery and event requests | Identifies the browser | | `X-Request-Id` | Optional | Your own correlation ID; echoed back | ### On the response | Header | When | Purpose | |---|---|---| | `X-Request-Id` | Always | Yours if you sent one, otherwise generated. Quote it in support requests. | | `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset` | Rate-limited endpoints | Your current budget | | `Retry-After` | On `429` | How long to wait | ## Identifying the shopper Discovery and analytics need to know *which* shopper a request belongs to, without knowing who they are. `X-Lbx-Visitor-Id` carries that. | | | |---|---| | Scope | One browser, long-lived | | Who generates it | Your integration | | Required | Yes, on discovery requests and on analytics events | | Survives a token refresh | Yes | It is an opaque string you own; a UUID is the usual choice. It is not used to authorize anything, so it does not need to be secret. It does need to be consistent, because it is what joins a shopper's discovery requests to the analytics events that follow. If your backend generates this value instead of passing through what your frontend produced, every shopper collapses into one: personalization stops working and reports stop being meaningful. A signed-in shopper additionally passes `user_id` — a body field on discovery requests, a field on events. It is separate and optional; see [Personalization](/discovery/personalization/). ## Pagination Endpoints that list stored records page with `page` and `size`, and return a consistent envelope: ```bash curl -G 'https://api.eu1.luigisbox.ai/platform/v1/channels' \ --data-urlencode 'catalog_id=lbc_8w3k2p' \ --data-urlencode 'page=2' \ --data-urlencode 'size=50' \ -H 'Authorization: Bearer ' ``` The envelope is the same on every such endpoint: ```json { "items": [{ "id": "lbn_4hj9tv", "name": "example.com" }], "page": 2, "size": 50, "total": 61 } ``` Discovery results are different: they page with an opaque `cursor`, because a ranked result set is not a stable list of rows. See [Sorting and pagination](/discovery/sorting-and-pagination/). ## Sorting On collection endpoints, one parameter, `field:direction`, with the direction always spelled out: ```text ?sort=created_at:desc ?sort=price:asc ``` There is no multi-field sort and no `-field` shorthand. A field is sortable only if the response shows it. Discovery sorts differently: its requests are JSON, so `sort` is an object rather than a string. See [Sorting and pagination](/discovery/sorting-and-pagination/#sorting). Every collection has a documented, deterministic default order on a value that does not change — usually `id` or `created_at` — so paging through it twice gives you the same records in the same order. ## Partial updates A `PATCH` body means "change exactly what I named": - A field you **omit** is left unchanged. - A field you send as `null` is **cleared**, when the field can be cleared. - A field that cannot be cleared rejects `null` with `422`. This changes a feed's URL and nothing else: ```bash curl -X PATCH 'https://api.eu1.luigisbox.ai/catalog/v1/lbc_8w3k2p/sources/feeds/41' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ -d '{"url": "https://example.com/feeds/products.xml.gz", "expected_version": 7}' ``` The same holds for [partial updates to catalog objects](/indexing/content-api/#partial-updates), where omitting a field is how you leave a stored attribute alone. ## Writes return the resource A successful `POST`, `PUT` or `PATCH` responds with the complete resource — server-assigned IDs, resolved defaults and computed fields included. No follow-up `GET` is needed to read back what was written. Secrets are the exception: they are accepted and never echoed back. A resource that holds one reports whether it is set rather than what it is. Deletes respond `204` with no body. Requests that are accepted for asynchronous processing respond `202` — see [Content API](/indexing/content-api/). ## The OpenAPI contract Every endpoint on the surface is described by one OpenAPI 3.1 document, and the [API Reference](/api/) is generated from it. The same document is downloadable: ```bash curl -O https://docs.luigisbox.ai/openapi.yaml ``` It is the authoritative description of the API — paths, parameters, request and response schemas, enums, defaults, and the error shape. Where this documentation and the contract disagree, the contract is right. ### Generating a client Point a generator at the spec to get a typed client in your language: ```bash # TypeScript types npx openapi-typescript https://docs.luigisbox.ai/openapi.yaml -o src/luigisbox.d.ts # A full client, any of ~50 languages npx @openapitools/openapi-generator-cli generate \ -i https://docs.luigisbox.ai/openapi.yaml \ -g python \ -o ./luigisbox-client ``` Any OpenAPI 3.1 generator works — `openapi-generator`, `openapi-typescript`, `oapi-codegen`, `kiota`, `NSwag`. Luigi's Box does not publish SDKs, so a generated client is the supported way to get one, and it is regenerable rather than something you maintain by hand. Two properties of the contract affect the generated code: - **Operation IDs are curated**, verb first — `list_catalogs`, `index_objects`, `get_object_timeline` — so generated method names read like the API rather than like the URL. - **One schema name means one thing surface-wide.** A `Catalog` is the same `Catalog` whichever service returns it, so a generated model is shared rather than duplicated per endpoint. ### Keeping up with changes Regenerate when you pull a new spec. While the API is pre-launch that regeneration can change request and response shapes, not only add to them, so review the diff rather than assuming your existing calls still compile. Once the API launches the contract only grows within `v1` — new endpoints, new optional fields, new enum values — and anything that would break a caller lands in a new version path running alongside the old one. If your generator is strict about unknown enum values, allow for them: a value added to an enum is not a breaking change on our side, and a client that hard-fails on one will break on a change we consider additive. ### Other uses for the spec - **Mock server.** `npx @stoplight/prism-cli mock openapi.yaml` gives you a local API that answers with schema-valid responses — useful before your credentials arrive. - **Request validation in tests.** Assert your payloads against the schemas before sending them. - **Import into a client.** Postman, Insomnia, Bruno and Paw all read the spec directly. ## See also - [Errors and rate limits](/api-basics/errors-and-rate-limits/) - [Authentication overview](/authentication/overview/) - [Identifiers](/concepts/identifiers/) - [API Reference](/api/) — every endpoint, parameter and schema