Webhooks
Receive events at your own HTTPS endpoint
Webhooks are available on the Pro, Team, and Enterprise plans. Register an endpoint in the
dashboard or with POST /v1/webhooks — the signing secret is shown once, at creation.
Event types
Only these events are delivered today:
| Event | Fires when | data fields |
|---|---|---|
| api.call.succeeded | An API request completes 2xx | endpoint, method, status_code, model, timestamp |
| api.call.failed | An API request completes non-2xx | endpoint, method, status_code, model, timestamp |
| key.created | A new API key is created | key_id, name, key_prefix, created_at |
| team.member.invited | Someone is invited to your team | email, role, team_id, invited_at |
| webhook.test | You trigger a test delivery | message, webhook_id, user_id |
Payload
Every delivery is a POST with this envelope:
| Field | Meaning |
|---|---|
| id | Unique per delivery. Stable across retries of the same event — dedupe on this. |
| webhook_id | Your endpoint's config ID. The same for every delivery to this URL — not a dedupe key. |
| timestamp | When the delivery was generated (ISO 8601). |
Headers
| Header | Value |
|---|---|
| X-Webhook-Signature | HMAC-SHA256 of the raw request body, hex, no prefix |
| X-Webhook-Event | The event name (data.event) |
| X-Webhook-Id | Same as id in the body — the dedupe key |
| X-Webhook-Timestamp | Same as timestamp in the body |
| User-Agent | TarqaAI-Webhook/1.0 |
Verifying the signature
Compute HMAC-SHA256 over the exact bytes of the request body with your signing
secret and compare, in constant time, against X-Webhook-Signature.
POST /v1/webhooks/:id/rotate issues a new secret and returns it once. The old secret stops
working immediately, so deploy the new one first.
Delivery semantics
- At-least-once. A delivery that times out or returns non-2xx after your handler already
processed it will arrive again. Dedupe on
X-Webhook-Id. - Retries. Up to 4 attempts total — the initial send plus retries after 1s, 5s, 15s. Retries survive a restart of our side (they are not held in memory).
- Timeout. Each attempt waits 10 seconds for your response. A slower handler is
treated as a failure and retried — so return
2xxwithin 10s and do the real work asynchronously. - Success = any
2xx. The response body is stored for your delivery log but is not interpreted. There is no "received vs processed" signal — if you return200and then fail to process, we will not know. - No ordering guarantee. A retried older event can land after a newer one. Use
timestampif order matters to you. - Auto-disable. After 15 consecutive failed deliveries the endpoint is set inactive and stops receiving events. Re-enable it in the dashboard once your endpoint is healthy.
- Replay protection is yours to do. Check
X-Webhook-Timestampagainst a tolerance window (5 minutes is reasonable). We do not reject replays server-side.
Inspecting deliveries
GET /v1/webhooks/:id/deliveries returns recent attempts with status code, response snippet,
attempt count, and error message — use it to debug a failing endpoint before it auto-disables.
