Webhooks
We POST a JSON event to your https endpoint when something happens, signed with that endpoint’s secret following Standard Webhooks, the format OpenAI, Twilio and Resend use.
Events
Section titled “Events”| Event | When | data |
|---|---|---|
lead.created |
A buyer or dealer saves a build (“Get my build”) | lead_id, build_id, dealership, vehicle, items, total, weekly, currency, marketing_consent, status, updated_at |
build.created |
The same moment, without the person (for analytics) | build_id, vehicle, items, total, currency, created_at |
quote.sent |
The quote is emailed to the buyer | lead_id, build_id, dealership, status: "sent", total, currency, updated_at |
lead.won |
A dealer marks the deal won | lead_id, build_id, dealership, status: "won", total, currency, updated_at |
With Include customer details on for the endpoint, lead.created, quote.sent and lead.won also
carry customer (name, email, mobile), rego and salesperson. build.created never does.
{ "id": "evt_d1024fc881e9becfc1c23952", "type": "lead.created", "timestamp": "2026-09-30T06:03:22.982Z", "api_version": "2026-10-01", "tenant": "yourbrand", "data": { "lead_id": "lead_542", "build_id": "bld_497c186a9058f43189e75b3ab5af4495", "dealership": "Norris Group", "vehicle": { "name": "Toyota Hilux Double Cab SR5 2026", "colour": "Crystal Pearl" }, "items": [ { "sku": "G4X4-GLASSCANOPY-HILUX", "name": "Alloy Canopy, Lift-up Glass Doors", "qty": 1, "unit_price": 4950 }, { "sku": "G4X4-BULLBAR-4X4", "name": "4x4 Alloy Bull Bar", "qty": 1, "unit_price": 2650 } ], "total": 10403, "weekly": 46, "currency": "AUD", "marketing_consent": false, "status": "proposed", "updated_at": "2026-09-30T06:03:22.981Z" }}Check every delivery
Section titled “Check every delivery”Each request carries three headers:
webhook-id: evt_d1024fc881e9becfc1c23952webhook-timestamp: 1790748203webhook-signature: v1,U3ZuJArKQ9Gbfhv7lDc...The signature is base64(HMAC-SHA256(secret, id + "." + timestamp + "." + raw body)), where the secret is
the base64 part after whsec_. Before trusting a body:
- Use the raw body, exactly as received (do not re-serialise the JSON).
- Compare against every
v1,value in the header (during a secret change there are two, separated by a space) with a constant-time comparison. - Refuse a timestamp more than 5 minutes from your clock.
- Remember
webhook-id: the same event can arrive twice. Ignore one you have handled.
A Standard Webhooks library does all four: npm install standardwebhooks (Node), pip install standardwebhooks (Python), or see verify_webhook.py for the
same check in plain Python.
import { Webhook } from 'standardwebhooks';const event = new Webhook(process.env.GOASK_WEBHOOK_SECRET).verify(rawBody, request.headers); // throws if not oursDelivery rules
Section titled “Delivery rules”- Answer 2xx within 10 seconds, then do slow work. Anything else counts as a failure. Redirects are not followed.
- Retries: right away, then after 5 s, 5 min, 30 min, 2 h, 5 h, 10 h, 10 h and daily, for about 5 days. The event id stays the same on every retry.
- Switched off: an endpoint that answers
410 Gone, or has not accepted a delivery for 5 days, is switched off and you get an email. Switch it back on from/developer. - Replay:
/developerlists the last 50 deliveries; Send again repeats one with the same id. - Order is not guaranteed. Use
updated_at, and read the lead when in doubt. - Your URL: https only, on a public address.
Secrets
Section titled “Secrets”A secret is shown once when the endpoint is made. New secret on /developer makes another one; the
old one keeps signing too for 24 hours, so you can switch without missing a delivery.