Respond to unfulfillable line notice
Respond to an unfulfillable-line notice.
Unfulfillable Notices
/api/v1/scent/unfulfillable-notices/{id}/respondWithin the 72-hour window, choose CancelWhole (cancel the whole outstanding line, full
refund) or ShipAvailable (ship what’s available, cancel + refund only the shortfall).
Returns the notice with the resulting refund figures now applied (status becomes
Resolved). A cross-tenant or unknown id returns 404 (no existence leak). Rejects a notice
that isn’t currently AwaitingPartnerResponse with 422 BUSINESS_NOTICE_NOT_AWAITING_RESPONSE
(already resolved, or already expired past its own deadline). If your response races the
72-hour expiry sweep for the same notice, the loser gets 409 CONFLICT_NOTICE_ALREADY_RESOLVED — the money already landed under whichever side won; retry
with a fresh read to see the outcome.
Path parameters
idstring (uuid)RequiredThe notice’s own GUID.
Body parameters
choicestring (enum)RequiredCancelWhole: cancel the whole outstanding line (full refund). ShipAvailable: ship what’s available, cancel + refund only the shortfall.
Response
idstring (uuid)scentOrderIdstring (uuid)The order this notice belongs to — the same Scent order GUID you already hold from order creation/tracking and the webhook’s own data.orderId.
reasonstring (enum)OutOfStock: a receiving-time shortage/damage discrepancy. Lost: the shipment carrying this line was declared lost — always resolves as a full cancel.
statusstring (enum)AwaitingPartnerResponse: the 72-hour clock is running, waiting on you. Resolved: you responded within the window (see responseChoice). ExpiredCancelledWhole/ExpiredShipAvailable: you did not respond in time, and the system applied its own default (nothing shipped vs. the shipment had already departed).
responseChoicestring (enum)The choice you made, when you responded within the window. Null if the notice expired instead (the effective outcome is then read off status) or is still open.
notifiedAtstring (date-time)responseDeadlineAtstring (date-time)The 72-hour deadline — respond before this instant or the system’s own default applies.
hasShipmentDepartedbooleanWhether the shipment carrying this line had already departed toward you at the moment the notice was raised — informs which default applies on expiry.
respondedAtstring (date-time)line.scentOrderLineIdstring (uuid)line.variantIdstring (uuid)line.skustringline.orderedQuantityintegerThe originally ordered quantity for this line.
line.availableQuantityintegerUnits still shippable (outstanding minus shortfall) — what ShipAvailable would keep.
line.shortfallQuantityintegerUnits that cannot be fulfilled — what both choices cancel + refund.
impact.cancelWholeobjectMirrors the order’s pricing{} so a refund reconciles field-for-field against the charge. Populated ONLY once the refund has genuinely landed.
impact.shipAvailableobjectMirrors the order’s pricing{} so a refund reconciles field-for-field against the charge. Populated ONLY once the refund has genuinely landed.
Other responses
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 Errors guide.403The route is not available to your credential (FORBIDDEN).404Unknown notice, or a cross-tenant id (no existence leak).409Lost a race against the 72-hour expiry sweep resolving the same notice.415The request body is not sent as application/json (UNSUPPORTED_MEDIA_TYPE).422The notice is no longer awaiting a response.429Too many requests — see the Rate limits guide. 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 PATCH \ --url https://api-omni.linra.net/api/v1/scent/unfulfillable-notices/5b1e3a1c-9d2e-4f3a-8b1c-9f0a2e3d4c5b/respond \ --header 'Authorization: Bearer $TOKEN' \ --header 'Content-Type: application/json' \ --data '{ "choice": "CancelWhole" }'const res = await fetch('https://api-omni.linra.net/api/v1/scent/unfulfillable-notices/5b1e3a1c-9d2e-4f3a-8b1c-9f0a2e3d4c5b/respond', { method: 'PATCH', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ choice: 'CancelWhole' }),});const { payload } = await res.json();var response = await httpClient.PatchAsJsonAsync( "https://api-omni.linra.net/api/v1/scent/unfulfillable-notices/5b1e3a1c-9d2e-4f3a-8b1c-9f0a2e3d4c5b/respond", new { choice = "CancelWhole" });
var envelope = await response.Content.ReadFromJsonAsync<ApiResponse<UnfulfillableLineNoticeResponse>>();Response
{ "state": "SUCCESS", "payload": { "id": "5b1e3a1c-9d2e-4f3a-8b1c-9f0a2e3d4c5b", "scentOrderId": "5b1e3a1c-9d2e-4f3a-8b1c-9f0a2e3d4c5b", "reason": "OutOfStock", "status": "AwaitingPartnerResponse", "responseChoice": "CancelWhole", "notifiedAt": "2026-08-22T09:14:03Z", "responseDeadlineAt": "2026-08-22T09:14:03Z", "hasShipmentDeparted": true, "respondedAt": "2026-08-22T09:14:03Z", "line": { "scentOrderLineId": "5b1e3a1c-9d2e-4f3a-8b1c-9f0a2e3d4c5b", "variantId": "5b1e3a1c-9d2e-4f3a-8b1c-9f0a2e3d4c5b", "sku": "string", "orderedQuantity": 0, "availableQuantity": 0, "shortfallQuantity": 0 }, "impact": { "cancelWhole": { "currency": "SAR", "goods": { "net": 0, "vat": 0, "total": 0 }, "commissionClawback": 0, "shippingFeeRefund": 0, "total": 0 }, "shipAvailable": { "currency": "SAR", "goods": { "net": 0, "vat": 0, "total": 0 }, "commissionClawback": 0, "shippingFeeRefund": 0, "total": 0 } } }, "details": null}
