My App
Webhooks

Webhooks Overview

Emofy delivers HTTP webhooks to subscribed URLs when domain events fire. At-least-once delivery, Stripe-compatible signing, idempotency via delivery ID.

Webhooks

Emofy delivers HTTP POST notifications to your URL whenever a subscribed event fires in an organization that installed your app.

Delivery semantics

  • At-least-once. Your receiver must be idempotent. Deduplicate on X-Emofy-Delivery-Id — never on the payload alone.
  • 5-attempt exponential retry for 5xx / timeout responses (AC-6). After the final attempt, the delivery is marked dead_lettered.
  • 10-second request timeout. Return 2xx fast. Offload slow work to your own job queue.
  • Per-URL concurrency cap. Emofy sends at most 3 deliveries in flight per receiver URL so one slow integration can't starve the platform's worker pool.
  • Auto-pause kicks in after 20 consecutive 5xx / timeout failures (checked against the last 50 deliveries within 15 min). You re-enable from the developer portal once your receiver is healthy again.

Envelope

Request body is always JSON:

{
  "event": "app.installed",
  "timestamp": 1740000000000,
  "deliveryId": "whd_...",
  "eventId": "wob_...",
  "apiVersion": "v1",
  "data": {
    "orgId": "org_...",
    "appId": "app_...",
    "installedBy": "usr_...",
    "installedAt": "2026-04-21T10:00:00.000Z"
  }
}

Request headers

HeaderMeaning
Content-TypeAlways application/json
Emofy-SignatureHMAC-SHA256 envelope — see Signature Verification
X-Emofy-Delivery-Idwhd_*use this as your idempotency key
X-Emofy-Event-Typee.g. app.installed
X-Emofy-Webhook-IdThe subscription id, apw_* or whk_*
X-Webhook-SignatureLegacy signature (T+0→T+30d only). See Signature Verification
X-Webhook-TimestampLegacy timestamp pair for the legacy signature

Quick checklist for your receiver

  1. Return 2xx only after you've durably recorded the delivery id.
  2. Verify Emofy-Signature — reject requests with invalid or expired signatures (see Signature Verification).
  3. Check Math.abs(Date.now() - t) < 5 * 60 * 1000 to reject replays.
  4. Use X-Emofy-Delivery-Id as the primary key in your ingest log — duplicate deliveries are part of the contract, not a bug.

On this page