Skip to content
RelationsAI
Try it uses test keys only. Requests go straight from your browser to https://voice-api.relationsai.com/v1 with a rai_test_ key, which never places a real call. It works once the API is enabled for your workspace (private preview: support@relationsai.com). Your key stays in this tab's memory; live keys are refused.
RelationsAI API

Receive signed event notifications on your server.


List webhook endpoints

GET
https://voice-api.relationsai.com/v1
/webhook-endpoints
Bearer (rai_test_... or rai_live_...)

Lists the webhook endpoints of the key's mode, newest first. Secrets are never listed, only their last four characters.

GET /v1/webhook-endpoints · Operation ID: listWebhookEndpoints

List webhook endpoints › query Parameters

limit
​integer · min: 1 · max: 100

Maximum number of objects to return, from 1 to 100. Defaults to 25.

Default: 25
cursor
​string · minLength: 1 · maxLength: 512

The next_cursor of the previous page. Send it with exactly the same filters as the request that returned it; a changed filter set is 400 invalid_cursor.

List webhook endpoints › Responses

A page of endpoints.

A page of webhook endpoints, newest first.
object
​string · const · required

Always list.

Const value: list
has_more
​boolean · required

True when more objects exist after this page.

next_cursor
​string | null · required

Pass as cursor (with the same filters) to fetch the next page. Null on the last page.

​WebhookEndpoint[] · required

Endpoints on this page.


Create a webhook endpoint

POST
https://voice-api.relationsai.com/v1
/webhook-endpoints
Bearer (rai_test_... or rai_live_...)

Registers an HTTPS URL to receive events of the key's mode. The response contains the signing secret (whsec_...) once; store it to verify signatures. A replay with the same Idempotency-Key returns the same endpoint with secret: null (the secret is never stored in readable form; if it was lost, rotate it). Every delivery is a POST with the event as JSON and these headers: RelationsAI-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<raw body>" with the secret>, RelationsAI-Event-Id, RelationsAI-Event-Type, RelationsAI-Delivery-Id and User-Agent: RelationsAI-Webhooks/1.0. Reject a signature older than 5 minutes.

Answer with any 2xx within 10 seconds. Anything else is retried after about 10 seconds, 1 minute, 5 minutes, 30 minutes, 2 hours, 6 hours and 12 hours, then marked failed. Delivery is at-least-once and unordered. Redirects are not followed. The URL must be public HTTPS on port 443. Back-pressure: at most 2 attempts are in flight to one endpoint at a time; after 5 failed attempts in a row an endpoint is paused (1 minute, doubling up to 1 hour) and its waiting deliveries are attempted after the pause, without using up their attempts; one success resumes it. The endpoint is never disabled automatically. Live-mode deliveries are attempted before test-mode ones, and a workspace's test-mode deliveries are limited to 60 attempts a minute.

POST /v1/webhook-endpoints · Operation ID: createWebhookEndpoint

Create a webhook endpoint › Headers

Idempotency-Key
​string · minLength: 1 · maxLength: 255 · pattern: ^[\x21-\x7E]+$

Optional. A unique key for this operation, 1 to 255 printable ASCII characters with no spaces (a UUID v4 is ideal). With it, a retry of the same request (same key, same body) returns the stored answer and never runs the action twice; reuse the same key for every retry, it is kept for 24 hours. Without it, every request runs: a retry after a timeout can repeat the action, so check the state with a GET before retrying.

Create a webhook endpoint › Request Body

Create a webhook endpoint in the key's mode.
url
​string · uri · maxLength: 2048 · pattern: ^https:// · required

Must start with https://; any other scheme is refused with 400 validation_error (issue invalid_format) before the URL is checked. Then: port 443 only, no user name or password, not a RelationsAI host, and the host must resolve only to public internet addresses, otherwise 422 webhook_url_not_allowed. Checked when created, when changed, and again on every delivery.

events
​WebhookSubscribableEventType[] · minItems: 1 · unique · required

Event types to deliver. webhook_endpoint.test cannot be subscribed to (the test operation always delivers it).

Enum values:
call.ended
call.settled
campaign.started
campaign.paused
campaign.resumed
campaign.stopped
campaign.completed
campaign.failed
description
​string · maxLength: 500

Your note about the endpoint.

Create a webhook endpoint › Responses

The endpoint was created. Store secret now; it is not shown again.

