Changelog
How the /api/v1 partner facade has grown since launch.
The /api/v1 facade is versioned as a whole (there is no per-endpoint versioning yet) — this page
tracks what’s changed since launch. All dates are the day each change landed.
2026-10-10 — Strict query input, Gateway error envelopes, public Location
Section titled “2026-10-10 — Strict query input, Gateway error envelopes, public Location”- Gateway errors use the envelope — every 401/403/404/405/415/502/503/504 the Gateway produces
now returns
{ "state", "payload": null, "details": { "message" } }instead of an empty body (or, for 415,application/problem+json). New codes:UNAUTHORIZED_MISSING_TOKEN,UNAUTHORIZED_INVALID_TOKEN,UNAUTHORIZED_TOKEN_EXPIRED,UPSTREAM_AUTH_FAILED(a server-side fault — retry later, don’t re-mint your token),FORBIDDEN,NOT_FOUND_ROUTE,METHOD_NOT_ALLOWED,UNSUPPORTED_MEDIA_TYPE,BAD_GATEWAY,SERVICE_UNAVAILABLE,GATEWAY_TIMEOUT.WWW-AuthenticateandAllowheaders are unchanged; a service’s own error passes through as before. - Dates are UTC — a date filter without an offset is read as UTC and a date-only value means
00:00Z (these used to fail with a 500). An unparseable value, or a from/to pair with from after
to, returns
400 VALIDATION_INVALID_DATE. isActiveis required onPATCH /api/v1/scent/webhooks/{id}/activeandPATCH /api/v1/scent/discount-codes/{id}/active. A body without it returns400 VALIDATION_ERRORSand changes nothing (it used to deactivate).Locationis the public URL — every201now carries an absolutehttps://api-omni.linra.net/api/v1/...(staginghttps://api-omni-stg.linra.net/...) URL instead of an internal address.- Neutral price code —
422 BUSINESS_PRICE_NOT_AVAILABLE(and the checkout-preview issuePRICE_NOT_AVAILABLE) replaces the previous price-check codes on this API, including an order’sfailureReason. Same status, same recovery: re-run the checkout preview and check out at the new price. - Token lifetime is exact — an access token stops working within at most 30 seconds of its 5-minute expiry.
- Docs — the catalog schemas in the reference now match the real responses (
info,pricing,images,logos; theinclude,id,note,accord,minPrice/maxPricefilters),pricingMode/modeBreakdownare explained on the Scent product page, the integration journey prices variants withGET /api/v1/scent/variants?include=pricing, and theapi-omni.linra.net/api-omni-stg.linra.nethosts are marked live.
2026-10-09 — Scent key notes
Section titled “2026-10-09 — Scent key notes”- Catalog —
info.notes(returned with?include=profile) gains a fourth list,key, next totop,heartandbase. It is filled only for a scent whose brand publishes a single note list with no top/heart/base pyramid; such a scent has emptytop/heart/base. For every other scentkeyis an empty array. Additive — no existing field changes. The?note=filter also matches key notes.
2026-10-09 — Scent product type
Section titled “2026-10-09 — Scent product type”- Catalog — a scent now carries
productType(Perfume,BodyMist,HairMist,PerfumeOil). Only a perfume has a concentration:concentrationisnullfor a body mist, hair mist or perfume oil, so treat it as optional. New concentration codeEauFraicheand audience codeKids.
2026-09-19 — Initial release
Section titled “2026-09-19 — Initial release”The current API surface described throughout this site — authentication, the unified error model and pagination contract, orders, cart and checkout, catalog, discount codes, returns, wallet, billing statements, commission periods, and webhooks — is the baseline. From this point on, this page records genuine changes to the live surface as they ship.
Have feedback on this documentation, or think something here doesn’t match what you’re actually seeing from the API? This document is generated from, and checked against, the real Gateway route table on every build — if you find a mismatch, it’s a bug in either the docs or the API, and we want to know about it either way.

