Webhooks
Webhooks notify your system of events in Carriyo. When a shipment status changes, an order is updated, or a return request moves through its lifecycle, Carriyo POSTs a JSON payload to a URL you configure. Your system then reacts: update an OMS, fire a notification, trigger a refund, open a ticket.
Webhooks are the integration pattern Carriyo recommends for status tracking. Polling individual endpoints is fine for occasional lookups. Webhooks scale more cleanly to high event volumes and remove the need to manage polling cadence on your side.
What Carriyo's webhooks do
- Per-tenant configurations. A tenant can register multiple webhook endpoints. A per-tenant limit may apply; check with your Carriyo contact if you're configuring many endpoints.
- Event-driven delivery. When an event happens, Carriyo
POSTs the payload to the configured URL. If your endpoint
responds with
2xx, the delivery is complete. If not, Carriyo retries. - Authentication options. Each webhook supports static
custom headers (for example, a fixed
Authorizationheader) or OAuth2 client-credentials. For OAuth2, Carriyo fetches a token from your token endpoint and attaches it to each call. - Retry with exponential delay. Failed deliveries are retried on a defined schedule. Persistent failures end up visible in the Integration Monitor for manual replay. See Retry and idempotency.
- Replay from the Dashboard. Once an underlying issue is fixed, failed events can be retriggered manually.
The model
Two concepts:
- A webhook configuration: your registered endpoint. It carries a name, URL, triggers, optional conditions, optional authentication, and an active flag. Configured in the Dashboard under Settings → Webhooks.
- An event: the record of something that happened in Carriyo. Each event has an entity type (shipment, order, or return request), an entity id, and the data describing the change. Events are emitted whether or not anyone is subscribed.
When an event fires, Carriyo evaluates the tenant's webhook configurations. Every configuration whose triggers and conditions match gets called.
Event families
Carriyo emits webhooks for three entity types:
- Shipment events. The bulk of webhook traffic. Status changes, label updates, scheduling changes, and so on.
- Order events. Order lifecycle (create, update).
- Return request events. The return request lifecycle.
The trigger options available within each family depend on the entity. For shipments, common triggers include status changes, label updates (carrier label and Carriyo label), promised delivery date changes, and scheduled collection or delivery date changes.
What's in the payload
The payload format depends on the entity type:
- Shipment webhooks. The body is the full Shipment object as JSON. Whatever is current on the shipment record at the time the webhook fires is what gets sent. No envelope, no diff.
- Order webhooks. The body is an envelope containing
oldImage(the order before the change),newImage(the order after the change), thetriggerthat fired the webhook, and anoperationflag indicating the type of change. - Return request webhooks. The body is the full ReturnRequest object as JSON.
Your handler should be tolerant of unknown fields. Carriyo adds new fields to these objects over time, and a handler that rejects unknown fields will break on those additions.
Retry and idempotency
When your endpoint returns non-2xx or times out, Carriyo retries the delivery on a defined schedule. The same event is retried, not a new one, so your handler will see the same payload more than once in normal operation. Make it idempotent.
Full retry cadence (standard and extended), idempotency strategies, and replay options are covered in Retry and idempotency.
Sequence is not guaranteed
Events for the same entity can arrive out of sequence,
especially during retry cycles or when a carrier batch-updates
multiple statuses at once. A delivered event might arrive
before out_for_delivery if the carrier reported both in one
update.
Don't rely on arrival order. Use timestamps on the payload to
work out the actual sequence. Don't apply an earlier state
over a later one: in_transit shouldn't overwrite delivered.
How it fits with other modules
- Orders. Order lifecycle events flow through the order webhook family.
- Shipping. Most webhook traffic is shipment-related. The status flow drives most events.
- Returns. Return-request lifecycle events.
- Post-purchase CX. Tracking pages and notifications consume the same events your systems do, in parallel.
- Event model. The broader event taxonomy and status-flow semantics behind the webhook payloads.