Skip to main content

Payload Spec

Delivery format

JSON over HTTPS POST. Content-Type: application/json.

Sample payload (Custom endpoint)

{
"projectId": "3c9acfb1-c6b7-4bbc-b6c3-628af54d56c1",
"webhookEndpoint": {
"id": "ep-001",
"name": "Production Notifications",
"endpointType": "CUSTOM",
"target": "https://example.com/webhook",
"contentKey": null
},
"eventType": "OUTBOUND_CALL_ERROR",
"body": {
"subject": "[Recho] Outbound call error",
"text": "[Recho] Outbound call error\n━━━━━━━━━━━━━━\ncallId: abc-123\ncallStatus: CALLING\ncallSid: CA94b51...\nclientId: client-1\n━━━━━━━━━━━━━━\nErrors:\n - [NETWORK_ERROR] Connection timed out (phase: CONNECTING)\n━━━━━━━━━━━━━━\nTime: 2026-05-12 10:24:00",
"data": {
"callId": "abc-123",
"callStatus": "CALLING",
"callSid": "CA94b51...",
"clientId": "client-1"
},
"errors": [
{
"code": "NETWORK_ERROR",
"message": "Connection timed out",
"timestamp": "2026-05-12T10:23:45.000Z",
"where": "OutboundCallAdapter.connect",
"phase": "CONNECTING",
"stacktrace": ""
}
]
},
"authConfig": { "authType": "NONE" }
}
note

Slack / Teams / Email deliveries are transformed internally; only Custom endpoints receive this exact structure.

Top-level fields

FieldTypeHow to use it
projectIdstringOriginating project ID (UUID). Use for routing or authorization checks in multi-project setups.
webhookEndpointWebhookEndpointSnapshot of the destination endpoint configuration. Use to identify which endpoint configuration produced this delivery when running multiple endpoints.
eventTypeEventTypeThe event kind. Use as the switch key on the receiver side. See Events for the full list.
bodyWebhookBodyThe notification body (described below).
authConfigAuthConfigReference info about how this request was authenticated. The actual authentication verification happens in the request headers (see Authentication). The payload only carries which method was used.

webhookEndpoint fields

FieldTypeHow to use it
idstringEndpoint ID (Recho-internal primary key). Use when correlating logs or contacting support.
namestringEndpoint name (display name in the dashboard).
endpointType'SLACK' | 'TEAMS' | 'EMAIL' | 'CUSTOM'Endpoint kind. Only Custom endpoints receive this structure verbatim.
targetstringThe configured destination (Custom: URL / Slack/Teams: Incoming Webhook URL / Email: address). Informational.
contentKeystring | nullTemplate kind key. null means the default format.

body fields

FieldTypeHow to use it
subjectstringDisplay-oriented subject. Use as the email Subject header or as a heading in UI.
textstringDisplay-oriented formatted body (human-readable). Includes newlines (\n) and separator lines. Stream it to Slack / Teams messages, log views, or email body. Do not parse it programmatically.
dataRecord<string, string>Machine-readable identification info. A flat string-to-string map containing keys like callId / callStatus / callSid / clientId. Read this in your program.
errorsArray<CallError> | undefinedPresent only on error. Detect errors via body.errors?.length and use the array for detail logs and notifications.

body.data fields (call identification)

FieldTypeHow to use it
callIdstringUnique call ID. The primary key for identifying a call in external systems. Events for the same callId are delivered in FIFO order (see Setup Guide).
callStatusstringCall status at the moment the notification was emitted. See callStatus reference for the full list of values. Do not use this to detect errors (use errors array instead).
callSidstringCarrier-side call ID (empty string when unavailable). Use for cross-referencing with the telephony provider's logs.
clientIdstringOptional client identifier (empty string when unspecified). Carries the application-side ID you supplied when initiating the call.

eventType

The eventType field corresponds one-to-one with the items listed in Notification Triggers in the dashboard. Whatever triggers you enable there are what you receive as eventType values.

See the Events page for the full list of 18 event types and their payload examples.

TypeScript type

