Authentication
Every request to the ingest API must include three headers: a site API key, an HMAC signature, and a timestamp. We validate all three before processing the body.
Headers
| Header | Required | Description |
|---|---|---|
X-Envara-Site-Key | Yes | Your site's API key (starts with ec_live_). Identifies which site is sending. |
X-Envara-Signature | Yes | sha256=<hex> — HMAC-SHA256 of the raw body, using your webhook secret as key. |
X-Envara-Timestamp | Recommended | Unix seconds. Requests outside ±5 minutes are rejected. |
X-Envara-Idempotency-Key | Optional | Your own unique ID. If the same key arrives twice within 5 minutes for the same site+event, the second is treated as a duplicate. |
X-Envara-Mode | Optional | Set to test to dry-run: validate, resolve bindings, return preview, never send to Meta. |
Computing the signature
The signature is an HMAC-SHA256 of the raw request body bytes, lowercase hex, prefixed with sha256=. Sign the body before any framework reformats it.
import { createHmac } from "crypto";
const body = JSON.stringify(payload);const signature = "sha256=" + createHmac("sha256", WEBHOOK_SECRET) .update(body) .digest("hex");<?php$body = json_encode($payload, JSON_UNESCAPED_SLASHES);$signature = 'sha256=' . hash_hmac('sha256', $body, $webhookSecret);import hmac, hashlib, json
body = json.dumps(payload, separators=(",", ":"))signature = "sha256=" + hmac.new( webhook_secret.encode(), body.encode(), hashlib.sha256).hexdigest()Why timestamps
Including X-Envara-Timestamp (current unix seconds) prevents replay attacks. We reject any request more than 5 minutes off from server time. Always use server time, not client time.
Idempotency
If you might retry a request after a network blip, pass X-Envara-Idempotency-Key with a unique value per logical event (e.g. order:1042:created). Duplicates are silently deduplicated and return the same result as the original.
Key rotation
API keys cannot be recovered after creation. If you lose yours, regenerate the webhook secret from the Site detail page (this invalidates the old secret immediately) and reset the API key by deleting and recreating the site.
Common errors
401 Missing site key— header not sent.401 Invalid site key— key doesn't match any site.401 Invalid signature— recompute over the exact body bytes you sent.401 Stale timestamp— clock drift > 5 min. Sync your server's NTP.403 Site is disabled— re-enable the site in the dashboard.
