📨 Webhooks
Webhooks overview
- Webhooks notify organizations in near real time about changes to related entities (orders, contacts, merchants, invitations).
- You can configure multiple endpoints per organization; all active endpoints receive all events.
- Event status can be inspected via the API.
Getting started
- Create an endpoint with a URL and a secret.
- Store your secret securely; it’s used to sign each webhook.
- Verify signatures on every request (see Security below).
- Use Ping to test your integration before going live.
Managing endpoints (Org‑scoped)
- Create: POST /organizations/:organizationId/webhooks
- List/get: GET /organizations/:organizationId/webhooks[/ :webhookId]
- Rotate secret: POST /organizations/:organizationId/webhooks/:webhookId/rotate-secret
- Pause/resume: POST /organizations/:organizationId/webhooks/:webhookId/(pause|resume)
- Delete: DELETE /organizations/:organizationId/webhooks/:webhookId (soft delete)
- Ping: POST /organizations/:organizationId/webhooks/:webhookId/ping
Secrets are write‑only and never returned after creation/rotation.
Events (read APIs)
- List: GET /organizations/:organizationId/webhook-events
- Filters: type, from, to, merchantId, resourceType, resourceId, page, limit
- Get: GET /organizations/:organizationId/webhook-events/:eventId
- Deliveries (lean status): GET /organizations/:organizationId/webhook-events/:eventId/deliveries
- Returns per-endpoint deliveries with deliveryStatus, retryCount, lastRetryAt, lastStatusCode, lastRespondedAt
Replay (Org-scoped, internal use by ops or via permissions):
- Replay an event: POST /organizations/:organizationId/webhook-events/:eventId/replay
- Re-enqueues to all active endpoints (or a single endpoint internally)
Event types (initial set)
- Orders: order.created, order.pending, order.processing, order.paid, order.failed, order.cancelled, order.completed, order.expired
- Contacts: contact.created, contact.updated, contact.deleted
- Merchants: merchant.created, merchant.updated, merchant.deleted
- Invitations: invitation.created, invitation.accepted, invitation.expired, invitation.revoked
Subject to expansion; breaking changes roll out via the version field.
Payload and headers
- Content type: application/json
- Body skeleton
- Headers (set by Koywe):
- Koywe-Event-Id, Koywe-Event-Type, Koywe-Event-Version
- Koywe-Organization-Id, Koywe-Merchant-Id (if applicable)
- Koywe-Environment
- Koywe-Webhook-Id
- Koywe-Signature: HMAC-SHA256 (hex) over the raw request body using your endpoint secret
- Koywe-Integrity-Signature: added by the delivery service to protect in-flight integrity
Environment is one of: local | qa | sandbox | production.
Security (signature verification)
- Compute HMAC-SHA256 of the exact request body using your saved endpoint secret.
- Compare your digest (hex) with Koywe-Signature. If they don’t match, reject the webhook.
- Replay-safe: use idempotency by event id (id is stable across replays).
Minimal pseudo-verification:
Delivery behavior and retries
- On event creation, Koywe persists the event and enqueues a delivery per active endpoint.
- Each delivery receives a unique task id; you can fetch lean status via the deliveries endpoint.
- If an endpoint fails, other endpoints still receive their deliveries.
- You can request a replay to resend an event.
Best practices
- Respond 2xx quickly (< 5s); process asynchronously on your side.
- Validate Koywe-Signature on every request.
- Treat webhooks as at-least-once delivery; deduplicate using event id.
- Use the ping endpoint to verify connectivity after configuration or secret rotation.
Permissions (org-scoped)
- organization_webhooks.manage: create/update/pause/resume/delete/rotate
- organization_webhooks.view: list/get endpoints
- organization_webhook_events.view: list/get events, view deliveries
- organization_webhook_events.replay: replay events
This summary complements the OpenAPI docs with usage guidance, security expectations, and event taxonomy.