Order Webhooks
Gett drives the order lifecycle by POSTing synchronously to two endpoints on your system. You respond with the order body (including your server-computed amounts); Gett waits for your reply before continuing. These are not fire-and-forget events — every delivery is a blocking RPC.
These Commerce API webhooks are a separate system from the Distribution Partner async event webhooks. They use a different signing scheme (Standard Webhooks) and a different interaction model (synchronous request/response vs. fire-and-forget).
Endpoints
Gett POSTs to {baseUrl}/validate and {baseUrl}/place, where baseUrl is the Webhook Base URL you provide during onboarding.
| Path | Purpose | When called |
|---|---|---|
{baseUrl}/validate | Price and availability check | Before the customer pays |
{baseUrl}/place | Place the order | After successful payment |
Both endpoints receive the same order body shape (see Request body). The /place body additionally carries paymentToken when Gett tokenized the card on the partner's behalf (see Payment token).
Request body
The request body is the order represented as a StandardOrderWebhook object — an ExternalOrder extended with an optional paymentToken. Field-level schemas live in the Commerce API Reference: ExternalOrder (the /validate body) and StandardOrderWebhook (the /place body). The validateOrder / placeOrder summaries are also listed under Webhooks on the reference overview.
Validate — example request body
All IDs are UUIDs. Monetary amounts are decimal major units (e.g. 24.00 = $24.00) — not minor units. Every lineItem carries a modifierGroups array (empty when the item has no modifiers).
Code
Place — example request body
Identical to validate, plus paymentToken when Gett performed Braintree tokenization:
Code
Payment token
paymentToken is a Braintree single-use payment-method nonce. It is present on /place only when your store has a Braintree tokenization key configured — Gett tokenizes the customer's saved card against your Braintree account and sends you the nonce to charge. When absent, payment falls back to your own tokenization flow.
Treat the payment token as a secret
The nonce is a short-lived, single-use payment credential — usable for up to a few hours until it is consumed. Use it once over TLS to charge, then discard it. Gett masks paymentToken in its own logs and distributed traces, and you must do the same: never write the raw value to logs, traces, or analytics. If you need a reference for reconciliation, keep only non-sensitive descriptors (e.g. card type or last four), never the nonce itself.
Response body
Respond with the same order shape, filling in the server-authoritative amounts and any errors. HTTP 200 with a valid body is the success signal; any non-2xx triggers Gett's retry policy.
Amounts ownership
| Field | Owner | Rule |
|---|---|---|
subTotal | Gett | Echo verbatim |
tip | Gett | Echo verbatim |
fees | Partner | Set authoritatively; Gett stores your value |
taxes | Partner | Set authoritatively; Gett stores your value |
Example success response
Code
Example error response (still HTTP 200)
Return errors inline on 200 — do not use 4xx for business-logic rejections (item unavailable, store closed, etc.). Reserve non-2xx for infrastructure failures.
Code
Security — Standard Webhooks signing
Gett signs every outbound webhook per the open Standard Webhooks spec. Because the spec is open, you can verify signatures using off-the-shelf libraries (e.g. standardwebhooks on npm, standardwebhooks on PyPI) rather than writing verification code by hand.
Headers Gett sends
| Header | Value |
|---|---|
Authorization | Bearer <apiKey> — authenticates Gett to your endpoint |
Idempotency-Key | Stable GUID for this delivery (reused across retries; use it for dedup) |
webhook-id | Stable message ID (same value as Idempotency-Key for this delivery) |
webhook-timestamp | Unix timestamp in seconds of this delivery attempt |
webhook-signature | Space-delimited list of v1,<base64> signatures (see below) |
Signature algorithm
The signed content is:
Code
For each active signing secret, Gett computes:
Code
where key is the base64-decoded bytes of the part after whsec_ in your secret (e.g. if your secret is whsec_ABC123==, the HMAC key is base64Decode("ABC123==")).
The webhook-signature header contains one v1,<base64> entry per active secret, space-delimited. This enables zero-downtime secret rotation: during a rotation overlap window both the old and new secret produce a signature; your verifier accepts whichever one it currently holds.
Verifying with a library (recommended)
Code
Verifying manually (TypeScript / Node.js)
Code
Verifying manually (Python)
Code
Always verify signatures
Never process an order webhook without verifying the signature and checking the timestamp. Reject requests with missing, invalid, or stale signatures with a 401 response.
Idempotency
Gett retries failed deliveries. Use Idempotency-Key (or webhook-id — they carry the same value) to deduplicate: if you have already processed this key, return 200 with the previously computed result rather than placing the order again.
Retry policy
Gett retries failed webhook deliveries with exponential backoff:
| Attempt | Delay |
|---|---|
| 1st retry | 30 seconds |
| 2nd retry | 2 minutes |
| 3rd retry | 10 minutes |
| 4th retry | 1 hour |
| Final retry | 6 hours |
A delivery is considered failed if your endpoint returns a non-2xx status code or does not respond within 30 seconds.
Best practices
- Respond as quickly as possible; the timeout is 30 seconds
- Always verify the signature before reading the body
- Use
Idempotency-Key/webhook-idto deduplicate retried deliveries - Return inline
errorson HTTP200for business-logic rejections; reserve non-2xxfor infrastructure failures - Log the full request including all headers for debugging