Subscribe to webhooks
Webhooks push order, item, and inventory events from Grasshopper to your systems the moment they happen. Every shipper account includes a self-service Integrations module, so your team can add, edit, and remove webhook subscriptions on its own: no code, no support ticket, and changes go live immediately.
See Topics for every event you can subscribe to, grouped by category, plus a recommended starter set for retail integrations.
How it works
A webhook subscription pairs one event with one endpoint URL. When that event fires anywhere in the platform, Grasshopper sends an HTTP request to your URL with a JSON payload describing the order or item, plus any custom headers you configured.
- Create one subscription per event you care about. You can point several events at the same URL; the
msg_info.topicfield in every payload tells you which event fired. - You can also register multiple endpoints for the same event, for example one per downstream system.
- Subscriptions are scoped to your account. You only receive events for your own orders and items.
Before you start
You need three things:
- A shipper login with access to your account management portal.
- A receiving endpoint on your side: a publicly reachable HTTPS URL that accepts a JSON body and responds with a
2xxstatus within a few seconds. - Your event list. Decide which topics you need. Most retailers start with the seven-topic starter set and expand later.
If your endpoint requires authentication, have the header name and secret value ready; you will enter them as HTTP headers on the subscription.
Add a webhook from your account
1. Open the Integrations module
Sign in to your shipper account, click the gear icon in the top navigation, and choose Integrations.
2. Click Add New Webhook
The Webhooks panel lists every subscription on your account. If you have none yet, the panel shows only the info banner and the button.
3. Fill in the subscription
A new subscription form opens with three fields:
Event Nameorder_status_changed. One event per webhook. The dropdown lists the full topic catalog; the Topics page describes each one.MethodGET, but most integrations should pick POST: the event payload travels in the request body, and many frameworks discard bodies on GET requests. PUT is also supported for endpoints designed that way.URLhttps://hooks.acmehome.com/grasshopper. It must be publicly reachable; deliveries come from Grasshopper's servers, not from your browser.4. Add HTTP headers (optional)
Every key/value pair you add here is sent as an HTTP header on every delivery for this subscription. Use them to make the payload parse cleanly and to authenticate the calls:
Content-Type: application/jsonso your framework parses the body as JSON. Recommended for every subscription.- A shared-secret header such as
X-Webhook-Token: your-secret-value. Your endpoint rejects any request without the expected value. See Verifying webhooks.
Click Add Key/Value Pair for additional headers, and the trash icon next to a pair to remove it.
5. Save
Click Save. The subscription is live immediately; the next time the event fires, Grasshopper calls your endpoint. There is nothing to deploy and no propagation delay.
To test a subscription end to end before wiring in the real event, subscribe a request-inspection URL (your own staging endpoint, or a tool like a request bin) to a low-volume topic, trigger the event on a test order, and inspect what arrives.
Edit or remove a subscription
- Edit reopens the form for that row. Change the event, method, URL, or headers, then Save. The change applies to the next delivery.
- The trash icon at the far right of a row deletes the subscription. Deliveries for that event stop immediately. Deleting a webhook affects nothing else on your account.
There is no undo and no confirmation grace period. Events that fire while a subscription is deleted are not delivered later if you re-create it; use the Orders API to backfill anything you missed.
Manage webhooks with the API
Everything the Integrations panel does is also exposed as REST endpoints, so you can script your webhook setup, sync it from your own admin tools, or manage it per environment in CI. Authenticate with a shipper access token, the same Authorization: Bearer flow as the rest of the API; see Authentication. Requests are scoped to the account that owns the token.
Returns the full catalog of event names you can subscribe to, as a flat array of strings. This is the list behind the Event Name dropdown. The Topics page describes the ones relevant to retailer integrations.
Lists your account's webhook subscriptions. Each entry includes _id, event, url, method, and headers. The _id value is the webhook_id used in the update and delete paths below.
Creates a subscription. Body parameters:
eventorder_status_changed.urlmethodPOST (recommended), GET, or PUT. Stored uppercase regardless of the case you send.headers{ "key": "...", "value": "..." } objects.# Replace {base_url} with the host you use to sign in to your shipper account curl -X POST "https://{base_url}/api/webhook" \ -H "Authorization: Bearer {access_token}" \ -H "Content-Type: application/json" \ -d '{ "event": "order_status_changed", "url": "https://hooks.acmehome.com/grasshopper", "method": "POST", "headers": [ { "key": "Content-Type", "value": "application/json" }, { "key": "X-Webhook-Token", "value": "whsec_9f2d41c0" } ] }'
const res = await fetch("https://{base_url}/api/webhook", { method: "POST", headers: { "Authorization": `Bearer ${accessToken}`, "Content-Type": "application/json" }, body: JSON.stringify({ event: "order_status_changed", url: "https://hooks.acmehome.com/grasshopper", method: "POST", headers: [ { key: "Content-Type", value: "application/json" }, { key: "X-Webhook-Token", value: "whsec_9f2d41c0" } ] }) }); const { data, status } = await res.json();
import requests res = requests.post( "https://{base_url}/api/webhook", headers={"Authorization": f"Bearer {access_token}"}, json={ "event": "order_status_changed", "url": "https://hooks.acmehome.com/grasshopper", "method": "POST", "headers": [ {"key": "Content-Type", "value": "application/json"}, {"key": "X-Webhook-Token", "value": "whsec_9f2d41c0"}, ], }, ) data = res.json()["data"]
{
"data": {
"_id": "6650f2a81c9d440000a1b2c3",
"event": "order_status_changed",
"url": "https://hooks.acmehome.com/grasshopper",
"method": "POST",
"headers": [
{ "key": "Content-Type", "value": "application/json" },
{ "key": "X-Webhook-Token", "value": "whsec_9f2d41c0" }
],
"createdAt": "2026-08-23T09:14:02.511Z"
},
"status": "ok"
}
Updates a subscription. Send only the fields you want to change (event, url, method, headers); everything else keeps its current value.
Deletes a subscription. Deliveries for that event stop immediately.
What your endpoint receives
Deliveries carry a JSON body with two parts: the entity that changed (order for order events, item for line-item and inventory events) and a msg_info envelope identifying the event and the subscription that fired. A trimmed order-event example:
{
"order": {
"order_id": "GH-1004312",
"status": 5,
"service_level": "wg",
"ref_order_number": "PO-88121",
"customer": { ... },
"delivery": { "scheduled_date": "2026-08-27", ... },
"line_items": [ ... ],
"retailer": { "_id": "63f7d2e4a9b8c700123f4a56", "identifier": "ACME" },
"source": "webhook"
},
"msg_info": {
"topic": "order_status_changed",
"subscriber_id": "63f7d2e4a9b8c700123f4a56",
"method": "POST",
"webhook_id": "6650f2a81c9d440000a1b2c3"
}
}
- Route incoming requests on
msg_info.topic, especially if several subscriptions share one URL. msg_info.webhook_idtells you which subscription produced the delivery.- Field-by-field documentation of the
orderanditemobjects is on the Payload page. Status codes are listed under Order statuses.
Delivery and auditing
Every delivery attempt is written to the order's tracking history, visible in the portal and in the API:
- Webhook sent, with the target URL and topic, on success.
- Webhook failed, with the error message and your endpoint's response body, on failure.
This makes delivery debuggable without any extra tooling: open the order, read the timeline, and you can see exactly what was sent where and what your endpoint answered.
A delivery that fails is logged on the order and dropped; there is no automatic retry queue. Acknowledge with a 2xx as fast as you can and process asynchronously. If your endpoint had an outage, reconcile with the Orders API rather than waiting for a redelivery.
Best practices
- Use POST with a Content-Type header. The payload is a JSON body; POST plus
Content-Type: application/jsonworks with every mainstream framework out of the box. - Serve HTTPS with a valid certificate. Payloads include customer contact details; do not receive them in the clear.
- Authenticate every delivery. Add a secret header to the subscription and reject requests without it. Rotate the secret by editing the webhook. More in Verifying webhooks.
- Acknowledge first, process later. Return
2xximmediately and queue the work. Slow endpoints show up as failures in the order timeline. - Be idempotent. Design handlers so processing the same event twice is harmless;
msg_info.topicplusorder.order_idplus the order'supdated_atmakes a good dedupe key. - Start small. The seven-topic starter set covers most tracking needs; add topics as your workflow grows instead of subscribing to everything on day one.
- Keep environments separate. Webhooks are configured per account. Point your staging account at staging endpoints and your production account at production endpoints.