Webhook
Each Webhook
contains the url
that EasyPost notifies when an object in the system updates.
Several types of objects are processed asynchronously within EasyPost. When an object updates, an Event
is sent via HTTP POST
to each configured
webhook url
. The webhook
object supports create, retrieve, update, and delete (CRUD) operations.
For best practices and request sanitation, refer to the Webhooks Guide.
Webhook endpoints must return a 2XX status code
to indicate successful receipt. A 200 OK
response is preferred. Endpoints that repeatedly return failures may be
automatically disabled; disabled webhooks can be re-enabled using the Webhook
update endpoint.
Securing webhook endpoints is crucial to ensure data integrity and authenticity. EasyPost recommends two primary methods for securing webhooks:
HMAC validation ensures webhook data is untampered during transmission.
- Include a
webhook_secret
when creating or updating a webhook. - EasyPost generates a signature with this secret, sent via the
X-Hmac-Signature
header in each event. - Validate the signature using
validate_webhook()
from EasyPost’s client libraries (function name may vary depending on the programming language; refer to the library documentation). - If the signature does not match, reject the event to prevent fraudulent data.
Basic authentication requires embedding a username and password in the webhook URL.
Example
https://username:secret@example.com/easypost-webhook
Each webhook delivery includes an Authorization
header. Validate the credentials against the stored values.
EasyPost performs certificate validation and requires that any webhook recipient using TLS (HTTPS) must have a certificate signed by a trusted public certification authority. This helps ensure that the data being transmitted is secure.
- Webhook endpoints must use
HTTPS
. - SSLv2, SSLv3, and export-grade ciphers are not supported.
For server setup guidance, refer to:
Webhook
was most recently disabled (if any){
"id": "hook_d31edbc62d1511f0a15761d2f710980c",
"object": "Webhook",
"mode": "test",
"url": "http://example.com",
"created_at": "2025-05-09T20:40:21Z",
"disabled_at": null,
"custom_headers": [
{
"name": "X-Header-Name",
"value": "header_value"
}
]
}
EasyPost supports optional custom headers on outbound webhook requests, allowing up to three custom headers. Each header must include a name
and
value
, both as ASCII strings under 1000 characters.
- Custom headers must be an array of key-value pairs.
- Each
name
must be unique within the list. - If specified in a
POST
orPATCH
request, bothname
andvalue
are mandatory. - Headers prefixed with
X-EasyPost-*
cannot be used. - Existing
X-*
standard name or non-standardX-*
headers may be overwritten if a conflict exists. - Header values are stored in plaintext. Use encrypted values if sensitive information is included.
Updating replaces the entire custom_headers
list. Partial updates are not supported.
All custom header names must conform to RFC 7230/ RFC 9112 formatting rules.
To create a Webhook
, provide a url
parameter to designate where notifications are sent. A webhook can be secured using a webhook_secret
for HMAC validation or basic authentication. The optional custom_headers
attribute enables the inclusion of additional header information, such as authentication tokens or metadata, with outbound webhook requests.
Request Parameters
1curl -X POST https://api.easypost.com/v2/webhooks \
2 -u "EASYPOST_API_KEY": \
3 -H 'Content-Type: application/json' \
4 -d '{
5 "webhook": {
6 "url": "example.com",
7 "webhook_secret": "A1B2C3",
8 "custom_headers": [{
9 "name": "X-Header-Name",
10 "value": "header_value"
11 }],
12 }
13 }'
1{
2 "id": "hook_d31edbc62d1511f0a15761d2f710980c",
3 "object": "Webhook",
4 "mode": "test",
5 "url": "http://example.com",
6 "created_at": "2025-05-09T20:40:21Z",
7 "disabled_at": null,
8 "custom_headers": [
9 {
10 "name": "X-Header-Name",
11 "value": "header_value"
12 }
13 ]
14}
Retrieve an unpaginated list of all Webhooks
associated with the API Key
.
1curl -X GET https://api.easypost.com/v2/webhooks \
2 -u "EASYPOST_API_KEY":
1{
2 "webhooks": [
3 {
4 "id": "hook_d393bda62d1511f09d140fc7cf06773a",
5 "object": "Webhook",
6 "mode": "test",
7 "url": "http://example.com",
8 "created_at": "2025-05-09T20:40:22Z",
9 "disabled_at": null,
10 "custom_headers": [
11 {
12 "name": "X-Header-Name",
13 "value": "header_value"
14 }
15 ]
16 }
17 ]
18}
Retrieve a Webhook
by id
.
1curl -X GET https://api.easypost.com/v2/webhooks/hook_... \
2 -u "EASYPOST_API_KEY":
1{
2 "id": "hook_d34edeb62d1511f0b31155abe820005a",
3 "object": "Webhook",
4 "mode": "test",
5 "url": "http://example.com",
6 "created_at": "2025-05-09T20:40:21Z",
7 "disabled_at": null,
8 "custom_headers": [
9 {
10 "name": "X-Header-Name",
11 "value": "header_value"
12 }
13 ]
14}
Re-enable a disabled Webhook
or update the webhook_secret
and custom_headers
.
Request Parameters
1curl -X PATCH https://api.easypost.com/v2/webhooks/hook_... \
2 -u "EASYPOST_API_KEY": \
3 -H 'Content-Type: application/json' \
4 -d '{
5 "webhook_secret": "A1B2C3",
6 "custom_headers": [{
7 "name": "X-Header-Name",
8 "value": "header_value"
9 }],
10 }'
1{
2 "id": "hook_d3d8d0ee2d1511f08c9a6175d1cdccad",
3 "object": "Webhook",
4 "mode": "test",
5 "url": "http://example.com",
6 "created_at": "2025-05-09T20:40:22Z",
7 "disabled_at": null,
8 "custom_headers": [
9 {
10 "name": "X-Header-Name",
11 "value": "header_value"
12 }
13 ]
14}
Delete a Webhook
by id
.
1curl -X DELETE https://api.easypost.com/v2/webhooks/hook_... \
2 -u "EASYPOST_API_KEY":
1{}