Webhooks are how Geldstuck pushes state changes to your backend. Every domain event (a KYC completing, a transaction being funded, a document being reviewed) fires a signed HTTPS POST to each endpoint subscribed to the event’s type.

Signing

HMAC-SHA256 with a per-tenant secret. Timestamp + body, timing-safe comparison.

Automatic retries

Non-2xx responses are retried with exponential backoff. We never drop an event silently.

Event filtering

Subscribe to exact types, namespace wildcards (kyc.*), or everything (*).

Per-tenant isolation

Each tenant has its own endpoints, secret, and delivery log.

Registering an endpoint

Developers → Webhooks → Add endpoint. Paste your URL, pick events, hit save. You’ll see the first few deliveries land in the dashboard log in real time.

Request shape

Every delivery looks like this:
POST /webhooks/geldstuck HTTP/1.1
Host: api.acme.com
Content-Type: application/json
User-Agent: Geldstuck/1.0
X-Geldstuck-Event: kyc.completed
X-Geldstuck-Webhook-Id: evt_01HX3ZJ...
Geldstuck-Signature: t=1745311982,v1=b8a7e1c4...
X-Geldstuck-Signature: f3a2c1b8...       # legacy, still sent for compatibility

{
  "id": "evt_01HX3ZJ...",
  "type": "kyc.completed",
  "tenantId": "tnt_01HX3Z8MQW...",
  "data": { ... },
  "createdAt": "2026-04-22T10:34:17.000Z"
}

Responding

  • Return 2xx within 10 seconds to mark the delivery successful.
  • Any other status (or a timeout) triggers a retry.
  • The response body is ignored. Just return 200 OK with no body - don’t send sensitive data back.
Don’t do heavy work inside the handler. Enqueue and return 200. We treat slow responses as failures and retry - which can create duplicate work.

Next steps

Event catalog

Every event Geldstuck emits, with payload schemas.

Signatures

How we sign events, how you verify.

Verify in code

Drop-in handlers for Node, Python, Go, Ruby.

Retries & deliverability

Retry schedule, dead-letter behavior, replays.