Webhooks

Instead of fetching updates for tracking, batch labels, and transactions manually, you can use Shippo webhooks to get notified when a status changes.

Setting up and testing webhooks

You can set up webhooks on the API settings page of your Shippo web app. This page also allows you to test webhooks with a sample payload. Webhooks Sample Screenshot

We also offer a Webhooks API to allow you to programmatically create, retrieve, edit and delete webhooks. You can access the documentation here. The Webhooks API is currently in beta and the endpoints might change. Please reach out to support@shippo.com if you have questions.

note

When you purchase a label in Shippo, Shippo automatically creates a webhook for tracking that label. You can view the details of that webhook in the API settings page or using the webhooks endpoint.

Webhook event types

  • transaction_created : sent whenever a transaction is created in your account. The POST request body will contain a JSON of the  Transaction object  that was created.
  • transaction_updated : sent whenever a transaction is updated in your account. The POST request body will contain a JSON of the  Transaction object  that was updated.
  • track_updated : for tracking status updates. The POST request body will contain a JSON of the  Tracking object . If you are interested in the types of events returned within the track_updated field, please view more details  here .
    • We regularly request updates from each carrier's system to get the latest status of shipments. Whenever there's a change in status, we immediately send an update to the webhook via a POST request. The frequency of these updates varies among carriers due to the rate limits set by each carrier. On average, users can expect updates within 2 hours of an event occurring. For some carriers this time is much lower.
    • For API version 2017-03-29 and older, the body will contain the  Transaction object  if the label was created on Shippo.
  • batch_created : for creating the Batch object that contain Batch Shipments. This process is done asynchronously, so first you'd get an empty  Batch object  back, then Batch Shipments will be created in the background.
  • batch_purchased : for purchasing Batch Shipments through the Batch endpoint. This request is done asynchronously as well. Once purchases are complete, you will be able to download a merged PDF containing up to 100 labels per file.
  • all : sent when any of the supported events occur. Acts as a catch-all for events.

Additionally, the Shippo-API-Version header is included in all webhook responses to indicate what version of the API is being used.

Webhook metadata

Metadata is additional information you can include in many Shippo objects. For some of these objects (transaction, shipment, and batch), this metadata can be very useful when handling webhook notifications because it allows you to associate your own custom data with the Shippo objects.

The following example shows how to use metadata with a transaction and the resulting webhook payload that is created.

Create a transaction_created webhook

If you do not have one already, create a webhook with event type Transaction Created following the setting up and testing webhooks guide.

Create a transaction

Purchase a label by calling the transactions endpoint. Include the field metadata with a string containing your additional information.

Copy
Copied
url --location --request POST 'https://api.goshippo.com/transactions' \
--header 'Authorization: ShippoToken <API_TOKEN>' \
--header 'Content-Type: application/json' \
--header 'SHIPPO-API-VERSION: 2018-02-08' \
--data-raw '{
  "rate": "a5c9d1bec93149f5bedc3a9374b50970",
  "async": false,
  "label_file_type": "PDF",
  "metadata":"customer_ID:12, order_ID:558a"
}'

Webhook payload

The Shippo API will send a webhook payload to your URL including the metadata you configured in your transaction.

Copy
Copied
{
  "event": "transaction_created",
  "test": true,
  "data": {
    "object_state": "VALID",
    "status": "SUCCESS",
    "object_created": "2024-06-17T14:31:40.000Z",
    "object_updated": "2024-06-17T14:31:40.000Z",
    "object_id": "70ae8117ee1749e393f249d5b77c45e0",
    "object_owner": "mrshippo@shippo.com",
    "test": true,
    "rate": "fe9a78973c5b409498af1fd9baefbe34",
    "tracking_number": "ZW70QJC",
    "tracking_status": "UNKNOWN",
    "eta": "2024-06-22T14:31:40.347Z",
    "tracking_url_provider": "https://tools.usps.com/go/TrackConfirmAction_input?origTrackNum=ZW70QJC",
    "label_url": "https://shippo-delivery.s3.amazonaws.com/70ae8117ee1749e393f249d5b77c45e0.pdf?Signature=vDw1ltcyGveVR1OQoUDdzC43BY8%3D&Expires=1437093830&AWSAccessKeyId=AKIAJTHP3LLFMYAWALIA",
    "commercial_invoice_url": "",
    "messages": [],
    "order": "7535a41cac64426fa87ebfa24ad11123",
    "metadata": "customer_ID:12, order_ID:558a",
    "parcel": "faf460225c4d49699e18384dc32a1cc6",
    "billing": {
      "payments": []
    }
  }
}

On receiving the webhook, you can parse the metadata and use it to update your system, notify users, or trigger other actions. For example, you might use this update to send an automated email to your customer to keep them up to date. This is a common pattern for parcel tracking. The Shippo API also supports metadata in webhooks for tracking labels purchased outside of Shippo.

You can use metadata in this way for any of the supported webhook event types.

Webhook metadata for tracking

Metadata from a transaction does not get passed to your tracking webhook payload. You can add metadata to an existing tracking object by re-registering your tracking webhook.

