Skip to content
Linra Omni Developer Docs

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-Authenticate and Allow headers 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.
  • isActive is required on PATCH /api/v1/scent/webhooks/{id}/active and PATCH /api/v1/scent/discount-codes/{id}/active. A body without it returns 400 VALIDATION_ERRORS and changes nothing (it used to deactivate).
  • Location is the public URL — every 201 now carries an absolute https://api-omni.linra.net/api/v1/... (staging https://api-omni-stg.linra.net/...) URL instead of an internal address.
  • Neutral price code — 422 BUSINESS_PRICE_NOT_AVAILABLE (and the checkout-preview issue PRICE_NOT_AVAILABLE) replaces the previous price-check codes on this API, including an order’s failureReason. 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; the include, id, note, accord, minPrice/maxPrice filters), pricingMode/modeBreakdown are explained on the Scent product page, the integration journey prices variants with GET /api/v1/scent/variants?include=pricing, and the api-omni.linra.net / api-omni-stg.linra.net hosts are marked live.
  • Catalog — info.notes (returned with ?include=profile) gains a fourth list, key, next to top, heart and base. It is filled only for a scent whose brand publishes a single note list with no top/heart/base pyramid; such a scent has empty top/heart/base. For every other scent key is an empty array. Additive — no existing field changes. The ?note= filter also matches key notes.
  • Catalog — a scent now carries productType (Perfume, BodyMist, HairMist, PerfumeOil). Only a perfume has a concentration: concentration is null for a body mist, hair mist or perfume oil, so treat it as optional. New concentration code EauFraiche and audience code Kids.

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.