Platform overview
What Linra Omni is, how the API is versioned, and the contracts every endpoint shares — independent of which product you're calling.
What is Linra Omni
Section titled “What is Linra Omni”Linra Omni is a single B2B commerce platform, not a collection of separately-integrated systems. You sign one partner agreement, hold one set of API credentials, and integrate against one versioned API — and that stays true as Linra adds more product lines over time. Today that means Scent (perfume and fragrance); tomorrow it may mean others. Whichever products you sell through, you never re-authenticate differently, re-learn a different response shape, or manage a second wallet.
This page covers only the platform layer — the concepts and contracts that work identically no matter which product you’re calling: authentication, the response envelope, pagination, rate limits, and the shared error model. Anything specific to Scent (its catalog, cart, order states, returns) lives on the Scent product page and its own guides instead.
flowchart TD
Partner["Your integration"] -->|"HTTPS + bearer token"| API["Linra Omni API — /api/v1"]
API --> Platform["Platform layer<br/>Authentication · Wallet · Billing Statements · Commission Periods"]
API --> Scent["Scent — /api/v1/scent/**<br/>Catalog · Cart · Orders · Returns · Webhooks"]
API -.-> Future["A future product — /api/v1/{product}/**"]
Everything under Platform in the sidebar is built to keep working exactly the same way once a second product line ships, with no breaking change on your side — that is the guarantee this split exists to make. Everything under Scent is specific to that one product’s own catalog and order lifecycle. See URL conventions for exactly how that split shows up in the URLs themselves.
If you only integrate with one product today, you don’t need to think about this distinction much — just start with Getting started. It matters mainly for knowing which parts of your integration are safe to assume will never change shape as Linra grows.
API versioning
Section titled “API versioning”The entire partner-facing surface lives under one version prefix, /api/v1. There is no
per-resource versioning — a breaking change to any endpoint would ship as /api/v2 for the whole
facade, announced in the Changelog well ahead of time. Every path in this reference
is relative to that prefix and one of the base URLs for your environment.
Authentication & the token model
Section titled “Authentication & the token model”Every request other than the token exchange itself carries a short-lived bearer token, obtained by
exchanging your clientId/clientSecret credential at POST /api/v1/auth/token:
sequenceDiagram
autonumber
participant P as Your integration
participant L as Linra Omni API
P->>L: POST /api/v1/auth/token<br/>{ clientId, clientSecret }
alt Valid credential
L-->>P: 200 { accessToken, expiresIn: 300 }
P->>L: Any /api/v1/** call<br/>Authorization: Bearer accessToken
L-->>P: { "state": "SUCCESS", "payload": { ... } }
else Invalid credential
L-->>P: 401 UNAUTHORIZED_INVALID_CREDENTIALS
end
The token is scoped to your own partner identity, is short-lived by design (5 minutes, no refresh grant), and carries no data you supply yourself — see Authentication & tokens for the full model, why it’s deliberately short-lived, and the caching pattern you should build around it from day one.
The response envelope
Section titled “The response envelope”Every response — success or error — is wrapped in the same three-key envelope,
{ state, payload, details }. See Errors for the full shape and the error
codes you’ll actually encounter; it’s covered there rather than duplicated here since the envelope
and the error-code catalogue are two halves of the same page.
Pagination
Section titled “Pagination”Every list endpoint accepts page (1-based) and pageSize query parameters and returns its
results alongside a pagination object with this exact shape, regardless of which resource you’re
paging through:
{ "items": [ "..." ], "pagination": { "page": 1, "pageSize": 20, "totalCount": 143, "totalPages": 8 }}totalCountis the FULL count across every page, not just the page you requested.totalPagesis derived (ceil(totalCount / pageSize)) — keep paging whilepage < totalPages.pageSizeis 1 to 100 and defaults to 20;pagestarts at 1. A value outside those bounds (or one that isn’t a whole number) returns400 VALIDATION_INVALID_PAGE_SIZE/VALIDATION_INVALID_PAGE— it is never silently clamped.
Query parameters are strict
Section titled “Query parameters are strict”Every /api/v1 endpoint validates its query string. An unknown parameter name
(VALIDATION_UNKNOWN_QUERY_PARAMETER, with details.allowedParameters), a value that doesn’t parse
as the parameter’s type (VALIDATION_INVALID_QUERY_PARAMETER; enums add details.allowedValues), or
an unknown include token (VALIDATION_UNKNOWN_INCLUDE) returns 400 instead of being ignored — so
a typo can never silently widen a filter. Date filters are read as UTC when they carry no offset; a
date-only value means 00:00Z. See Errors.
Rate limits
Section titled “Rate limits”Every /api/v1 route is rate-limited using a sliding window, keyed by your credential — a burst
past the limit gets a 429 with a Retry-After header, never a silent throttle. See
Rate limits for the exact limits per route and the recommended retry
posture.
Errors
Section titled “Errors”Every error response’s state field is a stable, machine-readable code — cross-tenant access
always reports 404 (never 403, so a not-yours resource is indistinguishable from a
nonexistent one), and no error response ever leaks a stack trace or internal detail. See
Errors for the full HTTP-status-to-shape mapping and the codes you’re likely to
build handling around.
Where to go next
Section titled “Where to go next”- URL conventions — the platform-vs-product URL rule.
- Authentication & tokens — how to actually call any of this.
- Idempotency — the retry-safety contract for order creation.
- Scent — this product’s own endpoints and state catalogue.

