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" }
}
Slack / Teams / Email deliveries are transformed internally; only Custom endpoints receive this exact structure.
Top-level fields
| Field | Type | How to use it |
|---|---|---|
projectId | string | Originating project ID (UUID). Use for routing or authorization checks in multi-project setups. |
webhookEndpoint | WebhookEndpoint | Snapshot of the destination endpoint configuration. Use to identify which endpoint configuration produced this delivery when running multiple endpoints. |
eventType | EventType | The event kind. Use as the switch key on the receiver side. See Events for the full list. |
body | WebhookBody | The notification body (described below). |
authConfig | AuthConfig | Reference 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
| Field | Type | How to use it |
|---|---|---|
id | string | Endpoint ID (Recho-internal primary key). Use when correlating logs or contacting support. |
name | string | Endpoint name (display name in the dashboard). |
endpointType | 'SLACK' | 'TEAMS' | 'EMAIL' | 'CUSTOM' | Endpoint kind. Only Custom endpoints receive this structure verbatim. |
target | string | The configured destination (Custom: URL / Slack/Teams: Incoming Webhook URL / Email: address). Informational. |
contentKey | string | null | Template kind key. null means the default format. |
body fields
| Field | Type | How to use it |
|---|---|---|
subject | string | Display-oriented subject. Use as the email Subject header or as a heading in UI. |
text | string | Display-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. |
data | Record<string, string> | Machine-readable identification info. A flat string-to-string map containing keys like callId / callStatus / callSid / clientId. Read this in your program. |
errors | Array<CallError> | undefined | Present only on error. Detect errors via body.errors?.length and use the array for detail logs and notifications. |
body.data fields (call identification)
| Field | Type | How to use it |
|---|---|---|
callId | string | Unique 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). |
callStatus | string | Call 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). |
callSid | string | Carrier-side call ID (empty string when unavailable). Use for cross-referencing with the telephony provider's logs. |
clientId | string | Optional 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';
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:
| Field | Type | Required | Example | How to use it |
|---|---|---|---|---|
code | string | required | "NETWORK_ERROR" | Machine-readable error code (^[A-Z0-9_]+$). Use as a switch key on the receiver side. See the catalog below. |
message | string | required | "Connection timed out" | Human-readable error message (Japanese or English). Display / log purposes. |
timestamp | string (ISO8601) | required | "2026-05-12T10:23:45.000Z" | Error occurrence time (UTC, millisecond precision). Use for time-ordered sorting. |
where | string | required | "OutboundCallAdapter.connect" | Origin of the error (class / function / module name). Reference info for Recho-side investigation. |
phase | string | required | "CONNECTING" | Phase of the call at which the error occurred. Use for root-cause categorization and aggregation. |
stacktrace | string | required | "Error: Connection timed out\n at ..." | Stack trace. May be empty (e.g. for errors originating outside the system). For first-pass investigation. |
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).
| Code | Category | Description |
|---|---|---|
WEBSOCKET_CONNECTION_FAILED | WebSocket | Failed to connect to the Voice AI WebSocket. |
INVALID_REQUEST_ID | Request validation | Invalid request ID or phone number. |
INTERNATIONAL_PERMISSION_ERROR | Request validation | International dialing not permitted. |
STATUS_UPDATE_TO_CALLING_FAILED | Status transition | Transition to CALLING failed. |
STATUS_UPDATE_TO_CLOSING_FAILED | Status transition | Transition to CLOSING failed. |
STATUS_UPDATE_TO_FINAL_STATUS_FAILED | Status transition | Transition to a final status (COMPLETED, etc.) failed. |
STATUS_UPDATE_TO_ERROR_FAILED | Status transition | (Legacy) transition to ERROR failed. |
STATUS_UPDATE_TO_CONCURRENCY_LIMIT_EXCEEDED_FAILED | Status transition | Transition to CONCURRENCY_LIMIT_EXCEEDED failed. |
VOICEAI_PROCESSING_ERROR | VoiceAI | Internal VoiceAI processing error during the call. |
PRE_VOICEAI_RUNNING_FAILED | VoiceAI | Pre-call VoiceAI processing failed (config fetch, hooks, etc.). |
POST_VOICEAI_RUNNING_FAILED | VoiceAI | Post-call VoiceAI processing failed. |
ANALYZER_FAILED | Analysis | Call-result analysis failed. |
GEMINI_ANALYZER_FAILED | Analysis | Gemini-based analysis failed. |
HISTORY_FORMAT_FAILED | Analysis | Failed to format the conversation history. |
CALL_LOG_SAVE_FAILED | CallLog persistence | Failed to persist the call log. |
GEMINI_API_UNAVAILABLE | External API | Gemini API unavailable. |
STATUS_UPDATE_IN_CALLBACK_FAILED | Callback | Status-update failure inside the post-disconnect callback. |
CALLBACK_PROCESSING_FAILED | Callback | General failure inside the post-disconnect callback. |
STALE_CALL_STATUS_DETECTED | Internal monitoring | The status did not transition for an unusually long time (detected by an internal monitor). |
CALL_INITIATION_FAILED | Call initiation | The telephony provider failed to initiate the call. |
NETWORK_ERROR | Network | Generic network I/O failure. |
TIMEOUT | Network | External request or internal processing timed out. |