Webhook Ingest
Public-facing webhook endpoint that receives real-time call event notifications from Ultravox. Authentication is performed via URL path parameters (agency ID and webhook secret) rather than JWT tokens. Events are logged and queued for asynchronous processing by process-webhook-queue.
Endpoint
| Property | Value |
|---|---|
| Function Name | webhook-ingest |
| HTTP Method | POST |
| Authentication | URL-path-based: agency_id and webhook_secret embedded in the URL path. No JWT authentication. |
| Required Role | None (external webhook caller authenticated by secret) |
URL Format
POST /functions/v1/webhook-ingest/{agency_id}/{webhook_secret}
The agency_id and webhook_secret are extracted from the URL path segments. This URL is provided to the Ultravox webhook configuration and is returned by the get-integration-status endpoint.
Request
Headers
No specific headers are required beyond standard HTTP headers. No Authorization header is needed.
URL Parameters
| Field | Type | Required | Description |
|---|---|---|---|
agency_id | string (UUID) | Yes | The agency's unique identifier (extracted from URL path) |
webhook_secret | string | Yes | The agency's webhook secret for authentication (extracted from URL path) |
Body
The request body is a JSON payload conforming to the Ultravox webhook event format:
| Field | Type | Required | Description |
|---|---|---|---|
event | string | Yes | Event type: call.started, call.joined, or call.ended |
call | object | Yes | Call data object |
call.callId | string | Yes | Ultravox call identifier |
call.created | string (ISO 8601) | Yes | When the call was created |
call.joined | string (ISO 8601) | No | When the call was joined |
call.ended | string (ISO 8601) | No | When the call ended |
call.endReason | string | No | Reason the call ended |
call.agentId | string | No | Ultravox agent identifier |
call.agent | object | No | Agent details (agentId, name) |
call.metadata | object | No | Arbitrary metadata attached to the call |
call.shortSummary | string | No | Brief call summary (available on call.ended) |
call.summary | string | No | Full call summary (available on call.ended) |
{
"event": "call.ended",
"call": {
"callId": "ultravox-call-uuid",
"created": "2025-03-15T10:00:00Z",
"joined": "2025-03-15T10:00:05Z",
"ended": "2025-03-15T10:15:30Z",
"endReason": "hangup",
"agentId": "agent-uuid-123",
"agent": {
"agentId": "agent-uuid-123",
"name": "Sales Bot Alpha"
},
"shortSummary": "Customer inquired about pricing for enterprise plan."
}
}
Response
Success (204)
Returns an empty body with HTTP 204 (No Content) on successful queuing. This follows webhook best practice of returning quickly without a response body.
Error Responses
| Status | Condition |
|---|---|
| 400 | Missing agency_id or webhook_secret in the URL path |
| 400 | Invalid payload structure (missing event or call.callId) |
| 401 | Agency not found or webhook secret does not match (verified via get_agency_by_webhook_credentials RPC) |
| 405 | HTTP method is not POST |
| 500 | Failed to queue the webhook event, or unexpected server error |
Behavior
- Reject non-POST requests with
405. - Extract credentials from the URL path: parses
agency_idandwebhook_secretfrom path segments. - Validate payload structure: Ensures
eventandcall.callIdare present. - Verify credentials: Calls
get_agency_by_webhook_credentialsRPC to validate that theagency_idexists and thewebhook_secretmatches. - Log the webhook: Inserts a record into the
webhook_logstable with the agency ID, event type, full payload, and source IP (fromx-forwarded-forheader). - Queue for processing: Calls
insert_webhook_eventRPC to add the event to the webhook processing queue. - Return 204: Responds immediately with no body, ensuring fast webhook acknowledgment.
Database Tables / RPCs
| Table / RPC | Operation | Description |
|---|---|---|
get_agency_by_webhook_credentials (RPC) | Read | Validates the agency ID and webhook secret pair |
webhook_logs | Write (Insert) | Logs every incoming webhook event with metadata |
insert_webhook_event (RPC) | Write | Queues the event for asynchronous processing |
External APIs
None. This function is the receiver of external webhook calls, not a caller.
Related Functions
process-webhook-queue-- Consumes queued events created by this function and upserts call recordsprocess-enrichment-queue-- Further enriches call records with transcripts and AI analysisget-integration-status-- Returns the webhook URL that points to this endpoint