Webhook
Receive events pushed to Gaur over HTTP and append them to a table, with HMAC verification and deduplication.
The webhook connector is the one push-based connector. Instead of Gaur reaching out to a source, an external system (Stripe, GitHub, your own application) POSTs events to a Gaur URL as they happen. Each payload is verified, deduplicated, and appended to a table.
Use it when you want events to land in Gaur in near real time, rather than on a refresh schedule.
How it differs from pull connectors
| Pull connectors | Webhook | |
|---|---|---|
| Direction | Gaur fetches from the source | The source pushes to Gaur |
| Trigger | On demand or on a schedule | Whenever an event arrives |
| Freshness | As of the last refresh | Near real time |
Create a webhook source
In the Ingestion area, create a webhook source with:
| Field | Required | Description |
|---|---|---|
name | Yes | A display name. |
slug | Yes | A short URL-safe identifier (3 to 63 chars). |
table_name | Yes | The table events land in (3 to 63 chars). |
collection_ids | Yes | The collections that own the table. |
secret | Recommended | A signing secret (min 16 chars) for HMAC verification. |
event_id_path | Optional | A JSON Pointer to a unique event id in the payload, used for deduplication. |
When you create the source, Gaur returns a webhook URL of the shape:
https://<base-url>/v1/ingest/webhook/<token>Point your external system's webhook configuration at this URL. The token in the path identifies the source; treat it as a secret.
Verifying payloads (HMAC)
If you set a secret, every payload must be signed. The sender computes
an HMAC-SHA256 of the raw request body using the shared secret and sends
it in a header:
x-hub-signature-256: sha256=<hex_digest>Gaur recomputes the signature and rejects any request whose signature is
missing or wrong with 401. This is the standard scheme used by GitHub,
Stripe, and most webhook providers, so most senders can produce it out
of the box.
Rotating the secret without downtime
Rotating a signing secret normally means a window where in-flight senders break. Gaur avoids this with dual-secret rotation: when you rotate, the previous secret stays valid for a grace period alongside the new one. Update your sender to the new secret any time during that window; once it expires, only the new secret is accepted.
You can also regenerate the webhook URL if a token leaks. The old URL stops working immediately.
What lands in the table
Each received event becomes a row. Alongside your payload, Gaur records a few columns:
| Column | What it holds |
|---|---|
event_id | The dedup key: read from event_id_path if set, otherwise generated. |
source | The webhook source slug. |
received_at | When Gaur received the event. |
headers | A sanitized subset of request headers (the signature header is never stored). |
payload | The full JSON body. |
event_id is the table's primary key, so redelivered events are
deduplicated: if the same event_id arrives twice, only one row is
kept. Most providers retry on timeout, so set event_id_path to a
stable id from the payload to make redelivery safe.
Failed events and the dead-letter queue
A payload that can't be parsed as JSON, or that exceeds the size limits, is quarantined in a dead-letter queue (DLQ) instead of being dropped. From the source's view you can:
- See the DLQ count and inspect what failed.
- Replay the DLQ to reprocess quarantined payloads once the cause is fixed.
Source health
Each webhook source exposes a health view so you can tell whether events are flowing:
- Pending events waiting to be processed, and the age of the oldest.
- DLQ count of failed events.
- Last received timestamp.
Limits
- Signature required when a secret is set. Unsigned or wrongly-signed
requests get
401. - Rate limited. Webhook endpoints are rate limited per source token
and per client IP; bursts above the limit get
429. Senders should back off and retry. - Payload size. Oversized bodies and oversized batches are rejected to the DLQ rather than ingested.