Skip to main content

gopuff-webhooks

Receive and verify Gopuff (Powered by Gopuff partner API) webhooks. Use when setting up a Gopuff webhook handler, debugging svix-id / svix-timestamp / svix-signature verification, or handling order.status, order.status.v2 and order.delivered events, delivery status (driver location) and delivery ETA updates.

Source facts

Repository
hookdeck/webhook-skills
Last source activity
October 21, 2026 at 13:56
Detected SKILL.md language
English
Stars
100
Forks
16

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
20 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
gopuff-webhooks
description
Receive and verify Gopuff (Powered by Gopuff partner API) webhooks. Use when setting up a Gopuff webhook handler, debugging svix-id / svix-timestamp / svix-signature verification, or handling order.status, order.status.v2 and order.delivered events, delivery status (driver location) and delivery ETA updates.
license
MIT
metadata
{"author":"hookdeck","version":"0.1.0","repository":"https://github.com/hookdeck/webhook-skills"}
# Gopuff Webhooks Gopuff's partner API (Powered by Gopuff) sends webhooks about order fulfillment: order status changes, driver location and delivery ETA. Endpoints are registered in the **Svix App Portal**, which signs every delivery. Gopuff's own pages have no signature section; the scheme comes from [Svix's manual verification guide](https://docs.svix.com/receiving/verifying-payloads/how-manual). ## When to Use This Skill - How do I receive Gopuff webhooks? - How do I verify Gopuff webhook signatures (`svix-signature`)? - How do I handle `order.status.v2` or `order.delivered` events? - How do I get the Svix App Portal link for my Gopuff partner account? - Why is my Gopuff webhook signature verification failing? ## Verification (core) Each request carries `svix-id`, `svix-timestamp` (Unix seconds) and `svix-signature` (space-delimited `v1,<base64>` entries). The signed content is `{svix-id}.{svix-timestamp}.{raw body}`, HMAC-SHA256 with the base64-decoded part of the `whsec_` secret, base64-encoded. Use the raw body, never re-serialized JSON. ```javascript import crypto from 'node:crypto'; // toleranceSec = 0 (default) skips the timestamp window, because Hookdeck retries and replays // keep the original svix-timestamp. A positive value opts in. function verify(rawBody, { id, timestamp, signature }, secret, toleranceSec = 0) { if (!/^\d+$/.test(timestamp ?? '')) return false; if (toleranceSec > 0 && Math.abs(Date.now() / 1000 - Number(timestamp)) > toleranceSec) return false; const key = Buffer.from(secret.split('_')[1], 'base64'); // decode after "whsec_" const expected = crypto.createHmac('sha256', key) .update(`${id}.${timestamp}.`).update(rawBody).digest(); return signature.split(' ').some((entry) => { const [version, sig] = entry.split(','); const got = Buffer.from(sig ?? '', 'base64'); return version === 'v1' && got.length === expected.length && crypto.timingSafeEqual(got, expected); }); } ``` The examples verify the same way and also accept the white-labeled `webhook-*` headers. **Why not the `svix` SDK?** `new Webhook(secret).verify(...)` (npm) and `Webhook(secret).verify(...)` (PyPI) check the same signature, but they always enforce a 5-minute timestamp window with no way to turn it off. Hookdeck retries and replays carry the original `svix-timestamp`, so the SDK rejects them. The examples verify manually and make the window opt-in with `GOPUFF_TIMESTAMP_TOLERANCE_SECONDS` (default `0`; a positive number of seconds turns it on; anything that isn't a whole number is treated as `0`, with a warning at startup). If you never retry or replay late, the SDK is fine. > **For complete handlers with tests**, see [examples/express/](examples/express/), [examples/nextjs/](examples/nextjs/), [examples/fastapi/](examples/fastapi/). ## Common Event Types Event types you select in the Svix App Portal (from Gopuff's [webhook docs](https://devportaldocs.poweredbygopuff.com/#/webhooks/introduction)): | Event Type | Description | |------------|-------------| | `order.status.v2` | Order status changed (recommended; slim payload) | | `order.status` | Order status changed (full order object; end of support 08/15/2025) | | `order.delivered` | Order successfully delivered | Order statuses: `Pending` (no event sent), `Packing_Now`, `Packed`, `Delivery`, `Finished`, `Cancelled`. Gopuff also documents Delivery Status (driver location) and Delivery ETA payloads but does not list event-type strings for them. **The payloads contain no event-type field**, and Svix sends no event-type header. The examples tell payloads apart by shape (`order`, `driver`, `expected_delivery_time`). Always keep a default branch for unknown shapes. ## Environment Variables ```bash GOPUFF_WEBHOOK_SECRET=whsec_xxxxx # Svix App Portal > Endpoints > Signing Secret GOPUFF_TIMESTAMP_TOLERANCE_SECONDS=0 # Optional replay window; a positive value opts in ``` ## Local Development ```bash npx hookdeck-cli listen 3000 gopuff --path /webhooks/gopuff ``` No account required. Use the printed URL as the endpoint URL in the App Portal. (FastAPI example: port 8000.) ## Reference Materials - [references/overview.md](references/overview.md) - Events, payloads, order status flow - [references/setup.md](references/setup.md) - App Portal link, endpoint, secret - [references/verification.md](references/verification.md) - Signature details and debugging ## Recommended: webhook-handler-patterns - [Handler sequence](https://github.com/hookdeck/webhook-skills/blob/main/skills/webhook-handler-patterns/references/handler-sequence.md) - [Idempotency](https://github.com/hookdeck/webhook-skills/blob/main/skills/webhook-handler-patterns/references/idempotency.md) - [Error handling](https://github.com/hookdeck/webhook-skills/blob/main/skills/webhook-handler-patterns/references/error-handling.md) - [Retry logic](https://github.com/hookdeck/webhook-skills/blob/main/skills/webhook-handler-patterns/references/retry-logic.md) ## Related Skills - [svix-webhooks](https://github.com/hookdeck/webhook-skills/tree/main/skills/svix-webhooks) - The Svix signing scheme in general - [guesty-webhooks](https://github.com/hookdeck/webhook-skills/tree/main/skills/guesty-webhooks) - Another Svix-delivered provider - [clerk-webhooks](https://github.com/hookdeck/webhook-skills/tree/main/skills/clerk-webhooks) - Svix-signed auth events - [nash-webhooks](https://github.com/hookdeck/webhook-skills/tree/main/skills/nash-webhooks) - Delivery and logistics webhooks - [aftership-webhooks](https://github.com/hookdeck/webhook-skills/tree/main/skills/aftership-webhooks) - Shipment tracking webhooks - [shopify-webhooks](https://github.com/hookdeck/webhook-skills/tree/main/skills/shopify-webhooks) - Commerce order webhooks - [webhook-handler-patterns](https://github.com/hookdeck/webhook-skills/tree/main/skills/webhook-handler-patterns) - Idempotency, error handling, retry logic - [hookdeck-event-gateway](https://github.com/hookdeck/webhook-skills/tree/main/skills/hookdeck-event-gateway) - Production webhook infrastructure
View on GitHub