Use the tracking_number from your transaction response along with your carrier and metadata. This metadata will be included in all webhook payloads associated with tracking updates for this tracking_number.

Copy
Copied
 curl https://api.goshippo.com/tracks/ \
  --header "Authorization: ShippoToken <API_TOKEN>" \
  --header "Content-Type: application/json" \
  --data-raw '{
    "carrier": "usps",
    "tracking_number": "9205590164917312751089",
    "metadata": "Order 000123"
 }'

Webhook POST body example

Copy
Copied
{
  "metadata": "Shippo test webhook",
  "event": "track_updated",
  "data": {
    "test": true,
    "transaction": null,
    "tracking_history": [
      {
        "location": {
          "country": "US",
          "zip": "94103",
          "state": "CA",
          "city": "San Francisco"
        },
        "substatus": null,
        "status_date": "2020-03-08T01:29:06.473Z",
        "status_details": "The carrier has received the electronic shipment information.",
        "status": "UNKNOWN",
        "object_id": "7d7dc41675384da5b0b6d17545fb39d2",
        "object_updated": null,
        "object_created": "2020-03-12T09:49:06.473Z"
      },
      {
        "location": {
          "country": "US",
          "zip": "94103",
          "state": "CA",
          "city": "San Francisco"
        },
        "substatus": null,
        "status_date": "2020-03-09T03:34:06.473Z",
        "status_details": "Your shipment has departed from the origin.",
        "status": "TRANSIT",
        "object_id": "8bbc3b13964e4ac2b0a2e8b69297e98a",
        "object_updated": null,
        "object_created": "2020-03-12T09:49:06.473Z"
      },
      {
        "location": {
          "country": "US",
          "zip": "37501",
          "state": "TN",
          "city": "Memphis"
        },
        "substatus": null,
        "status_date": "2020-03-10T05:39:06.473Z",
        "status_details": "The Postal Service has identified a problem with the processing of this item and you should contact support to get further information.",
        "status": "FAILURE",
        "object_id": "334124a6c1fa4e70a94cd60e9b4e35d8",
        "object_updated": null,
        "object_created": "2020-03-12T09:49:06.473Z"
      },
      {
        "location": {
          "country": "US",
          "zip": "60611",
          "state": "IL",
          "city": "Chicago"
        },
        "substatus": null,
        "status_date": "2020-03-11T07:44:06.473Z",
        "status_details": "Your shipment has been delivered.",
        "status": "DELIVERED",
        "object_id": "a2b1d2301c294226ada274784a76cdb1",
        "object_updated": null,
        "object_created": "2020-03-12T09:49:06.473Z"
      }
    ],
    "tracking_status": {
      "location": {
        "country": "US",
        "zip": "60611",
        "state": "IL",
        "city": "Chicago"
      },
      "substatus": null,
      "status_date": "2020-03-11T07:44:06.471Z",
      "status_details": "Your shipment has been delivered.",
      "status": "DELIVERED",
      "object_id": "2d3d646335e449a8b0308f798970d045",
      "object_updated": null,
      "object_created": "2020-03-12T09:49:06.471Z"
    },
    "metadata": null,
    "messages": [],
    "carrier": null,
    "tracking_number": "SHIPPO_DELIVERED",
    "address_from": {
      "country": "US",
      "zip": "94103",
      "state": "CA",
      "city": "San Francisco"
    },
    "address_to": {
      "country": "US",
      "zip": "60611",
      "state": "IL",
      "city": "Chicago"
    },
    "eta": "2020-03-11T09:49:06.459Z",
    "original_eta": "2020-03-10T09:49:06.459Z",
    "servicelevel": {
      "name": null,
      "token": "shippo_priority"
    }
  },
  "carrier": "shippo",
  "test": true
}

Expected webhook behavior

Shippo expects your Webhook endpoint to return a 2XX HTTP status code in a timely manner (three seconds or less) to indicate that the POST payload has been received. If your Webhook endpoint does not process the payload in a timely manner or you return a 408, 429, or 5XX status code, Shippo will retry twice. No retry is attempted upon other client error status codes (4XX).

Debugging

Using your own server

If you have a public-facing webserver and would like to view the test events as they come in, you can use this BASH one-liner (listening on port 8891). This snippet returns the HTTP 200 response we expect your endpoint to return in production. (Note that you do not need to have JQ installed as this is just for pretty printing the POST Body response.)

Jq formatting for webhook test listener:

~$ while true; do { echo -e 'HTTP/1.1 200 OK\r\n'; } | nc -l 8891 | grep test | jq . ; done

Webhooks Debugging Screenshot

Using webhook testing sites

There are many websites available to test a webhook response. You can use sites like https://webhook-test.com/ to listen for webhooks sent by Shippo.

note

While you can test your webhooks using public services, it's important to understand that you are sharing your information with these third-parties. Only use test data. Never share production data. We recommend using your own server where possible.

The mention of a specific company or product name is solely for educational purposes and does not imply endorsement by Shippo.

To use a service like webhook-test, copy the unique webhook URL from the site and add it as the URL to your Shippo webhook.

Selecting Send sample sends a test payload that you can view in the webhook testing site.

webhook testing website sample