Skip to content
Linra Omni Vendor Docs

Create vendor offer

Submit a new offer.

Offers

POST/api/v1/scent/offers

Submits a new offer through the SAME review workflow the Portal vendor UI uses — nothing goes live without an internal reviewer’s approval. Idempotent when vendorExternalId is set: re-submitting the SAME vendorExternalId returns the already-created offer unchanged rather than creating a duplicate or erroring (a safe retry). Supply variantId for a vendor-proposed match to an existing catalog variant, or rawBrandName/rawProductName for an unmatched free-form entry. Requires the Offers capability.

Body parameters

variantIdstring (uuid)

A vendor-proposed match to an existing, active catalog variant. Omit for an unmatched free-form entry.

vendorSkustring

Your own human-readable SKU for this item.

barcodestringRequired

REQUIRED. The product’s EAN/UPC barcode (GTIN): 8, 12, 13 or 14 digits with a valid GS1 check digit, e.g. 4006381333931. Missing or invalid → 400 VALIDATION_ERRORS (field Barcode).

vendorExternalIdstring

Opaque id reserved for API integrations — doubles as the idempotency key.

costnumber (decimal)

Wholesale cost Linra pays you, in SAR. Required under a Model-1 (CostPlusMargin) agreement; must be omitted under Model 2.

costIsVatInclusiveboolean

REQUIRED whenever cost is present — there is no default. false = exclusive (cost is net, VAT added on top); true = inclusive (cost is the VAT-inclusive gross; net cost + input VAT are back-derived). Omitting this key while cost is present is rejected with 400 rather than assumed: a gross figure silently read as net would overstate your cost basis by the VAT rate.

salePricenumber (decimal)

Your own final sale price (SAR), ALREADY including Linra’s + the reselling partner’s full commission share (e.g. a price of 1000 at a 20% supplier percentage means you net 800). Required under a Model-2 (PercentageOfSale) agreement; must be omitted under Model 1.

salePriceIsVatInclusiveboolean

REQUIRED whenever salePrice is present — there is no default. false = exclusive; true = inclusive (gross), back-derived to net + VAT the same way costIsVatInclusive works for cost.

declaredStockQuantityinteger

Your declared quantity on hand, when you report a number rather than a bare yes/no.

declaredInStockboolean

Your declared availability.

rawBrandNamestring

Required when variantId is omitted — the brand name as you know it.

rawProductNamestring

Required when variantId is omitted — the product name as you know it.

rawConcentrationstring
rawSizeMlinteger
rawDescriptionstring
saveAsDraftboolean

Save as a Draft (no review queue entry yet) instead of submitting for review immediately.

Response

idstring (uuid)
statusstring (enum)

Draft (saved, not submitted) → PendingMatch (no variantId, awaiting reviewer match) or PendingReview (a proposed match, awaiting approval) → Approved (live) → Withdrawn/Suspended; Rejected is reachable from Draft/PendingMatch/PendingReview. You never set Approved yourself. PendingRepricing: your agreement’s pricing model was switched by Linra while this offer was Approved or PendingReview — the offer’s linked supply is paused (not sellable) until you resubmit ONLY the new model’s price field (cost under Model 1, sale price under Model 2; stock updates are still accepted and never change this status) and it is re-reviewed, at which point it returns to PendingReview and then Approved as usual.

pricingModelobject

CostPlusMargin (“Model 1”): you declare cost, Linra adds a markup. PercentageOfSale (“Model 2”): you declare the final sale price; Linra + the reselling partner deduct a percentage of it.

vendorExternalIdstring

Opaque id reserved for API integrations; doubles as an idempotency key.

product.variantIdstring (uuid)

A vendor-proposed match to an existing, active Variant. Null for an unmatched free-form entry.

product.vendorSkustring
product.barcodestring

The product’s EAN/UPC barcode. Null only on an offer created before the barcode became required, until its next edit.

product.rawBrandNamestring
product.rawProductNamestring
product.rawConcentrationstring
product.rawSizeMlinteger
product.rawDescriptionstring
cost.amountnumber (decimal)

The live, stored NET cost Linra pays you (SAR).

cost.isVatInclusiveboolean

Always false — pair amount with this value (false) on a write to safely resubmit it unchanged. This is the one entry mode that can never re-interpret an already-net figure as a fresh gross one. See enteredVatInclusive for how you actually entered it.

