How Webhook Delivery Works

This path is documentation-only — there is nothing to call here.
Webhooks are HTTP POST requests sent BY Ewity TO your app's
registered endpoint(s)
. Each event on this page is modelled as a
pseudo-path purely so the docs can group and describe them.

Registering endpoints

Webhook endpoints are managed per application in the developer
portal
(Application → Webhooks). An app can register any number of
endpoints; each endpoint has its own:

  • URL — where deliveries POST.
  • Event subscriptions — the subset of events this endpoint
    receives. An event a company triggers is delivered once to every
    subscribed endpoint of every app that company has installed.
  • Verification modesignature (default; deliveries carry
    X-Ewity-Signature) or platform_key (deliveries carry
    Authorization: Bearer <your platform API key>).

The envelope

Every delivery to a portal-created endpoint is a JSON envelope:

{
  "id": "evt_7FJq2mR9tXcW4bLnV8sKdY1p",
  "event": "customer.created",
  "created_at": "2026-08-12T14:30:05+05:00",
  "company": { "id": 1, "name": "Test Company", "domain": "test" },
  "install": { "store_id": "pl_id_rLCD8Ks1rVRGIFs", "external_account_id": null },
  "data": { "...": "event-specific payload" }
}
  • id — unique delivery id (evt_ + 24 chars). Also sent as the
    X-Ewity-Delivery header. Dedupe on it.
  • event — the event name, also sent as X-Ewity-Event.
  • company — the merchant business the event happened in.
  • install.store_id — the install's store id (the same value your app
    passes as X-Ewity-Store when calling the Apps API).
  • data — the event-specific payload, documented per event below.

Verifying signatures

With verification mode signature, every delivery carries:

X-Ewity-Signature: t=<unix timestamp>,v1=<hex hmac_sha256(secret, "{t}.{raw_body}")>

signed with your app's signing secret (shown in the developer portal).
Verify with a constant-time compare against the exact raw request
bytes
, and reject timestamps outside a 5-minute window:

const crypto = require('crypto');

function verifyEwitySignature(secret, rawBody, header) {
  const m = /^t=(\d+),v1=([0-9a-f]{64})$/.exec(header || '');
  if (!m) return false;
  const [, t, sig] = m;
  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
  const expected = crypto
    .createHmac('sha256', secret)
    .update(`${t}.${rawBody}`)
    .digest('hex');
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(sig));
}

Delivery semantics

  • Deliveries are queued and sent asynchronously — one POST per
    subscribed endpoint per installed company.
  • Any 2xx response counts as acknowledged. Non-2xx responses and
    connection failures are logged by Ewity but not retried
    deliveries are best-effort single attempts. Poll the corresponding
    read APIs if you need guaranteed convergence.
  • The same event may occasionally be delivered more than once; dedupe
    by the X-Ewity-Delivery id.

Legacy compatibility mode

Endpoints migrated from the pre-Apps ordering-platform webhook system
(webhook_url / inventory_webhook_url) keep receiving exactly the
bytes they always parsed
: the raw event payload with no envelope, an
X-Event header carrying the historical event name, and
Authorization: Bearer <platform API key>. This raw format exists
only for migrated endpoints — portal-created endpoints always receive
the envelope, even when subscribed to a legacy event name.

Each legacy event has a modern envelope twin carrying the identical
payload as data. Firing a legacy event also delivers to subscribers
of its twin (and each subscriber sees the event name it subscribed
to). New integrations should subscribe to the twins.

Legacy event (raw, no envelope)Modern twin (envelope)
OrderStatusChangedorder.status_changed
OrderNotificationorder.notification
StoreTurnedOnstore.turned_on
ReviewRequestedReminderorder.review_reminder
CatalogueUpdatedcatalogue.updated

Delivery, retries & the health breaker

  • Timeouts: Ewity spends at most 5 s connecting and 15 s per delivery.
  • Retries: a non-2xx response, timeout or connection failure is retried
    after 1, 4 and 8 minutes (four attempts total). Every attempt carries the
    same envelope id / X-Ewity-Delivery — dedupe on it.
  • Auto-disable: an endpoint that keeps failing (a majority of its
    deliveries over a sustained recent window, with a minimum delivery volume so
    a single blip never trips it) is disabled automatically. The app's
    developers are emailed; deliveries stop and missed events are NOT queued.
  • Re-enable from the portal's Webhooks tab once the endpoint is fixed —
    the endpoint gets a fresh health window. Use the Apps API to reconcile
    anything missed while disabled.
  • The Webhooks tab shows each endpoint's recent delivery health (delivered /
    failed / retried, per hour).
Recent Requests
Log in to see full request history
TimeStatusUser Agent
Retrieving recent requests…
LoadingLoading…
Response
200

Documentation-only path — no request or response exists. See the per-event operations below for the actual delivery payloads.

Language
Credentials
Bearer
LoadingLoading…
Response
Click Try It! to start a request and see the response here!