Docs

Dispatch docs

Send customer webhooks from your app with customer-managed endpoints, event catalogs, retries, and replay.

Model

Create an app for the product surface that emits events. Each customer, account, tenant, or organization in your product is a recipient. Recipients add endpoints and subscribe to the event types you expose.

  • App: the product area that sends webhooks, such as "Billing events".
  • Recipient: one customer or tenant in your product, such as customer_123.
  • Endpoint: the recipient-owned URL where deliveries are sent.
  • Event type: a named event such as invoice.paid or job.failed.
  • Message: one event you send through Relin to the recipient's matching endpoints.

Backend setup

  1. Create an API key from the Dispatch dashboard.
  2. Create an app and publish event types such as invoice.paid, user.created, or job.failed.
  3. When a signed-in customer opens webhook settings, create a portal session for that customer's recipient ID.
  4. Open the portal URL so the customer can manage endpoints without giving them workspace access.
  5. Send messages with the same recipient ID so Relin routes each message to that customer's subscribed endpoints.

Create an app

Apps group recipients, endpoints, event types, and messages for one webhook product surface.

POST /api/v1/apps Authorization: Bearer rlk_... Content-Type: application/json { "name": "Billing webhooks", "routingKeyBodyPath": "customer.id", "routingKeyHeader": "x-customer-id" }

The response includes an appId. Use it for event types, recipients, portal sessions, messages, and debugging calls.

Publish event types

Event types are the list your customers see when choosing subscriptions in the portal.

PUT /api/v1/apps/{appId}/event-types/invoice.paid Authorization: Bearer rlk_... Content-Type: application/json { "description": "An invoice was paid", "examplePayload": { "invoiceId": "inv_123", "customerId": "customer_123" } }

Customer portal

Create a short-lived portal URL when a signed-in customer opens webhook settings in your app. The portal URL is scoped to one recipient.

POST /api/v1/apps/{appId}/recipients/customer_123/portal-sessions Authorization: Bearer rlk_... Content-Type: application/json { "name": "Acme Inc.", "expiresInSeconds": 3600, "returnUrl": "https://your-app.example.com/settings/webhooks" }

Embed the returned URL in an iframe or open it in a new tab. Customers can add endpoints, choose event types, enable or disable delivery, and rotate endpoint secrets.

Message format

Send the recipient, event type, and JSON data from your backend. Include a stable message ID when you want duplicate sends to resolve to the same message.

POST /api/v1/apps/{appId}/messages Authorization: Bearer rlk_... Content-Type: application/json { "recipient": "customer_123", "type": "invoice.paid", "messageId": "evt_123", "data": { "invoiceId": "inv_123" } }

Use idempotencyKey instead of messageId if that is the naming style your backend already uses. If neither is provided, Relin generates a message ID.

Inspect and replay

When a customer says they did not receive an event, fetch the message and attempts first. Replay after the customer's endpoint is fixed.

GET /api/v1/apps/{appId}/messages/{messageId} GET /api/v1/apps/{appId}/messages/{messageId}/attempts POST /api/v1/apps/{appId}/messages/{messageId}/replay

Open Dispatch