Receive results
Configure one endpoint and the platform pushes the results you subscribe to.
Call completion, saved business actions and later analysis are separate events;
enable the ones you need with
PUT /v1/webhook-endpoint {"url": …, "enabled_events": […]}.
Review results in the workspace
Section titled “Review results in the workspace”Home → Recent conversations and Activity → Calls show up to three current recorded responses from each call, including qualification status, shift responses, and saved or proposed caller details. These remain available when an AI summary is unavailable. If a call has more responses, the preview shows the total; open the call for every response, its caller evidence and correction history.
Proposed contact changes require review before changing an existing contact. A recorded shift response does not confirm an assignment. Qualification notes describe what was recorded and do not establish a booked appointment or callback.
The call-list API adds recorded_responses and recorded_response_count separately
from AI summary and captured_fields. Preview notes and values may be shortened;
their note_truncated and value_truncated flags identify shortened values. The
full receipt remains in the call detail’s conversation_actions collection.
The result events
Section titled “The result events”call.ended - appended in the same transaction that finalizes the call:
{ "call_id": "call_01J9…", "contact_id": "cont_01J9…", "agent_version_id": "agv_01J9…", "direction": "outbound", "duration_ms": 93000, "disposition": "completed_no_goal", "sub_code": "survey_completed", "recording_available": true, "transcript_available": true, "transcript_url": "/v1/calls/call_01J9…/transcript", "survey_response": { "survey_response_id": "srv_01J9…", "completion_status": "complete", "score": 0.83, "answers": { "csat_overall": { "answer": 4, "verbatim_quote": "a four, pretty good" }, "q_delivered": { "answer": true, "verbatim_quote": "yes it did" } } }, "analysis_pending": true}The completion event carries call metadata and inline survey/appointment results.
Saved action receipts and later analysis arrive separately. Transcript text stays out by design -
transcript_url points at the authenticated API. analysis_pending: true says the
post-call judge hasn’t run yet; its verdict arrives as call.analyzed.
survey.completed - when the call produced a survey response: the ids,
completion_status, score, and the same inline answers.
call.analyzed - minutes later, the judge’s verdict: success, score, a bounded
summary, extracted_fields, per-dimension results (goal completion, disclosure,
opt-out honored, knowledge grounding), and latency percentiles - the same shape
GET /v1/calls/{id} serves in analysis.
Answer entries carry the caller’s verbatim_quote, so the events you enable are your
consent surface for conversation-derived data reaching your endpoint.
One company, several workflows
Section titled “One company, several workflows”A snow-service company can use one receiver for customer reception, worker support, shoveler outreach and customer qualification. Route each verified event inside your integration; subscribing another workflow does not require replacing the company’s existing webhook endpoint.
| Work | Events to consider | What to save in your system |
|---|---|---|
| Customer or worker support | message.taken, ticket.opened, ticket.resolved |
The caller-request ID, call/contact references and the recorded message or ticket state. Use the request ID to correlate resolution. |
| Availability for several shifts | conversation.action_recorded with data.kind = "shift_response" |
A response for each call and subject_ref (shift), plus its source turns and correction history. Accepted, declined and tentative are separate responses. |
| Customer fit or candidate screening | conversation.action_recorded with data.kind = "qualification" |
The sales or recruiting subject, recorded status, summary and configured answers in payload. Preserve answered, unknown and refused rather than converting missing answers to “no.” |
| Call summary | call.ended, then call.analyzed |
Call completion first, then the bounded summary and extracted fields. Analysis can arrive later and does not prove an action succeeded. |
| Suppression | optout.recorded |
The suppression reference and originating call, routed to your contact/suppression workflow. “Not interested” alone is a qualification response, not this event. |
A worker’s accepted response is not a staffing assignment. Your staffing system or dispatcher confirms the assignment. Likewise, captured interest or a next-step note is not a qualified customer, booked callback or hiring decision. Require the corresponding saved action or human decision before promising it.
conversation.action_recorded carries an immutable receipt in data: its id,
call_id, nullable contact_id, kind, subject_ref, revision, response,
payload, source_turns and created_at, plus confirmation evidence when present.
This event is committed with the receipt. The legacy shift.confirmed event is a
compatibility projection; use the receipt collection when one call discusses
several shifts.
Keep corrections and separate shifts
Section titled “Keep corrections and separate shifts”Keep receipt history by data.id. For a current-response view, group by
(tenant_id, call_id, kind, subject_ref). Rank receipts by the highest
source_turns[].turn_number first (zero when absent), then revision as a
tie-breaker. Arrival time and revision alone cannot determine the current answer:
a delayed older turn can be saved with a higher database revision.
For example, these are reduced views of four shift-response receipts in one call:
Shift (subject_ref) |
Response | Highest source turn | Revision | Current response |
|---|---|---|---|---|
| morning-route | accepted | 4 | 1 | Replaced by the later caller correction |
| afternoon-route | tentative | 6 | 1 | Tentative for this separate shift |
| morning-route | declined | 9 | 2 | Declined for the morning shift |
| morning-route | accepted | 3 | 3 | Delayed earlier evidence; keep in history |
Serialize updates to each current-response record or use a transactional compare
and update so concurrent deliveries cannot overwrite newer evidence. Scope
records to the verified tenant. Dedupe the envelope’s event.id, save the receipt
and update the current view in one transaction, or first persist the whole event
in a durable queue and process it idempotently. Return 2xx only after durable
acceptance. The signature verifier below does not implement this storage step.
For recovery, GET /v1/calls/{call_id} with calls:read returns the call’s
conversation_actions history. Rebuild each subject’s current response using the
same ordering. A call’s general disposition or analysis summary does not replace
the per-subject receipts.
Preserve the existing connection
Section titled “Preserve the existing connection”Read GET /v1/webhook-endpoint before changing subscriptions. Preserve its URL,
api_version_pin and existing enabled_events; explicitly add the selected
workflow events to that set. PUT /v1/webhook-endpoint replaces the configuration,
so sending only the new workflow’s events can stop the existing support feed.
Endpoint setup requires webhooks:manage; reading calls requires calls:read.
Keep API keys and signing secrets on your server.
Use the portal’s integration setup or your own receiver to forward verified records into a CRM, staffing system or helpdesk. These are API/webhook integration paths; they do not imply a native connector to a particular vendor.
Verify signatures
Section titled “Verify signatures”Every delivery is HMAC-signed: Vocapable-Signature: t=<unix>,v1=<hex>. Verify with
the snippets in the Webhooks guide - reject skew over 5 minutes,
and accept either v1 entry during a secret rotation’s 24-hour overlap.
Prove the pipe before you need it
Section titled “Prove the pipe before you need it”curl -X POST https://api.vocapable.com/v1/webhook-endpoint/test \ -H "Authorization: Bearer $VOCAPABLE_API_KEY"Sends one signed sample (data.test: true) with production mechanics - same envelope,
same signature, same secrets, same 10-second success rule - and reports
{delivered, status_code}. A receiver that verifies the ping verifies real traffic.
Recognize data.test: true and acknowledge it without creating customer work.
Recover after an outage
Section titled “Recover after an outage”Deliveries retry on a ladder (1m, 5m, 30m, 2h, 6h, then 6-hourly) for 24 hours, then
mark exhausted. If your receiver was down longer than that:
curl https://api.vocapable.com/v1/webhook-deliveries?status=exhausted \ -H "Authorization: Bearer $VOCAPABLE_API_KEY"
curl -X POST https://api.vocapable.com/v1/webhook-deliveries/whd_01J9…/redrive \ -H "Authorization: Bearer $VOCAPABLE_API_KEY"Each redrive grants exactly one more attempt and is available only for an exhausted
delivery. Delivery remains at-least-once, so receivers must dedupe on event.id.
Or poll
Section titled “Or poll”Everything pushed is also pullable: GET /v1/calls/{id}, /transcript,
GET /v1/survey-responses?call_id=…, GET /v1/campaigns/{id}/survey-rollup, and bulk
POST /v1/exports. Webhooks are the fast path, not the only path.