A webhook endpoint together with its signing secret. The secret is shown only in this response; store it now.
id
​string · pattern: ^we_[A-Za-z0-9_-]{1,… · required

Endpoint id (we_...).

object
​string · const · required

Always webhook_endpoint.

Const value: webhook_endpoint
livemode
​boolean · required

The endpoint receives events of this mode only.

url
​string · uri · required

Where events are delivered.

description
​string | null · required

Your note about the endpoint.

events
​WebhookSubscribableEventType[] · required

Event types delivered to this endpoint. The test event is delivered on request regardless of this list.

Enum values:
call.ended
call.settled
campaign.started
campaign.paused
campaign.resumed
campaign.stopped
campaign.completed
campaign.failed
status
​string · enum · required

enabled endpoints receive deliveries; disabled ones do not. Open enum.

Enum values:
enabled
disabled
secret_last4
​string · required

Last four characters of the current signing secret, to tell secrets apart.

created_at
​string · date-time · required

When the endpoint was created.

updated_at
​string · date-time · required

When the endpoint was last changed.

​required

The most recent delivery attempt, or null if none yet.

secret
​string | null · pattern: ^whsec_[A-Za-z0-9_-]… · required

The signing secret (whsec_...), shown only in the first response to the create or rotate request. null on an idempotent replay of that request (same Idempotency-Key): the secret is stored only encrypted and is never returned again. If it was lost, rotate the secret.


Retrieve a webhook endpoint

GET
https://voice-api.relationsai.com/v1
/webhook-endpoints/{webhook_endpoint_id}
Bearer (rai_test_... or rai_live_...)

Returns one webhook endpoint with a summary of its most recent delivery.

GET /v1/webhook-endpoints/{webhook_endpoint_id} · Operation ID: getWebhookEndpoint

Retrieve a webhook endpoint › path Parameters

webhook_endpoint_id
​string · pattern: ^we_[A-Za-z0-9_-]{1,… · required

The webhook endpoint id (we_...).

Retrieve a webhook endpoint › Responses

The endpoint.

A URL on your server that receives signed event notifications for one mode. Deliveries are at-least-once and not ordered; use the event `id` to discard duplicates and the resource's own timestamps or status to discard stale updates.
id
​string · pattern: ^we_[A-Za-z0-9_-]{1,… · required

Endpoint id (we_...).

object
​string · const · required

Always webhook_endpoint.

Const value: webhook_endpoint
livemode
​boolean · required

The endpoint receives events of this mode only.

url
​string · uri · required

Where events are delivered.

description
​string | null · required

Your note about the endpoint.

events
​WebhookSubscribableEventType[] · required

Event types delivered to this endpoint. The test event is delivered on request regardless of this list.

Enum values:
call.ended
call.settled
campaign.started
campaign.paused
campaign.resumed
campaign.stopped
campaign.completed
campaign.failed
status
​string · enum · required

enabled endpoints receive deliveries; disabled ones do not. Open enum.

Enum values:
enabled
disabled
secret_last4
​string · required

Last four characters of the current signing secret, to tell secrets apart.

created_at
​string · date-time · required

When the endpoint was created.

updated_at
​string · date-time · required

When the endpoint was last changed.

​required

The most recent delivery attempt, or null if none yet.


Delete a webhook endpoint

DELETE
https://voice-api.relationsai.com/v1
/webhook-endpoints/{webhook_endpoint_id}
Bearer (rai_test_... or rai_live_...)

Deletes the endpoint. Pending deliveries to it are cancelled. This cannot be undone.

DELETE /v1/webhook-endpoints/{webhook_endpoint_id} · Operation ID: deleteWebhookEndpoint

Delete a webhook endpoint › path Parameters

webhook_endpoint_id
​string · pattern: ^we_[A-Za-z0-9_-]{1,… · required

The webhook endpoint id (we_...).

Delete a webhook endpoint › Headers

Idempotency-Key
​string · minLength: 1 · maxLength: 255 · pattern: ^[\x21-\x7E]+$

Optional. A unique key for this operation, 1 to 255 printable ASCII characters with no spaces (a UUID v4 is ideal). With it, a retry of the same request (same key, same body) returns the stored answer and never runs the action twice; reuse the same key for every retry, it is kept for 24 hours. Without it, every request runs: a retry after a timeout can repeat the action, so check the state with a GET before retrying.

Delete a webhook endpoint › Responses

The endpoint was deleted.

Returned by a successful delete. The object no longer exists.
id
​string · required

Id of the deleted object.

object
​string · required

Type of the deleted object, for example contact.

livemode
​boolean · required

true for live mode, false for test mode.

deleted
​boolean · const · required

Always true.

Const value:

Update a webhook endpoint

PATCH
https://voice-api.relationsai.com/v1
/webhook-endpoints/{webhook_endpoint_id}
Bearer (rai_test_... or rai_live_...)

Changes the URL, description, subscribed events or status. Disabling an endpoint stops new deliveries to it; events that occur while it is disabled are not delivered later.

PATCH /v1/webhook-endpoints/{webhook_endpoint_id} · Operation ID: updateWebhookEndpoint

Update a webhook endpoint › path Parameters

webhook_endpoint_id
​string · pattern: ^we_[A-Za-z0-9_-]{1,… · required

The webhook endpoint id (we_...).

Update a webhook endpoint › Request Body

Fields to change. Omitted fields are left as they are.
url
​string · uri · maxLength: 2048 · pattern: ^https://

Must start with https://; any other scheme is refused with 400 validation_error (issue invalid_format) before the URL is checked. Then: port 443 only, no user name or password, not a RelationsAI host, and the host must resolve only to public internet addresses, otherwise 422 webhook_url_not_allowed. Checked when created, when changed, and again on every delivery.

description
​string | null · maxLength: 500

Your note about the endpoint. Null clears it.

events
​WebhookSubscribableEventType[] · minItems: 1 · unique

Event types to deliver. Replaces the current list. webhook_endpoint.test cannot be subscribed to (the test operation always delivers it).

Enum values:
call.ended
call.settled
campaign.started
campaign.paused
campaign.resumed
campaign.stopped
campaign.completed
campaign.failed
status
​string · enum

enabled or disabled.

Enum values:
enabled
disabled

Update a webhook endpoint › Responses

The updated endpoint.

A URL on your server that receives signed event notifications for one mode. Deliveries are at-least-once and not ordered; use the event `id` to discard duplicates and the resource's own timestamps or status to discard stale updates.
id
​string · pattern: ^we_[A-Za-z0-9_-]{1,… · required

Endpoint id (we_...).

object
​string · const · required

Always webhook_endpoint.

Const value: webhook_endpoint
livemode
​boolean · required

The endpoint receives events of this mode only.

url
​string · uri · required

Where events are delivered.

description
​string | null · required

Your note about the endpoint.

events
​WebhookSubscribableEventType[] · required

Event types delivered to this endpoint. The test event is delivered on request regardless of this list.

Enum values:
call.ended
call.settled
campaign.started
campaign.paused
campaign.resumed
campaign.stopped
campaign.completed
campaign.failed
status
​string · enum · required

enabled endpoints receive deliveries; disabled ones do not. Open enum.

Enum values:
enabled
disabled
secret_last4
​string · required

Last four characters of the current signing secret, to tell secrets apart.

created_at
​string · date-time · required

When the endpoint was created.

updated_at
​string · date-time · required

When the endpoint was last changed.

​required

The most recent delivery attempt, or null if none yet.


Rotate a webhook signing secret

POST
https://voice-api.relationsai.com/v1
/webhook-endpoints/{webhook_endpoint_id}/rotate-secret
Bearer (rai_test_... or rai_live_...)

Issues a new signing secret, returned once. During the grace period every delivery carries two v1= signatures, one per secret, so you can deploy the new secret without missing events; after it, only the new secret signs. At most two secrets ever sign a delivery.

Rotating again while a grace period runs:

  • grace_period_hours: 0 is always allowed and retires EVERY previous secret immediately: use it when a secret may have leaked, and deploy the new one at once.
  • a grace period above 0 keeps the OLDEST secret still signing (the one your receiver most likely uses) until its original grace end, discards the secret issued by the rotation in between, and issues a new one. Use it when the response to a rotation was lost.

A replay of this request with the same Idempotency-Key returns the endpoint with secret: null: the secret is shown only in the first response and is never stored in readable form. To recover a secret you did not receive, rotate again (with a grace period, as above).

POST /v1/webhook-endpoints/{webhook_endpoint_id}/rotate-secret · Operation ID: rotateWebhookEndpointSecret

Rotate a webhook signing secret › path Parameters

webhook_endpoint_id
​string · pattern: ^we_[A-Za-z0-9_-]{1,… · required

The webhook endpoint id (we_...).

Rotate a webhook signing secret › Headers

Idempotency-Key
​string · minLength: 1 · maxLength: 255 · pattern: ^[\x21-\x7E]+$

Optional. A unique key for this operation, 1 to 255 printable ASCII characters with no spaces (a UUID v4 is ideal). With it, a retry of the same request (same key, same body) returns the stored answer and never runs the action twice; reuse the same key for every retry, it is kept for 24 hours. Without it, every request runs: a retry after a timeout can repeat the action, so check the state with a GET before retrying.

Rotate a webhook signing secret › Request Body

How long the previous secret keeps signing deliveries alongside the new one.
grace_period_hours
​integer · enum · required

Hours during which every delivery carries two signatures, one per secret, so you can deploy the new secret without dropping events. 0 retires every previous secret immediately (always allowed, also during a grace period). A value above 0 during a running grace period keeps the oldest secret still signing until its original grace end and discards the one in between.

Enum values:
0
1
24
168

Rotate a webhook signing secret › Responses

The endpoint with its new secret. Store it now.

A webhook endpoint together with its signing secret. The secret is shown only in this response; store it now.
id
​string · pattern: ^we_[A-Za-z0-9_-]{1,… · required

Endpoint id (we_...).

object
​string · const · required

Always webhook_endpoint.

Const value: webhook_endpoint
livemode
​boolean · required

The endpoint receives events of this mode only.

url
​string · uri · required

Where events are delivered.

description
​string | null · required

Your note about the endpoint.

events
​WebhookSubscribableEventType[] · required

Event types delivered to this endpoint. The test event is delivered on request regardless of this list.

Enum values:
call.ended
call.settled
campaign.started
campaign.paused
campaign.resumed
campaign.stopped
campaign.completed
campaign.failed
status
​string · enum · required

enabled endpoints receive deliveries; disabled ones do not. Open enum.

Enum values:
enabled
disabled
secret_last4
​string · required

Last four characters of the current signing secret, to tell secrets apart.

created_at
​string · date-time · required

When the endpoint was created.

updated_at
​string · date-time · required

When the endpoint was last changed.

​required

The most recent delivery attempt, or null if none yet.

secret
​string | null · pattern: ^whsec_[A-Za-z0-9_-]… · required

The signing secret (whsec_...), shown only in the first response to the create or rotate request. null on an idempotent replay of that request (same Idempotency-Key): the secret is stored only encrypted and is never returned again. If it was lost, rotate the secret.


Send a test event

POST
https://voice-api.relationsai.com/v1
/webhook-endpoints/{webhook_endpoint_id}/test
Bearer (rai_test_... or rai_live_...)

Creates a webhook_endpoint.test event and delivers it to this endpoint only, signed like any other event. The response is the delivery, usually pending; read the deliveries list to see the result.

POST /v1/webhook-endpoints/{webhook_endpoint_id}/test · Operation ID: sendWebhookEndpointTestEvent

Send a test event › path Parameters

webhook_endpoint_id
​string · pattern: ^we_[A-Za-z0-9_-]{1,… · required

The webhook endpoint id (we_...).

Send a test event › Headers

Idempotency-Key
​string · minLength: 1 · maxLength: 255 · pattern: ^[\x21-\x7E]+$

Optional. A unique key for this operation, 1 to 255 printable ASCII characters with no spaces (a UUID v4 is ideal). With it, a retry of the same request (same key, same body) returns the stored answer and never runs the action twice; reuse the same key for every retry, it is kept for 24 hours. Without it, every request runs: a retry after a timeout can repeat the action, so check the state with a GET before retrying.

Send a test event › Responses

The test event was created and its delivery scheduled.

One event's delivery to one endpoint, with its attempts so far.
id
​string · pattern: ^wd_[A-Za-z0-9_-]{1,… · required

Delivery id (wd_...).

object
​string · const · required

Always webhook_delivery.

Const value: webhook_delivery
livemode
​boolean · required

Mode of the event.

webhook_endpoint_id
​string · required

The endpoint.

event_id
​string · required

The event delivered (evt_...). Also sent as the RelationsAI-Event-Id header.

event_type
​WebhookEventType · enum · required

An event type. Open enum; new types can be added.

Enum values:
call.ended
call.settled
campaign.started
campaign.paused
campaign.resumed
campaign.stopped
campaign.completed
campaign.failed
status
​string · enum · required

pending (first attempt not made yet), retrying (failed, another attempt is scheduled), succeeded (your server answered 2xx), failed (every attempt failed). Open enum.

Enum values:
pending
retrying
succeeded
failed
attempts
​integer · min: 0 · required

Attempts made so far.

last_attempt_at
​string | null · date-time · required

When the last attempt was made.

next_attempt_at
​string | null · date-time · required

When the next attempt is scheduled, if any.

response_status
​integer | null · required

HTTP status of your server's last answer, if it answered.

duration_ms
​integer | null · min: 0 · required

How long the last attempt took.

error
​string | null · enum · required

Why the last attempt failed: timeout (no answer in 10 seconds), connection_failed (including a host name that did not resolve in time), tls_error, blocked_destination (the URL resolved to a non-public address), http_error (a non-2xx answer), signing_failed (RelationsAI could not sign the delivery; nothing was sent, the attempt still counts, and the delivery fails after its last attempt like any other; contact support if it persists). Null if it succeeded. Open enum.

Enum values:
timeout
connection_failed
tls_error
blocked_destination
http_error
signing_failed
created_at
​string · date-time · required

When the delivery was created.


List deliveries

GET
https://voice-api.relationsai.com/v1
/webhook-endpoints/{webhook_endpoint_id}/deliveries
Bearer (rai_test_... or rai_live_...)

Lists deliveries to this endpoint, newest first, for troubleshooting. Deliveries are kept for 30 days.

GET /v1/webhook-endpoints/{webhook_endpoint_id}/deliveries · Operation ID: listWebhookDeliveries

List deliveries › path Parameters

webhook_endpoint_id
​string · pattern: ^we_[A-Za-z0-9_-]{1,… · required

The webhook endpoint id (we_...).

List deliveries › query Parameters

limit
​integer · min: 1 · max: 100

Maximum number of objects to return, from 1 to 100. Defaults to 25.

Default: 25
cursor
​string · minLength: 1 · maxLength: 512

The next_cursor of the previous page. Send it with exactly the same filters as the request that returned it; a changed filter set is 400 invalid_cursor.

status
​string · enum

Only deliveries in this status.

Enum values:
pending
retrying
succeeded
failed

List deliveries › Responses

A page of deliveries.

A page of deliveries, newest first.
object
​string · const · required

Always list.

Const value: list
has_more
​boolean · required

True when more objects exist after this page.

next_cursor
​string | null · required

Pass as cursor (with the same filters) to fetch the next page. Null on the last page.

​WebhookDelivery[] · required

Deliveries on this page.


Retry a delivery

POST
https://voice-api.relationsai.com/v1
/webhook-deliveries/{webhook_delivery_id}/retry
Bearer (rai_test_... or rai_live_...)

Schedules an immediate new attempt of a failed or retrying delivery. The event and its id are unchanged, so your duplicate check still works.

POST /v1/webhook-deliveries/{webhook_delivery_id}/retry · Operation ID: retryWebhookDelivery

Retry a delivery › path Parameters

webhook_delivery_id
​string · pattern: ^wd_[A-Za-z0-9_-]{1,… · required

The webhook delivery id (wd_...).

Retry a delivery › Headers

Idempotency-Key
​string · minLength: 1 · maxLength: 255 · pattern: ^[\x21-\x7E]+$

Optional. A unique key for this operation, 1 to 255 printable ASCII characters with no spaces (a UUID v4 is ideal). With it, a retry of the same request (same key, same body) returns the stored answer and never runs the action twice; reuse the same key for every retry, it is kept for 24 hours. Without it, every request runs: a retry after a timeout can repeat the action, so check the state with a GET before retrying.

Retry a delivery › Responses

A new attempt was scheduled.

One event's delivery to one endpoint, with its attempts so far.
id
​string · pattern: ^wd_[A-Za-z0-9_-]{1,… · required

Delivery id (wd_...).

object
​string · const · required

Always webhook_delivery.

Const value: webhook_delivery
livemode
​boolean · required

Mode of the event.

webhook_endpoint_id
​string · required

The endpoint.

event_id
​string · required

The event delivered (evt_...). Also sent as the RelationsAI-Event-Id header.

event_type
​WebhookEventType · enum · required

An event type. Open enum; new types can be added.

Enum values:
call.ended
call.settled
campaign.started
campaign.paused
campaign.resumed
campaign.stopped
campaign.completed
campaign.failed
status
​string · enum · required

pending (first attempt not made yet), retrying (failed, another attempt is scheduled), succeeded (your server answered 2xx), failed (every attempt failed). Open enum.

Enum values:
pending
retrying
succeeded
failed
attempts
​integer · min: 0 · required

Attempts made so far.

last_attempt_at
​string | null · date-time · required

When the last attempt was made.

next_attempt_at
​string | null · date-time · required

When the next attempt is scheduled, if any.

response_status
​integer | null · required

HTTP status of your server's last answer, if it answered.

duration_ms
​integer | null · min: 0 · required

How long the last attempt took.

error
​string | null · enum · required

Why the last attempt failed: timeout (no answer in 10 seconds), connection_failed (including a host name that did not resolve in time), tls_error, blocked_destination (the URL resolved to a non-public address), http_error (a non-2xx answer), signing_failed (RelationsAI could not sign the delivery; nothing was sent, the attempt still counts, and the delivery fails after its last attempt like any other; contact support if it persists). Null if it succeeded. Open enum.

Enum values:
timeout
connection_failed
tls_error
blocked_destination
http_error
signing_failed
created_at
​string · date-time · required

When the delivery was created.