cost.enteredVatInclusiveboolean

Display-only — your actual original entry-mode preference. NEVER accepted on a write; use isVatInclusive (always false) for that.

cost.inputVatnumber (decimal)

Your own input VAT on the current cost, back-derived when enteredVatInclusive is true.

cost.pendingobject

A cost change staged by you (or an internal edit) on an Approved offer, awaiting reviewer approval — the live cost above is untouched until applied.

price.amountnumber (decimal)

The live, stored NET sale price (SAR).

price.isVatInclusiveboolean

Always false — pair amount with this value (false) on a write to safely resubmit it unchanged. See enteredVatInclusive for how you actually entered it.

price.enteredVatInclusiveboolean

Display-only — your actual original entry-mode preference. NEVER accepted on a write.

price.vatnumber (decimal)

The VAT on the current sale price, back-derived when enteredVatInclusive is true.

price.pendingobject

A sale-price change staged by you on an Approved offer, awaiting reviewer approval — the live sale price above is untouched until applied.

stock.declaredQuantityinteger

Your declared quantity on hand, when you report a number rather than a bare yes/no.

stock.declaredInStockboolean
review.reviewedAtstring (date-time)
review.reasonstring

Other responses

400Request validation failed.
401No bearer token (UNAUTHORIZED_MISSING_TOKEN), an invalid token (UNAUTHORIZED_INVALID_TOKEN) or an expired one (UNAUTHORIZED_TOKEN_EXPIRED — mint a new token). UPSTREAM_AUTH_FAILED is different: a dependent service refused the Gateway itself. That is a server-side fault — retry later and do NOT re-mint your token. See the Rate limits & errors guide.
403Your token doesn’t carry the capability this endpoint requires.
404No API route matches this path (NOT_FOUND_ROUTE). A missing resource on a real route returns that service’s own NOT_FOUND_* code instead.
415The request body is not sent as application/json (UNSUPPORTED_MEDIA_TYPE).
429Too many requests. Retry after the Retry-After header (seconds).
502A dependent service returned an invalid response (BAD_GATEWAY). Retry with backoff.
503The service is temporarily unavailable (SERVICE_UNAVAILABLE). Retry with backoff.
504A dependent service did not respond in time (GATEWAY_TIMEOUT). Retry with backoff.
curl --request POST \
--url https://api-omni-vendors.linra.net/api/v1/scent/offers \
--header 'Authorization: Bearer $TOKEN' \
--header 'Content-Type: application/json' \
--data '{
"variantId": "5b1e3a1c-9d2e-4f3a-8b1c-9f0a2e3d4c5b",
"vendorSku": "string",
"barcode": "string",
"vendorExternalId": "string",
"cost": 0,
"costIsVatInclusive": true,
"salePrice": 0,
"salePriceIsVatInclusive": true,
"declaredStockQuantity": 0,
"declaredInStock": true,
"rawBrandName": "string",
"rawProductName": "string",
"rawConcentration": "string",
"rawSizeMl": 0,
"rawDescription": "string",
"saveAsDraft": false
}'

Response

{
"state": "SUCCESS",
"payload": {
"id": "5b1e3a1c-9d2e-4f3a-8b1c-9f0a2e3d4c5b",
"status": "Draft",
"pricingModel": {},
"vendorExternalId": "string",
"product": {
"variantId": "5b1e3a1c-9d2e-4f3a-8b1c-9f0a2e3d4c5b",
"vendorSku": "string",
"barcode": "string",
"rawBrandName": "string",
"rawProductName": "string",
"rawConcentration": "string",
"rawSizeMl": 0,
"rawDescription": "string"
},
"cost": {
"amount": 0,
"isVatInclusive": true,
"enteredVatInclusive": true,
"inputVat": 0,
"pending": {
"amount": 0,
"inputVat": 0
}
},
"price": {
"amount": 0,
"isVatInclusive": true,
"enteredVatInclusive": true,
"vat": 0,
"pending": {
"amount": 0,
"vat": 0
}
},
"stock": {
"declaredQuantity": 0,
"declaredInStock": true
},
"review": {
"reviewedAt": "2026-08-22T09:14:03Z",
"reason": "string"
}
},
"details": null
}