Webhooks
Receive conversation_processed events at your HTTPS endpoint.
Subscribe
Admins can register an HTTPS endpoint in Settings → Developer → Webhooks. Select Add webhook to create a subscription. You can also enable, disable, test, and delete subscriptions here.
Set a signing secret when registering your endpoint. Dashboard subscriptions apply to the organization; contact your account manager for team-scoped subscriptions.
Custom headers
Add up to five custom headers when your receiver needs authentication or routing information, such as client_id or Authorization: Bearer YOUR_RECEIVER_TOKEN. Use your receiver's credentials, not your Rilla API key.
In the new webhook form, select Add header and enter a name and value. For an existing subscription, select Edit headers, make your changes, then Save headers. Remove all rows and save to clear the headers; Cancel discards unsaved edits.
Values are encrypted at rest and masked in the editor. Only admins in your organization can access saved headers. Both live events and tests use the saved configuration, so save before testing.
Names must be unique ignoring case, and names and values must be valid HTTP headers. The full header map is limited to 4096 UTF-8 bytes serialized as JSON. Rilla's content type, signature, and transport headers are reserved. See the complete limits and reserved names.
Event payload
The event contains conversation metadata, summaries, survey results, and a temporary transcript URL when available. Use conversation_id with Get a conversation to retrieve the full export record.
{
"webhook_event_id": "55555555-5555-4555-8555-555555555555",
"event_type": "conversation_processed",
"sent_at": "2026-09-01T15:12:00Z",
"data": {
"conversation_id": "11111111-1111-4111-8111-111111111111",
"organization_id": "66666666-6666-4666-8666-666666666666",
"conversation_url": "https://app.rilla.com/conversations/single?id=11111111-1111-4111-8111-111111111111",
"transcript_url": null,
"user_id": "33333333-3333-4333-8333-333333333333",
"user_email": "alex@example.com",
"recorded_at": "2026-09-01T14:00:00Z",
"recording_duration_seconds": 3240,
"summary": "Customer selected the premium package.",
"custom_insights": null,
"surveys": [],
"appointment_id": "appt-1234",
"customer": {
"name": "Jordan Lee",
"email": "jordan@example.com",
"phone": null
}
}
}Verify the raw request body
With signing enabled, X-Rilla-Signature contains sha256=<hex>. Compute HMAC-SHA256 over the exact raw bytes and compare in constant time. Do not parse and re-serialize the body before verification.
import { createHmac, timingSafeEqual } from 'node:crypto';
// secret comes from your server's secret manager.
function verify(rawBody, header, secret) {
if (!/^sha256=[a-f0-9]{64}$/i.test(header ?? '')) {
return false;
}
const expected = createHmac('sha256', secret)
.update(rawBody).digest();
const provided = Buffer.from(header.slice(7), 'hex');
return provided.length === expected.length &&
timingSafeEqual(expected, provided);
}Delivery and retries
Verify and durably accept the event, then return a 2xx within 10 seconds. Process lengthy work from your own queue. Make downstream writes idempotent using stable business identifiers such as conversation_id. A network interruption can lead to a retry even if your handler already processed the request. Do not rely on webhook_event_id staying the same across attempts.
| Delivery | Behavior |
|---|---|
| Attempts | Delivery is best-effort. Confirm the applicable retry policy with Rilla; do not depend on an exact delivery schedule. |
| Final failure | Moved to a Rilla-side dead-letter queue; contact your account manager for replay. |
| Multiple subscriptions | Delivery retries are not independent for each subscriber. Reconcile missed events through the Data Export API. |
| Ordering | Not guaranteed. |
| Transcript URL | Temporary; download the content promptly rather than persisting only its URL. |