type EventType =
// Outbound
| 'OUTBOUND_CALL_PENDING'
| 'OUTBOUND_CALL_REQUESTED'
| 'OUTBOUND_CALL_CALLING'
| 'OUTBOUND_CALL_CLOSING'
| 'OUTBOUND_CALL_COMPLETED'
| 'OUTBOUND_CALL_EXPIRED'
| 'OUTBOUND_CALL_NO_RESPONSE'
| 'OUTBOUND_CALL_CANCELED'
| 'OUTBOUND_CALL_BUSY'
| 'OUTBOUND_CALL_UNREACHABLE'
| 'OUTBOUND_CALL_MAX_ATTEMPTS_REACHED'
| 'OUTBOUND_CALL_ERROR'
// Inbound
| 'INBOUND_CALL_CONNECTING'
| 'INBOUND_CALL_CALLING'
| 'INBOUND_CALL_CLOSING'
| 'INBOUND_CALL_COMPLETED'
| 'INBOUND_CALL_CONCURRENCY_LIMIT_EXCEEDED'
| 'INBOUND_CALL_ERROR';
info

Events not enabled in the dashboard are not delivered at all.

body.errors[] (error details)

Included only when errors occurred. The array contains one or more entries with the following shape:

FieldTypeRequiredExampleHow to use it
codestringrequired"NETWORK_ERROR"Machine-readable error code (^[A-Z0-9_]+$). Use as a switch key on the receiver side. See the catalog below.
messagestringrequired"Connection timed out"Human-readable error message (Japanese or English). Display / log purposes.
timestampstring (ISO8601)required"2026-05-12T10:23:45.000Z"Error occurrence time (UTC, millisecond precision). Use for time-ordered sorting.
wherestringrequired"OutboundCallAdapter.connect"Origin of the error (class / function / module name). Reference info for Recho-side investigation.
phasestringrequired"CONNECTING"Phase of the call at which the error occurred. Use for root-cause categorization and aggregation.
stacktracestringrequired"Error: Connection timed out\n at ..."Stack trace. May be empty (e.g. for errors originating outside the system). For first-pass investigation.
Important

Detect errors by checking that body.errors is non-empty. body.data.callStatus may contain transitional statuses such as CALLING even when an error occurred — it is not fixed to ERROR.

TypeScript types

type CallError = {
code: string; // matches ^[A-Z0-9_]+$
message: string;
timestamp: string; // ISO 8601 (UTC)
where: string;
phase: string;
stacktrace: string;
};

type WebhookBody = {
subject: string;
text: string;
data: Record<string, string>;
errors?: CallError[]; // only on error
};

Common error codes

Other codes may appear beyond the ones listed here. Receivers should handle unknown codes gracefully (e.g. log via the default arm of a switch statement).

CodeCategoryDescription
WEBSOCKET_CONNECTION_FAILEDWebSocketFailed to connect to the Voice AI WebSocket.
INVALID_REQUEST_IDRequest validationInvalid request ID or phone number.
INTERNATIONAL_PERMISSION_ERRORRequest validationInternational dialing not permitted.
STATUS_UPDATE_TO_CALLING_FAILEDStatus transitionTransition to CALLING failed.
STATUS_UPDATE_TO_CLOSING_FAILEDStatus transitionTransition to CLOSING failed.
STATUS_UPDATE_TO_FINAL_STATUS_FAILEDStatus transitionTransition to a final status (COMPLETED, etc.) failed.
STATUS_UPDATE_TO_ERROR_FAILEDStatus transition(Legacy) transition to ERROR failed.
STATUS_UPDATE_TO_CONCURRENCY_LIMIT_EXCEEDED_FAILEDStatus transitionTransition to CONCURRENCY_LIMIT_EXCEEDED failed.
VOICEAI_PROCESSING_ERRORVoiceAIInternal VoiceAI processing error during the call.
PRE_VOICEAI_RUNNING_FAILEDVoiceAIPre-call VoiceAI processing failed (config fetch, hooks, etc.).
POST_VOICEAI_RUNNING_FAILEDVoiceAIPost-call VoiceAI processing failed.
ANALYZER_FAILEDAnalysisCall-result analysis failed.
GEMINI_ANALYZER_FAILEDAnalysisGemini-based analysis failed.
HISTORY_FORMAT_FAILEDAnalysisFailed to format the conversation history.
CALL_LOG_SAVE_FAILEDCallLog persistenceFailed to persist the call log.
GEMINI_API_UNAVAILABLEExternal APIGemini API unavailable.
STATUS_UPDATE_IN_CALLBACK_FAILEDCallbackStatus-update failure inside the post-disconnect callback.
CALLBACK_PROCESSING_FAILEDCallbackGeneral failure inside the post-disconnect callback.
STALE_CALL_STATUS_DETECTEDInternal monitoringThe status did not transition for an unusually long time (detected by an internal monitor).
CALL_INITIATION_FAILEDCall initiationThe telephony provider failed to initiate the call.
NETWORK_ERRORNetworkGeneric network I/O failure.
TIMEOUTNetworkExternal request or internal processing timed out.