Webhooks overview

Receive Nyumba Zetu events on your own HTTPS endpoint, signed and retried.

A webhook is an HTTPS endpoint you host. When something happens in Nyumba Zetu that you have subscribed to — a payment arrives, an invoice is issued, an allocation is reversed — the platform signs a small JSON body and sends it to that endpoint as a POST.

Webhooks are a change feed

This is the single most important thing to understand before you design around them. A subscription is a forward-looking feed of state changes, and it is not a data export.

When to use webhooks, and when to poll

Reach for webhooks when
  • You want to react promptly to a change — notify a resident, kick off a reconciliation, refresh a cache.
  • The fact that something changed is what you need, and you can fetch the detail yourself.
  • You can host an endpoint that answers quickly and tolerates being called more than once for the same event.
Poll the partner API when
  • You need history, including anything from before you subscribed.
  • You need the complete record, not a reference to it.
  • You need a guaranteed-complete set to reconcile against — a ledger export, a month-end total, a warehouse load.
  • You cannot host a public HTTPS endpoint.

Most integrations use both: the webhook is the trigger, the partner API is the source of the record.

How a delivery is put together

  1. You register an endpoint

    POST /v3/webhooks with your HTTPS URL and the event names you want. The response contains the signing secret once. See Managing endpoints.

  2. Something happens in the platform

    A state change is recorded and published for delivery. Only events the catalogue marks as publicly subscribable can leave the platform — see the events reference.

  3. The platform signs and sends

    The body is serialised once and signed with your secret, then POSTed to your URL with x-nz-webhook-timestamp and x-nz-webhook-signature.

  4. Your endpoint verifies and answers 2xx

    Verify the signature against the raw body, do your work asynchronously, and return a 2xx quickly. Anything else is treated as a failed delivery — see Retries and failures.

How deliveries behave

The mechanism, stated plainly — none of this is a service level.

Signed, always. Every delivery carries x-nz-webhook-signature. Signing is fail-closed: a webhook whose secret cannot be resolved is not sent unsigned, it is not sent at all.

HTTPS only, public addresses only. Your URL must be https, must not contain credentials, and must not resolve to a private, loopback, link-local or reserved address. This is re-checked on every delivery, not only at registration, and the cleared address is pinned for the request.

At least once, not exactly once. A delivery that fails is retried. A 2xx your server sent but that never reached the platform is a failure from the platform's side, so the same event can arrive twice. Deduplicate on executionId — it is stable across every retry of the same event.

Per-endpoint retry budget. Each registered endpoint has its own delivery queue, retry counter and dead-letter state. A failing endpoint exhausts its own budget and does not slow down anyone else's.

No ordering guarantee. Deliveries are independent and retried independently, so events can arrive out of the order in which they occurred. Use the ids and timestamps in the payload rather than arrival order.

Scope and permissions

A webhook belongs to exactly one organisation, resolved from your access token — never from the request body. Optionally it can be narrowed to a single branch with branchId; omit it to receive the whole organisation.