Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.nedzo.ai/llms.txt

Use this file to discover all available pages before exploring further.

Every agent can fire an outbound webhook the moment a conversation ends. Use it to push transcripts, summaries, dispositions, and extracted fields into your own CRM, data warehouse, or notification system. Previously called the “Post-Call Webhook” (voice only). It now fires for all three agent types:
Agent typeWhen it fires
VoiceAfter a phone call ends (inbound or outbound)
ChatAfter an SMS, Instagram, Messenger, email, or web chat conversation is finalized
Web AgentAfter a web agent conversation (voice or chat) ends

Setup

In the dashboard

  1. Open your agent and go to the Settings tab.
  2. Under Post-Conversation Webhook, paste your endpoint URL and save.
  3. Click Test webhook to fire a sample payload so you can verify your server accepts it.

Via API

Set postConversationWebhookUrl when creating or updating an agent:
curl -X PATCH "https://api.nedzo.ai/v1/agents/{agentId}" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"postConversationWebhookUrl": "https://example.com/webhooks/conversation-completed"}'
Set the field to null to disable the webhook.
The legacy field name postCallWebhookUrl is still accepted on create/update for backwards compatibility, but API responses always return postConversationWebhookUrl.

Delivery semantics

  • Fire-and-forget. Nedzo sends the request but does not retry on failure.
  • Timeout. The request is aborted if your server takes longer than 10 seconds to respond.
  • Success. Any 2xx status is logged as delivered. Non-2xx responses and timeouts are logged but do not retry.
  • Order. One webhook per conversation, sent after the conversation has been persisted, summary/extraction has run, and the workflow trigger has been queued.
  • URL validation. Only https:// (or http:// for public hosts in development) is allowed. Internal IPs and metadata endpoints are rejected to prevent SSRF.
  • HIPAA. If the agent has HIPAA compliance enabled, transcript is omitted from the payload and summary is sent as null.

Payload

Nedzo sends a POST request with Content-Type: application/json and a JSON body.
Breaking change (April 2026). The voice and web payload shape changed. If you parsed disposition, outcome, contactId, or agentId from the root of the payload, switch to the nested locations (analysis.disposition, contact.contactId, agent.agentId). The vendor callId field has been removed. A new endedReason field is now sent on the root.Chat payloads are unchanged.

Common fields

Every payload includes these fields, regardless of channel:
FieldTypeDescription
eventstring"conversation.completed" for chat and web. Voice sends "call.completed" for backwards compatibility.
channelstringOne of voice, web, sms, email, whatsapp, instagram, facebook, web_chat.
conversationIdstring (UUID)The Nedzo conversation record ID.
workspaceIdstring (UUID)The workspace the agent belongs to.
startedAtstring (ISO 8601)When the conversation started.
endedAtstring (ISO 8601)When the conversation ended.
agentobject{ agentId, name, phone? }. Use agent.agentId to identify the agent. phone only included for voice.
contactobject | nullContact record, or null when no contact was matched/created. Always a fully populated object when present — never an empty {}. Voice/web include { contactId, firstName, lastName, phone, email, contactBusinessName, tags, customFields }; chat includes { contactId }.
analysis.summarystring | nullAI-generated summary. null if HIPAA is enabled or summary generation failed.
analysis.evaluationboolean | nullSuccess evaluation result if configured.
analysis.dispositionstring | nullAI-classified disposition label when call disposition classification is enabled on the agent.
analysis.dataExtractionobjectMap of configured extraction field names to values.
transcriptstringFull transcript. Omitted entirely when HIPAA compliance is enabled.

Voice-only fields

FieldTypeDescription
directionstring"inbound" or "outbound".
durationSecondsnumberCall duration in seconds.
endedReasonstring | nullRaw reason the call ended (e.g. customer-ended-call, no-answer, voicemail, assistant-forwarded-call). Use this for fine-grained branching.
agent.phonestring | nullThe phone number the agent used.

Chat-only fields

FieldTypeDescription
messageCountnumberNumber of messages exchanged.
lastMessageAtstring (ISO 8601)Timestamp of the final message.
contactIdstring (UUID) | nullContact record, if one was matched/created. Chat payloads also include this convenience field at the root.

Web Agent fields

