Several types of objects are processed asychronously in the EasyPost system (Batches, Trackers, etc.). In order to update users with the status of these background tasks, EasyPost dispatches a webhook event whenever a new Event occurs. Webhooks are push notifications, or callbacks, which allow users to stay up-to-date on the status of their EasyPost objects without needing to poll for updates. Whenever a webhook is triggered, an Event is sent via HTTP POST to each configured webhook URL. Each of these webhooks expect a successful response; in the case of a failure, the EasyPost system will attempt to retry the webhook.

In order to take advantage of webhooks, all you need to do is add your webhook urls to your account page. The way these webhook Events are processed will be specific to your application, but below is an example of a request's JSON body and a simple Sinatra application that removes problematic shipments from a Batch.

Webhook POST JSON

{
  "mode": "production",
  "description": "batch.created",
  "previous_attributes": {"state": "purchasing"},
  "pending_urls": ["example.com/easypost-webhook"],
  "completed_urls": [],
  "created_at": "2015-12-03T19:09:19Z",
  "updated_at": "2015-12-03T19:09:19Z",
  "result": {
    "id": "batch_b3b885c63c22887ab8881f2b12898379",
    "object": "Batch",
    "mode": "production",
    "state": "purchased",
    "num_shipments": 1,
    "reference": null,
    "created_at": "2015-12-03T19:09:19Z",
    "updated_at": "2015-12-03T19:09:19Z",
    "scan_form": null,
    "shipments": [
      {
        "batch_status": "postage_purchased",
        "batch_message": null,
        "id": "shp_a5b1348307694736aaqqqq8fqda53f93"
      }
    ],
    "status": {
      "created": 0,
      "queued_for_purchase": 0,
      "creation_failed": 0,
      "postage_purchased": 1,
      "postage_purchase_failed": 0
    },
    "pickup": null,
    "label_url": null
  },
  "id": "evt_6daa0e2b50bc4219b2525a8232bbd24b",
  "object": "Event"
}
        

Receiving a Webhook Example

require "easypost"
require "sinatra"

post "/easypost-webhook" do
  result = params["result"]

  case result["object"]
  when "Batch"
    batch = EasyPost::Batch.new(result)

    case batch.state
    when "purchase_failed"
      batch.shipments.each do |shipment|
        if shipment.batch_status == "postage_purchase_failed"
          batch.remove_shipments([shipment])
        end
      end
    end
  end
end
          

A great way to learn more about the contents of each webhook Event is by using RequestBin. RequestBin bins are easy to create, and they provide you with a URL that you can use to collect webhook requests made by EasyPost and inspect their contents.

Authentication

Currently, our recommended best practice for securing webhooks involves using basic authentication and HTTPS on your endpoint. This will help prevent any altering of any information communicated to you by EasyPost, and it will prevent any third parties from masquerading as EasyPost and sending fraudulent data. https://username:secret@www.example.com/easypost-webhook is an example of how you could add basic authentication to your Webhook URL.

Frequently Asked Tracking Questions:

How many times will EasyPost attempt to deliver the webhook Event to my URL endpoint?
After 6 failures, EasyPost will no longer attempt to send the webhook. There is an increasing delay between retries.
What HTTP status code do I need to return?
You should return a status code of 2XX. A 200 is preferred.
How long do I have to respond?
You must respond within 7 seconds. If no response is sent back, the webhook Event will be considered a failure and it will be sent again. It is a best practice to receive the webhook and send the Event to be processed by a background worker; this allows you to immediately return a successful response so you do not receive the webhook a second time.
How can I test my webhook integration?
All asynchronous actions that trigger webhooks in Production will also trigger webhooks in Test. For example, you could create a Test Tracker or purchase a Test Shipment. If you are developing locally and need a public URL for your webhooks, you can set one up at requestb.in.
Can I receive webhooks for packages not shipped through EasyPost?
In order to receive webhooks for packages not shipped through EasyPost, all you need to do is create an EasyPost Tracker object with the desired tracking code. Tracker objects send webhooks whenever new tracking Events are detected.
How can I retry failed Events?
Currently there is not a way to retry failed Events.
How many webhook endpoints can I designate?
Most users use 1-5, but you can setup up to 100 webhook endpoints. If you need more, just let us know.