If you are building an application that relies on constant updates for your Nash deliveries, then integrating a Nash webhook will help you receive real-time delivery events.
At Nash, we support a few webhooks types. The webhook response will include 3 fields:
type
field. Webhook types can be of type delivery
, task
, courier_location
.
event
field which can be one of several possible statuses (see below).
data
field which is a Job object, similar to the Create Job endpoint or see the example below.
To set up a webhook, you can do so in the Webhook Management page in the Nash Portal. Here, you can filter by event type and add multiple endpoints if you want to send different events to different endpoints, for example. All event schemas and types are enumerated under the Event Catalog tab. Select events will have example payloads. Note that event schemas are assumed to be batch jobs. If your job is not a batch job, there will be no key “batch” and you’ll see "isBatch": false
, both nested under the key “data”.
We support webhooks in both sandbox and production environments. Failed webhook requests will be retried according to our retry policy and are sent securely.
type=delivery
:
Frequency: once per state transition (e.g., from created
-> assigned_driver
, or dropoff_arrived
-> dropoff_complete
)
Guaranteed events: created
, assigned_driver
, pickup_enroute
, pickup_arrived
, dropoff_enroute
, dropoff_arrived
, dropoff_complete
(guaranteed events may be inferred from future events)
Events:
type=task
:
Frequency: once per state transition (e.g., from running -> completed)
Events:
type=courier_location
:
Events:
-updated
Frequency: once every 1-2 minutes (if courier_location is available)
Here’s a sample response that you can expect from our webhook for an ongoing delivery:
Note: All timestamps are in UTC and in this format “%Y-%m-%dT%H:%M:%S.%f”.
{
"type": "delivery",
"event": "dropoff_complete",
"data": {
"id": "job_R7FXJrfB99bpvpzf6CriJC",
"createdAt": "2022-03-05T01:11:51.078927",
"portalUrl": "https://portal.usenash.com/active/job_R7FXJrfB99bpvpzf6CriJC",
"externalIdentifier": null,
"jobMetadata": {},
"isActive": false,
"jobConfigurations": [
{
"package": {
"description": "Test package description",
"pickupEndTime": null,
"pickupStartTime": "2022-03-05T01:16:51",
"dropoffStartTime": null,
"dropoffEndTime": null,
"valueCents": 100,
"taxCents": 950,
"serviceFeeCents": null,
"itemsCount": 1,
"pickupLocation": {
"id": "loc_dB4x4pToexhgRvGhZSTHaQ",
"address": "185 University Ave, Palo Alto, CA 94301",
"formattedAddress": "185 University Ave, Palo Alto, CA 94301, USA",
"addressNumber": "185",
"addressFormattedStreet": "University Ave",
"addressCity": "Palo Alto",
"addressCountry": "US",
"addressState": "CA",
"addressZip": "94301",
"addressCounty": "Santa Clara County",
"businessName": "Test pickup Business",
"instructions": "Test pickup Instructions",
"firstName": "Test pickup FirstName",
"lastName": "Test pickup LastName",
"phoneNumber": "+12345679012",
"email": null
},
"dropoffLocation": {
"id": "loc_5heYem2xKGfNt9twg33kcT",
"address": "401 San Antonio Rd, Mountain View, CA 94040",
"formattedAddress": "401 San Antonio Rd, Mountain View, CA 94040, USA",
"addressNumber": "401",
"addressFormattedStreet": "San Antonio Rd",
"addressCity": "Mountain View",
"addressCountry": "US",
"addressState": "CA",
"addressZip": "94040",
"addressCounty": "Santa Clara County",
"businessName": "Test dropoff Business",
"instructions": "Test dropoff Instructions",
"firstName": "Test dropoff FirstName",
"lastName": "Test dropoff LastName",
"phoneNumber": "+12345679019",
"email": null
}
},
"tasks": [
{
"id": "tsk_7xKGR6PW2pBtuTeRg2b7Bw",
"createdAt": "2022-03-05T01:11:51.078927",
"status": "COMPLETED",
"providerId": "FleetSimulator",
"tipAmountCents": 250,
"winnerQuote": {
"id": "qot_nh5VSwxr4trHsuKHpQbGW6",
"providerId": "FleetSimulator",
"providerName": "FleetSimulator"
},
"quotes": [
] {
"id": "qot_nh5VSwxr4trHsuKHpQbGW6",
"providerId": "FleetSimulator",
"providerName": "FleetSimulator",
"providerLogo": "https://nash-provider-logos.s3.amazonaws.com/FleetSimulator.png",
"createdTime": "2022-03-05T01:11:52.417462",
"expireTime": "2022-03-05T02:11:52.417463",
"nashFeeCents": 100,
"priceCents": 0,
"currency": "USD",
"pickupWindow": null,
"dropoffEta": "2022-03-05T01:17:52.417416",
"tollFeeCents": 0,
"insuranceFeeCents": 0,
"totalPriceCents": 0
}
],
"failedQuotes": [],
"delivery": {
"id": "dlv_MwQDy3s6ajvw5aQ7eQPt7i",
"status": "DROPOFF_COMPLETE",
"isActive": false,
"pickupEta": null,
"dropoffEta": "2022-03-05T01:17:52.417416",
"dropoffDeadline": null,
"currency": "USD",
"documents": [
{
"id": "doc_ELre5GCELQ6w3UHKAgbm6F",
"type": "SHIPPING_LABEL",
"url": "https://nash-documents-dev.s3-us-west-1.amazonaws.com/dlv_bR7NWwhWSQRohyjs7UZd7D_fEavuZda787M70sJEhtCAA==.png",
"data": null,
"contentType": "image/png"
},
{
"id": "doc_nuKEL5W8mMgnXuRrFqwwsc",
"type": "PICKUP_LABEL",
"url": "https://nash-documents-dev.s3-us-west-1.amazonaws.com/dlv_bR7NWwhWSQRohyjs7UZd7D_QPiARbKwfJRkC94KVQrT8w==.png",
"data": null,
"contentType": "image/png"
}
],
"nashFeeCents": 100,
"priceCents": 0,
"courierName": "Tjy Ifulu",
"courierPhoneNumber": "+13408480904",
"courierLocation": {
"lat": 37.4043247,
"lng": -122.1112215
},
"courierProfileImage":"https://nash-proof-of-delivery-sandbox.s3-us-west-1.amazonaws.com/dlv_SXnvEsXY4aEQ5YVY92sLPK_4t9WSOg3Zw-h4BT0fFUWqw==.jpg",
"proofOfDelivery": [
{
"type": "photo_proof_of_delivery",
"url": "https://nash-proof-of-delivery-sandbox.s3-us-west-1.amazonaws.com/dlv_SXnvEsXY4aEQ5YVY92sLPK_4t9WSOg3Zw-h4BT0fFUWqw==.jpg",
"size": 12421
},
{
"type": "barcode_scan",
"text": "pkg_SggEeiudfNRQDvtAF35qPr",
"url": "https://nash-proof-of-delivery-dev.s3-us-west-1.amazonaws.com/dlv_JJUqcMDdxDxoj6Zsk8iru3_rp_nNJtdAVItcnBpKxTHBQ==..png",
"size": 566,
}
],
"statusHistory": [
{
"createdAt": "2022-03-05T01:12:00.984078",
"status": "created"
},
{
"createdAt": "2022-03-05T01:12:16.067396",
"status": "not_assigned_driver"
},
{
"createdAt": "2022-03-05T01:13:02.459762",
"status": "assigned_driver"
},
{
"createdAt": "2022-03-05T01:14:32.532602",
"status": "pickup_enroute"
},
{
"createdAt": "2022-03-05T01:15:17.533789",
"status": "pickup_complete"
},
{
"createdAt": "2022-03-05T01:16:02.598233",
"status": "dropoff_enroute"
},
{
"createdAt": "2022-03-05T01:17:32.690484",
"status": "dropoff_arrived"
},
{
"createdAt": "2022-03-05T01:18:17.945368",
"status": "dropoff_complete"
}
],
"tollFeeCents": 0,
"waitFeeCents": 0,
"waitTimeMinutes": 0,
"cancellationFeeCents": 0,
"returnFeeCents": 0,
"insuranceFeeCents": 0,
"taxAmountCents": 0,
"totalPriceCents": 0
},
"failureReason": null
}
]
}
]
}
}
Best Practices
Nash jobs can include multiple delivery attempts (see Job Overview). When processing our webhook updates, please ensure that cancellations
/ failures of one task does not cause issues in your application.
Furthermore, since there are multiple tasks, you should be prepared to handle multiple instances of the same
webhook event. For example, if a job has two tasks - one assigned to Fleet A and another assigned to Fleet B -
both fleets might send pickup arrived
events. Refer to this section for more details on the guaranteed statuses we will send.
You should also be prepared for some fleets erroneously sending statuses such as pickup complete
or
dropoff complete
when their drivers have not completed a delivery yet.
Verifying Webhooks
We use a service called Svix to send webhooks. Svix prevents attacks and forgeries by signing webhook requests, and also handles retries.
How to Verify
To verify the webhook signature and ensure the request genuinely came from Nash via Svix, you have a couple of options:
- Use the Svix SDKs: The recommended approach is to use the official Svix SDKs for your language/framework. These libraries handle signature verification and timestamp checks automatically.
- Manually Verify: You can manually verify the signature using the request headers (
svix-id
, svix-timestamp
, svix-signature
) and your endpoint’s signing secret. You will also need to implement the timestamp check yourself to prevent replay attacks.
You’ll need the signing secret, which can be found in the Nash Portal under Settings > Webhook Management > Click on an Endpoint > Signing Secret.
Firewall Configuration (Static IP Addresses)
If your webhook receiving endpoint is behind a firewall or NAT, you may need to explicitly allow traffic from Svix’s IP addresses. webhooks will originate from the following IP addresses: https://docs.svix.com/receiving/source-ips
Retry Policy
A webhook retry is an attempt by Svix to re-send a webhook message that previously failed to be delivered to your endpoint (e.g., due to a network error, server error (5xx), or certain 4xx errors like 408, 409, 429 on your end). Our automatic retry schedule is approximately as follows:
- Immediately
- 5 seconds
- 5 minutes
- 30 minutes
- 2 hours
- 5 hours
- 10 hours
- Another 10 hours
Reference: https://docs.svix.com/retries
You can also manually trigger retries for specific messages or automatically retry (“Recover”) all failed messages starting from a given date via the Nash Portal (Webhook Management > Select Endpoint > Attempts).