Webhooks
If a key has a webhook URL configured, Govza POSTs to it on every order status
change.
Events: order.assigned, order.in_progress, order.delivered,
order.cancelled.
{ "event": "order.assigned", "occurred_at": "2026-08-11T10:32:00.000Z", "external_order_id": "SHOP-10432", "order_code": "YB2072", "status": "assigned", "price": 300, "tracking_url": "https://track.govza.app/…", "driver": { "name": "Isa", "phone": "+79280003396" }}Respond 2xx to acknowledge. Anything else is retried with exponential backoff,
up to eight attempts.
Verifying the signature
Section titled “Verifying the signature”Every request carries:
X-Govza-Signature: t=1723377600,v1=9f86d081884c7d65…v1 is HMAC-SHA256(secret, "<t>.<request body>"), hex-encoded. The secret is
shown once when the webhook URL is set or changed.
import crypto from 'node:crypto';
function verify(rawBody, header, secret) { const parts = Object.fromEntries(header.split(',').map((kv) => kv.split('=')));
const age = Math.abs(Date.now() / 1000 - Number(parts.t)); if (!Number.isFinite(age) || age > 300) return false;
const expected = crypto .createHmac('sha256', secret) .update(`${parts.t}.${rawBody}`, 'utf8') .digest('hex');
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));}Endpoint requirements
Section titled “Endpoint requirements”httpson a public address only; redirects are not followed;- respond quickly: queue the real work and return
2xxstraight away; - expect the same event to arrive more than once, and make handling idempotent.
Changing the URL
Section titled “Changing the URL”Changing a key’s webhook URL issues a new signing secret, shown once. The previous secret stops working.