Skip to main content

Webhooks

Webhooks push events to your server as they happen, so you don’t have to poll. When something changes in a tenant — a bill is created, an order is fulfilled, stock runs low — Vantr sends an HTTPS POST to the endpoints you’ve registered. Every delivery is signed with a per-endpoint secret so you can prove it came from us and was not tampered with, and deliveries are retried with backoff so a brief outage on your side doesn’t drop events.

Register an endpoint

Register endpoints in the developer portal under Webhooks, or programmatically with the /v2/webhooks API (scopes webhooks.read / webhooks.write):
The signing secret is returned only once, on create. Store it securely — you’ll need it to verify deliveries. If you lose it, rotate it with PATCH /v2/webhooks/{id} (sending a new secret) and update your server. Omit events (or send []) to subscribe to everything.
Endpoints must be public HTTPS URLs. Plain http://, localhost, and private / internal / link-local hosts are rejected at save time, and re-checked (with DNS resolution) before every delivery to prevent SSRF.

The request we send

Verify the signature

X-Webhook-Signature has two parts:
  • t — the unix timestamp (seconds) when we signed the delivery.
  • v1HMAC_SHA256(secret, "{t}.{rawBody}") as hex.
To verify a delivery:
  1. Read the raw request body (the exact bytes — don’t re-serialize a parsed object).
  2. Parse t and v1 from X-Webhook-Signature.
  3. Recompute HMAC_SHA256(secret, "{t}.{rawBody}") and constant-time compare it to v1.
  4. Reject deliveries whose t is outside your tolerance window (we recommend ±5 minutes) to prevent replay.

Delivery, retries, and idempotency

  • Acknowledge fast. Respond 2xx within ~10 seconds. Any non-2xx (or a timeout, connection error, or redirect — we do not follow redirects) is treated as a failed delivery.
  • Retries. Failed deliveries are retried with exponential backoff and jitter (≈30s, 1m, 2m, … up to ~1h) for several attempts over a few hours, then marked dead. The retried request is byte-identical (same X-Webhook-Id, same body, same signature).
  • At-least-once. A delivery can arrive more than once (e.g. you 2xx’d but we didn’t see it). Make your handler idempotent by deduping on X-Webhook-Id.
  • Order is not guaranteed. Use the timestamp / your own state to resolve ordering if it matters.

Events

Subscribe to specific events with the events array, use a prefix.* wildcard (e.g. invoice.*), or subscribe to everything by omitting events.