Endpoints

All public endpoints live under https://bridge.envara.ae/api/public.

POST /api/public/ingest/{source}/{event}

The single endpoint you'll use 99% of the time. Accepts any signed event for any source/event combination.

Path parameters

  • {source} — platform identifier (woocommerce, shopify, generic, or your own).
  • {event} — dotted event name (order.created, user.signup, etc.).

Headers

bash
Content-Type: application/jsonX-Envara-Site-Key: ec_live_xxxxxxxx...X-Envara-Signature: sha256=<hex hmac>X-Envara-Timestamp: 1731234567X-Envara-Idempotency-Key: order:1042:created   # optionalX-Envara-Mode: test                            # optional: dry-run only

Body

Any JSON. See Event envelope for the recommended shape.

Response — 200 OK

json
{  "ok": true,  "event": "order.created",  "event_id": "8a3f...c1",  "order_id": "uuid-or-null",  "whatsapp": "sent",  "bindings_run": 1,  "recipients_sent": 1,  "recipients_failed": 0}

The whatsapp field is one of:

  • sent — all recipients delivered to Meta successfully.
  • partial — some succeeded, some failed.
  • failed — all failed.
  • no_bindings — event accepted but no binding is configured (set up one in the dashboard).
  • skipped_no_phone — no recipient phone could be resolved.
  • skipped_no_config — WhatsApp Cloud credentials not configured.

Response — error

json
{ "error": "Invalid signature" }

See Errors for the full list.

Dry-run mode

With X-Envara-Mode: test, the endpoint returns a previews array showing exactly which bindings would fire, the recipients resolved, and the slot values — without calling Meta.

json
{  "ok": true,  "event": "order.created",  "event_id": "8a3f...c1",  "whatsapp": "skipped_no_config",  "bindings_run": 1,  "dry_run": true,  "previews": [    {      "binding_id": "uuid",      "template": "order_confirmation_v1",      "language": "en",      "recipients": ["+9715XXXXXXXX"],      "slots": {        "header": ["Acme"],        "body": ["Ada", "1042", "AED 199.00"],        "buttonUrl": []      },      "resolved": true    }  ]}

OPTIONS /api/public/ingest/{source}/{event}

CORS preflight. Returns 204 with permissive headers. You should not need to call this directly — browsers do it automatically.

GET /api/public/health

Returns 200 with a small JSON body. Use it for uptime probes — no auth required.