Changelog
What's shipped on the vendor API, going forward.
2026-10-10 — Strict query input, Gateway error envelopes, public Location
Section titled “2026-10-10 — Strict query input, Gateway error envelopes, public Location”-
Live hosts — the vendor API is served at
https://api-omni-vendors.linra.net(production) andhttps://api-omni-vendors-stg.linra.net(staging); the API reference servers list is updated accordingly. -
Gateway errors use the envelope — every 401/403/404/405/415/502/503/504 the vendor 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. -
Required fields —
declaredInStockis required onPATCH /api/v1/scent/offers/{offerId}/stock(a typo such as{"quantity":5}used to take the offer out of stock), and it must agree withdeclaredStockQuantity.isActiveis required onPATCH /api/v1/scent/webhooks/{id}/activeandPATCH /api/v1/credentials/{id}/active. A body without them returns400 VALIDATION_ERRORSand changes nothing. -
Dates are UTC — a date filter without an offset is read as UTC and a date-only value means 00:00Z; an unparseable value returns
400 VALIDATION_INVALID_DATE. -
Locationis the public URL — every201now carries an absolutehttps://api-omni-vendors.linra.net/api/v1/...(staginghttps://api-omni-vendors-stg.linra.net/...) URL instead of a relative or internal one. -
Token lifetime is exact — an access token stops working within at most 30 seconds of its 5-minute expiry.
-
Docs — your first credential comes from Linra: contact your Linra account manager. Further credentials: Portal dashboard https://omni-portal.linra.net → Administration → API Credentials (one address for staging and production; choose with the Environment selector).
2026-10-09 — Barcode required on offers
Section titled “2026-10-09 — Barcode required on offers”- Offers — breaking change, effective from this release —
barcode(the product’s EAN/UPC: 8, 12, 13 or 14 digits with a valid check digit) is now required onPOST /api/v1/scent/offersand as theBarcodecolumn of the offer import; a create without it, or with a bad check digit, is a400 VALIDATION_ERRORS(fieldBarcode). OnPATCH /api/v1/scent/offers/{id}it may be omitted — the stored barcode is kept, never cleared. Offer responses carry it asproduct.barcode. - Offers —
PATCH /api/v1/scent/offers/{id}is now a partial update — a field you omit (or send asnull) keeps its stored value; it was previously cleared (and on anApprovedoffer a clearedvendorSku/vendorExternalIdsent the offer back to review).""clears an optional text field (vendorSku,vendorExternalId,rawConcentration,rawDescription; alsorawBrandName/rawProductNameon an offer matched to a catalog variant; whitespace-only counts as empty). With no price field in the body the stored price is kept, so a body such as{"barcode": "4006381333931"}or{"cost": 120, "costIsVatInclusive": false}is valid on its own. Request and response shapes are unchanged. - Compatibility — offers created before this release keep working unchanged (stock, cost and
sale-price pushes, orders, payouts). Their stock and price can still be edited without a barcode; a
barcode is needed before changing their product details, and before any edit that sends a
RejectedorPendingRepricingoffer back to review (every edit of aRejectedoffer; a price change on aPendingRepricingone; this applies to the stock, cost and sale-price pushes too). In an offer import file, rows that update an existing offer may leaveBarcodeblank or omit the column; rows that create one need it. A retried create that reuses an oldvendorExternalIdmust now carry a barcode too (the body is validated before the idempotent replay). Nothing else in v1 changes.
2026-09-28 — Return request read; evidence Location header
Section titled “2026-09-28 — Return request read; evidence Location header”- Returns — new
GET /api/v1/scent/returns/{id}reads one of your own return requests (same ownership scope andOrderscapability as the other return actions). POST /api/v1/scent/returns/{id}/evidencenow answers201with aLocationheader pointing at that public route (it previously named an internal path you could not call).
2026-09-19 — Initial release
Section titled “2026-09-19 — Initial release”The current vendor API surface, as documented across this site:
- Authentication —
POST /api/v1/auth/token, capability-scoped, audiencevendor-api. - Profile —
GET /api/v1/profile, read-only. - Credentials — self-service credential management under
/api/v1/credentials, gated by theAccountcapability (reads require no capability). - Offers — submit and edit product offers (
/api/v1/scent/offers), gated by theOfferscapability. - Stock — instant declared-availability/quantity pushes
(
/api/v1/scent/offers/{offerId}/stock), gated by theStockcapability. - Cost — approval-pipelined cost pushes (
/api/v1/scent/offers/{id}/cost), gated by theCostcapability, independently ofOffers. - Orders & fulfilment — poll assigned fulfilment groups with delta sync, and push fulfilment
status (
/api/v1/scent/orders/**), gated by theOrderscapability. - Returns — confirm receipt, inspect, upload evidence, and propose an outcome for a model-A
return (
/api/v1/scent/returns/**), gated by theOrderscapability. - Webhooks — subscription management and HMAC-signed push delivery for
vendor.scent.order.assignedandvendor.scent.offer.review-decision(/api/v1/scent/webhooks/**), gated per event type.
From this point on, this changelog records only genuine changes to the live API — going forward.

