Skip to content
Linra Omni Developer Docs

Create webhook subscription

Create a webhook subscription.

Webhooks

POST/api/v1/scent/webhooks

The response’s secret is shown EXACTLY ONCE — store it immediately. Up to 5 active subscriptions per partner (BUSINESS_WEBHOOK_SUBSCRIPTION_LIMIT above that). See the Webhooks guide for the full HMAC verification walkthrough.

Body parameters

urlstring (uri)Required

Must be a public HTTPS URL — private/loopback/link-local addresses are rejected (SSRF guard), re-checked on every delivery attempt.

eventTypesarray of string (enum)Required
headersobject

Optional partner-defined outbound headers (name→value), added to every delivery ALONGSIDE the always-on HMAC signature. WRITE-ONLY — never returned by any read. At most 10 entries; each name up to 128 characters and each value up to 2048 characters, no CR/LF in either. Content-Type, Host, Content-Length, and the fleet’s own X-Linra-Signature/ X-Linra-Timestamp header names are reserved and rejected.

Response

subscription.idstring (uuid)
subscription.urlstring (uri)
subscription.eventTypesarray of string
subscription.isActiveboolean
subscription.lastDeliveryAtstring (date-time)
subscription.lastDeliveryStatusstring (enum)

Null until the first delivery attempt. DeadLettered means every retry was exhausted — see the Webhooks guide for the retry schedule.

subscription.createdAtstring (date-time)
secretstring

Shown exactly once — store it now. Used as the HMAC signing key.

Other responses

400Request validation failed (VALIDATION_ERRORS, with details.errors), or the webhook URL is not allowed — not a valid absolute https URL, its host does not resolve, or it resolves to a private/non-routable address (VALIDATION_WEBHOOK_URL_UNSAFE, details.reason says which).
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).
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).
422Active-subscription cap exceeded.
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 POST \
--url https://api-omni.linra.net/api/v1/scent/webhooks \
--header 'Authorization: Bearer $TOKEN' \
--header 'Content-Type: application/json' \
--data '{
"url": "https://your-integration.example.com/webhooks/linra",
"eventTypes": [
"order.completed"
],
"headers": {
"Authorization": "Bearer your-own-inbound-token"
}
}'

Response

{
"state": "SUCCESS",
"payload": {
"subscription": {
"id": "5b1e3a1c-9d2e-4f3a-8b1c-9f0a2e3d4c5b",
"url": "https://your-integration.example.com/webhooks/linra",
"eventTypes": [
"string"
],
"isActive": true,
"lastDeliveryAt": "2026-08-22T09:14:03Z",
"lastDeliveryStatus": "Success",
"createdAt": "2026-08-22T09:14:03Z"
},
"secret": "string"
},
"details": null
}