Tracking Webhooks

Have tracking and document changes for your freight pushed to your own system instead of polling. Both arrive on one webhook: one URL and one signing secret per company.

Tracking webhooks: how it works

  1. Register your URL, once. POST /tracking/webhooks with your HTTPS url and an error_contact_email. The response carries the webhook id and its signing secret. Store the secret now; it is returned only once.
  2. Send a test, once. POST /tracking/webhooks/{webhook_id}/test delivers a signed tracking.webhook.test event to your URL right away and tells you what your endpoint answered. A 2xx proves Shipwell reached your endpoint through your firewall and TLS. Make your handler reject a bad signature, so a 2xx also means your signature check passed.
  3. Receive updates, no further calls. Book freight as usual with POST /dispatching/jobs. Whenever its tracking changes, a signed tracking.updated event is POSTed to your URL, usually within a minute or two, carrying the full current tracking snapshot. For each one: verify X-Shipwell-Signature, ignore an id you have already processed, ignore a sequence lower than the highest you have applied for that resource_id, replace your copy of the shipment's tracking, and answer any 2xx within 10 seconds.
  4. Pull when you need to. GET /tracking/timelines/{resource_id} returns the current tracking, under data and paged, for filling gaps such as catching up after downtime. It carries no sequence, so it can't be ordered against deliveries: one retried across your pull may hold an older snapshot. Keep applying deliveries by sequence, but a delivery that arrives after a pull can overwrite newer pulled contents; no later change is guaranteed to correct the snapshot, so pull again after applying any delivery that arrives after a pull, since a retry can come hours later. Never let a snapshot with is_terminal: false replace one with is_terminal: true, because a finished shipment sends no further changes.

Deliveries that fail with a timeout, network error, 408, 429 or 5xx are retried for about 47 hours. Every event payload is described under Webhooks in this reference. To pause, change or remove a webhook, use Company → Webhooks in the Shipwell app.

Documents webhooks: how it works

Have the documents a carrier produces for your freight (BOL, proof of delivery, weight certificate) pushed to the same URL instead of polling.

  1. Subscribe, once. Include "documents.updated" in event_names when you register your URL with POST /tracking/webhooks, alongside "tracking.updated" or on its own. It must be enabled for your company first, or the request answers 403 documents_webhooks_not_enabled. To add it to a webhook you already registered, tick Document updates under Events in Company → Webhooks in the Shipwell app.
  2. Send a test, once. POST /tracking/webhooks/{webhook_id}/test proves Shipwell reaches your endpoint and your signature check passes, exactly as for tracking.
  3. Receive updates, no further calls. Whenever a shipment's documents change (retrieval starts, a document arrives or finishes, retrieval completes or fails), a signed documents.updated event is POSTed to your URL, usually within a minute or two. details.documents is the full current collection that GET /documents/{resource_id} returns, with a download link on each file. Apply it with the same rules as tracking: verify the signature, skip an id you have processed, ignore a sequence lower than the highest you have applied for that resource_id and documents.updated (it counts separately from tracking.updated), and replace your copy of the collection.
  4. Download the files, no API call. Each file usually carries content.url, set when that delivery was sent: a Shipwell link valid for about 10 minutes, or the carrier's own link. Download it as soon as the event arrives. If a file has content: null, or the link fails, call the document's base64_link with your API key: it returns the files inline. File content is never inside the webhook itself, so its size stays small.
  5. Pull when you need to. GET /documents/{resource_id} returns the current collection; it carries no sequence, so a delivery retried across your pull may hold an older collection: pull again after applying any delivery that arrives after a pull. A finished collection can reopen when Shipwell retrieves the documents again, so a later delivery may go back from is_terminal: true to false: apply it by sequence like any other.
Copyright © Shipwell 2025. All right reserved.