GET /api/.../:id always works, but a webhook subscription is the faster and
cheaper way to learn about a state change the moment it happens.
Webhooks are delivered at least once and may arrive out of order for
the same resource (a retried delivery can land after a later event). Key your
handler off
X-MF-Delivery for de-duplication and off the resource’s own
status field for ordering — never assume the Nth webhook you receive is the
Nth thing that happened.Subscribe
201:
Event catalog
Every payload is wrapped in the same envelope as any other response:
The payload is intentionally thin — it tells you what changed, not the full
resource. Treat it as a trigger to
GET /api/.../:id for the authoritative,
PII-masked record, not as the source of truth to persist directly.Delivery
Each delivery is an HTTPPOST to your url with:
Your endpoint must respond within 10 seconds. Any
2xx status marks the
delivery successful; anything else (including a timeout) is treated as a
failure and scheduled for retry.
Verifying the signature
ComputeHMAC_SHA256("<timestamp>.<raw request body>", secret) and compare
it, constant-time, against the v1 value. Always use the raw request
body — not a re-serialized/parsed-and-re-stringified version, which can
differ byte-for-byte.
Retries and parking
A failed delivery (non-2xx, timeout, or connection error) is retried with
backoff: 1 minute, 5 minutes, 25 minutes, 2 hours, 12 hours. After 5 failed
attempts the delivery is marked PARKED — it will not be retried
automatically.
If a PARKED delivery matters (e.g. you fixed an outage on your endpoint),
replay it manually — see below. There’s no automatic un-parking.
Manage subscriptions and deliveries
GET /deliveries returns each attempt’s status
(PENDING | DELIVERED | FAILED | PARKED), attempts, and
last_status_code — use it to build a delivery-health view, or to find and
replay anything stuck PARKED.
POST /deliveries/:id/retry re-queues one delivery immediately, outside the
normal backoff schedule.
If you’d rather poll
Every event above has a corresponding field you can poll instead:GET /api/investors/v1/:id (status), GET /api/mandates/v1/:id
(status), GET /api/orders/v1/:id (status, payment_status). Webhooks
and polling are not mutually exclusive — most integrations use webhooks as
the primary signal and a low-frequency poll (or
POST /api/investors/v1/sync)
as a reconciliation fallback for missed deliveries.