Web Agent payloads use the voice-style structure — endedReason, durationSeconds on the root — plus channel: "web".

Removed in April 2026

The following root-level fields were removed from voice and web payloads. They remain available under nested objects:
Removed root fieldNew location
dispositionanalysis.disposition
outcomeRemoved (use endedReason for raw reason, analysis.disposition for AI-classified label)
contactIdcontact.contactId
agentIdagent.agentId
callIdRemoved entirely (vendor call ID is no longer exposed)

Example payloads

Voice call

{
  "event": "call.completed",
  "channel": "voice",
  "conversationId": "0a9b8c7d-...",
  "workspaceId": "w1w2w3-...",
  "direction": "outbound",
  "endedReason": "customer-ended-call",
  "durationSeconds": 245,
  "startedAt": "2026-04-23T14:30:00Z",
  "endedAt": "2026-04-23T14:34:05Z",
  "contact": {
    "contactId": "a1b2c3d4-...",
    "firstName": "John",
    "lastName": "Doe",
    "phone": "+14155551234",
    "email": "john@example.com",
    "contactBusinessName": "Acme Co",
    "tags": ["lead", "interested"],
    "customFields": { "budget": "5000" }
  },
  "agent": {
    "agentId": "x1y2z3-...",
    "name": "Sales Agent",
    "phone": "+14155550001"
  },
  "analysis": {
    "evaluation": true,
    "summary": "Customer confirmed interest and booked a demo for Friday at 2pm.",
    "disposition": "Appointment Booked",
    "dataExtraction": { "budget": "5000", "timeline": "Q3 2026" }
  },
  "transcript": "User: Hi...\nAssistant: Hello John..."
}

Chat conversation (SMS / Instagram / email / web chat)

{
  "event": "conversation.completed",
  "channel": "sms",
  "conversationId": "0a9b8c7d-...",
  "workspaceId": "w1w2w3-...",
  "contactId": "a1b2c3d4-...",
  "messageCount": 8,
  "startedAt": "2026-04-23T14:30:00Z",
  "endedAt": "2026-04-23T14:45:00Z",
  "lastMessageAt": "2026-04-23T14:45:00Z",
  "contact": {
    "contactId": "a1b2c3d4-..."
  },
  "agent": {
    "agentId": "x1y2z3-...",
    "name": "Support Agent"
  },
  "analysis": {
    "summary": "Visitor asked about pricing tiers and agreed to a follow-up email.",
    "disposition": "Interested - Demo Scheduled",
    "dataExtraction": { "interest": "pricing" }
  },
  "transcript": "User: How much does this cost?\nAssistant: Our plans start at..."
}

Web Agent conversation

{
  "event": "conversation.completed",
  "channel": "web",
  "conversationId": "0a9b8c7d-...",
  "workspaceId": "w1w2w3-...",
  "endedReason": "customer-ended-call",
  "durationSeconds": 132,
  "startedAt": "2026-04-23T14:30:00Z",
  "endedAt": "2026-04-23T14:32:12Z",
  "contact": {
    "contactId": "a1b2c3d4-...",
    "firstName": "Jane",
    "lastName": "Smith",
    "phone": null,
    "email": "jane@example.com",
    "contactBusinessName": null,
    "tags": [],
    "customFields": {}
  },
  "agent": {
    "agentId": "x1y2z3-...",
    "name": "Website Assistant"
  },
  "analysis": {
    "evaluation": true,
    "summary": "Visitor asked about onboarding and asked for a demo link.",
    "disposition": "Interested - Demo Scheduled",
    "dataExtraction": { "intent": "demo_request" }
  },
  "transcript": "User: Hi, I was looking at your pricing page...\nAssistant: Happy to help..."
}

Security

  • Always use HTTPS. Nedzo blocks requests to non-public IPs and metadata endpoints but you should also refuse plaintext HTTP on your end.
  • Verify the source. Nedzo does not currently sign outbound webhooks. If you need to verify the sender, host your endpoint behind an auth gateway, allowlist Nedzo IP ranges, or include a shared secret in the URL path.
  • Be idempotent. Use conversationId as your idempotency key so duplicate deliveries (e.g. from network retries on your side) don’t create duplicate records.