Skip to main content

Outbound webhooks

Upwell can POST a JSON event to a URL you host whenever something changes — a carrier invoice is created, matched to a shipment, approved, and so on. Webhooks are the push counterpart to polling.

Subscribing

Webhook subscriptions are configured in the Upwell dashboard (there’s no public REST endpoint to create one). A subscription has:
  • url — your HTTPS receiver.
  • triggers — the list of event types you want delivered.
  • authSettings — how Upwell proves the delivery came from Upwell (see Authenticating deliveries).
  • retryAttempts — how many times Upwell retries a failed delivery (0–10).

Carrier-invoice triggers

“Ingestion done” (matched + audited) is best observed via *.shipment_updated or the generic update.carrier_invoice. The *.status.APPROVED / *.status.EXCEPTION triggers reflect the later review lifecycle. See Knowing when a carrier invoice is processed.
For the full set of triggers you can subscribe to — across every resource, not just carrier invoices — see the Webhook event catalog.

The delivery envelope

Every delivery is a single JSON object — the event row. The fields you’ll read: Plus delivery bookkeeping (tenantId, retries, createdAt, processedAt, …).

The payload shape varies by trigger

There is no single payload shape. Status-change events deliver a mapped object nested under carrierInvoice; row-level events (*.shipment_updated) deliver raw new/old column snapshots. The robust pattern is to read resourceId from the envelope and call GET /api/rest/carrier_invoices/{resourceId} for a canonical representation — then the payload is just a hint about what changed.
Status-change events (update.carrier_invoice.status.APPROVED / .EXCEPTION) — payload.carrierInvoice with the invoice and its matched relations nested:
Row-level events (update.carrier_invoice.shipment_updated) — raw new/old snapshots (snake_case columns):
Note new.source_system = "API" and new.integration_id are stamped by Upwell — confirming the invoice was API-submitted. source_system_id is null for API submissions.

Authenticating deliveries

You choose how Upwell authenticates to your receiver when you create the subscription. Three options:
Upwell sends Authorization: Basic base64(username:password) using the credentials you configure.
No auth header. Rely on URL secrecy / network controls. Not recommended for production.
Upwell always sends Content-Type: application/json and a User-Agent of UpwellWebhookService/<version> (https://www.upwell.com).

Reliability

  • Deliveries that return 5xx are retried, up to the subscription’s retryAttempts.
  • Each delivery has a 15-second timeout.
  • Return a 2xx quickly; do slow work asynchronously.
  • Build an idempotent receiver: dedupe on the delivery id (or resourceId + trigger).

Example receiver

See it end-to-end

The sample TMS app implements this receiver alongside a polling fallback, and walks the full submit → attach → process flow. Start from the submission guide.