Skip to main content

Webhooks & Delivery

After every call Hanc.AI can send the call — summary, transcript, extracted fields — to your own system: a ticket system, a CRM, an ERP or any HTTPS endpoint. This page describes exactly how that delivery behaves: what happens when your server is down, how often we retry, what your firewall must allow and what the request looks like.

All Plans

Post-call delivery with retries and the delivery log is available on every plan, including Free.

What is sent, and when​

A request goes out once the call has ended and its analysis is finished (summary, sentiment, your extracted fields) — typically a few seconds after hang-up.

SourceWhere you set it up
API Call actionAgent → Actions → Post call → API Call
Workflow stepWorkflow builder → API call tool step with When it runs: After the call
Agent webhookThe webhook_url field of the agent (API reference)

Requests an agent makes during a conversation (live tools) are not covered here: they are needed in that very second and are never repeated later.

When your server is unavailable​

Nothing is lost. The request is stored in a delivery queue before the first attempt, and it stays there until your server accepts it or the schedule runs out.

  • A delivery counts as successful when your endpoint answers with any 2xx status within 30 seconds.
  • Everything else is retried: connection refused, DNS or TLS errors, a timeout, and any other status — 5xx, 429, and 4xx as well. If an API key expired and you renew it, the pending calls arrive on their own.
  • Every attempt sends the same request with the same delivery ID.

Retry schedule​

AttemptPause before itTime since the call ended
1— (immediately)~0
21 minute~1 min
35 minutes~6 min
430 minutes~36 min
52 hours~2 h 36 min
66 hours~8 h 36 min
724 hours~1 day 8 h
848 hours~3 days 8 h

That is 8 attempts over about 3.4 days — enough to cover a weekend outage.

Your own schedule​

In an API Call action (and in a workflow API call step that runs after the call) you can replace the schedule under Retries on failure:

  • up to 10 retries,
  • each pause from 1 minute to 7 days,
  • remove all rows to send once, with no retries.

An action you never touched follows the default schedule above.

After the last attempt​

The delivery is marked Not delivered, you are notified by email unless you switched that off, and the request is kept for 30 days. During that time you can send it again — one click in the delivery log or one API call. Sending again is also possible for a delivery that already succeeded, for example after a restore on your side.

Independently of any webhook, the call itself stays in your Hanc.AI account — transcript, summary, recording and extracted fields are available in Calls and through the API. A long outage delays the hand-over to your system; it does not delete the conversation.

At-least-once

Delivery is at least once. In rare cases — for example when your server processed a request but the answer did not reach us in time — the same call arrives twice. Use X-Hanc-Delivery-Id to recognise and skip a repeat.

Failure notifications​

You do not have to watch the log: an action can tell you by email when its request is not delivered. Choose under Failure notification in the action (or in the workflow step):

SettingWhen the email is sent
After the last attempt (default)Once, when the retry schedule is used up and the request is marked Not delivered
After every failed attemptAfter each failed attempt, with the time of the next one — and after the last
Do not notifyNever; failures are visible in the log only

The email names the action and the agent, your server's host, what it answered (for example HTTP 503 or timeout after 30s), which attempt of how many it was, and links to the delivery log. The final one also says until when the request is kept and that it can be sent again.

Send to sets the recipient — typically whoever operates the receiving system. Left empty, the email goes to the account owner. It is written in the account's language.

To keep an outage from flooding your inbox, notifications are limited per action to 10 an hour and 30 a day; the last one before a pause says until when it lasts. Every failure is still recorded in the log. A request you send again by hand is not notified about.

Delivery log​

Every attempt is recorded: time, HTTP status or network error, duration and the beginning of your server's answer.

In the app: CRM → Communications → open an API call entry. You see the status (Delivered, Retrying, Not delivered), all attempts, the time of the next one and the Send again button.

Through the API (authenticate with your API key in x-api-key):

RequestResult
GET /v1/webhook-deliveriesYour deliveries, newest first. Filters: status (pending, delivered, failed), agent_id, call_id, limit, offset
GET /v1/webhook-deliveries/{id}One delivery with all attempts and the request body
POST /v1/webhook-deliveries/{id}/resendSends it again now and returns the outcome
{
"id": "6ac71fb82e4f72e709a4a566",
"delivery_id": "0b0f2f0e-6c0f-4f0b-9c55-3c6a3a1f8a11",
"kind": "api_call",
"name": "Create ticket",
"call_id": "6ac71f9d2e4f72e709a4a4f0",
"status": "pending",
"attempts_made": 2,
"attempts_max": 8,
"next_attempt_at": "2026-10-09T11:36:04.000Z",
"attempts": [
{ "n": 1, "at": "2026-10-09T11:30:03.512Z", "duration_ms": 212, "error": "connection refused" },
{ "n": 2, "at": "2026-10-09T11:31:04.007Z", "duration_ms": 187, "status_code": 503, "error": "HTTP 503", "response_preview": "Service Unavailable" }
]
}

Header values of the stored request (your keys) are never returned.

Network & firewall​

Hanc.AI calls your endpoint — the connection is always opened from our side to yours.

DirectionOutbound from Hanc.AI → inbound on your side
Source IP addresses178.104.10.47 (delivery service) and 128.140.65.92 (call service, used as a fallback)
ProtocolHTTPS (TLS 1.2 or newer). Plain HTTP works but is not recommended
Port443, or whichever port your URL names
IP versionIPv4
CertificateMust be valid and issued by a public authority; self-signed certificates are rejected
Response timeAnswer within 30 seconds — ideally acknowledge immediately and process in the background
RedirectsFollowed, up to 5

Allow-listing: if your firewall or WAF filters by source address, allow the two addresses above for your webhook path. We announce a change of these addresses in advance.

Not possible: addresses inside a private network (10.x, 172.16–31.x, 192.168.x, localhost). The endpoint must be reachable from the internet — directly or through your reverse proxy / API gateway.

Browser: webhooks run server-to-server. No browser settings, extensions or open ports on employee workstations are involved.

Request format​

POST, PUT and PATCH carry a JSON body (Content-Type: application/json, UTF-8).

{
"call_from": "+431234567890",
"call_to": "+439876543210",
"direction": "inbound",
"call_type": "phone",
"call_status": "ended",
"start_timestamp": 1730000000000,
"end_timestamp": 1730000187000,
"duration": 187000,
"call_summary": "Customer reports a broken router and asks for a callback…",
"transcription": [
{ "speaker": "agent", "content": "Hello…", "timestamp": 1730000001000 },
{ "speaker": "user", "content": "Hi…", "timestamp": 1730000003000 }
],
"task_achieved": true,
"sentiment": { "sentiment": "neutral", "explanation": "…" },
"custom_analysis_data": {
"customer_number": "K-20417",
"ticket_category": "Hardware",
"priority": "high"
},
"collected_data": { },
"transfer_history": [ ],
"recording_url": "https://…",
"disconnection_reason": "user_hangup"
}
FieldContent
call_summarySummary of the conversation
transcriptionFull conversation, turn by turn, with timestamps
call_from, call_to, directionCaller, called number, inbound or outbound
start_timestamp, end_timestamp, durationUnix time and duration in milliseconds
custom_analysis_dataYour own fields, extracted from the conversation — see Retrieval Variables
collected_dataData the agent collected during the call
sentiment, task_achievedMood of the conversation and whether its goal was reached
recording_urlLink to the recording, if recording is on
transfer_historyTransfers that happened during the call

For GET and DELETE the same fields travel in the query string; nested values such as transcription are left out.

Headers​

HeaderMeaning
X-Hanc-Delivery-IdIdentifies the delivery. Identical on every attempt — use it to skip duplicates
X-Hanc-AttemptNumber of the attempt, starting at 1
X-Correlation-IdInternal trace ID; quote it when you contact support
User-AgentHANC-Webhooks/1.0
your headersEverything you configured in the action

Authentication​

You decide how your endpoint recognises us:

  • API key or token — add a header to the action, e.g. Authorization: Bearer <token> or X-API-Key: <key>. Headers are sent with every attempt.
  • Basic auth — Authorization: Basic <base64(user:password)>.
  • Query parameter — for systems that expect the key in the URL.
  • Source address — allow only the IP addresses listed above.

The methods can be combined; a key plus an IP allow-list is the usual setup.

Shaping the request for your system​

By default the request carries the whole call (see Request format). For a system that expects its own structure — most ticket systems do — you describe that structure yourself and fill it from the call.

Variables​

In a post-call API Call action and in a workflow API call step, the URL, headers, query parameters and body take variables in double braces. They are filled in from the call just before the request leaves.

VariableValue
{{call_id}}ID of the call
{{call_from}}, {{call_to}}Caller and called number
{{customer_phone}}, {{customer_email}}The other party's number and e-mail, whichever the direction of the call
{{call_direction}}, {{call_type}}inbound / outbound, phone / web
{{call_start}}, {{call_end}}Start and end, ISO 8601 (UTC)
{{call_duration}}Duration in seconds
{{call_summary}}Summary of the conversation
{{call_transcription}}Full conversation as text
{{call_sentiment}}, {{call_task_achieved}}Mood and whether the goal was reached
{{call_recording_url}}Link to the recording
{{agent_id}}ID of the agent
your fieldsEvery Retrieval Variable by its name, e.g. {{customer_number}}, {{priority}} — and every variable a workflow collected during the call

Rules worth knowing:

  • A body field that consists of one variable only keeps that variable's type: "priority": "{{priority}}" is sent as the number 3, "urgent": "{{urgent}}" as true. Text around a variable makes it text.
  • A value placed in the URL is percent-encoded automatically (+43… becomes %2B43…).
  • A variable the call has no value for is sent empty — never as the literal {{name}}.

In the app, the {x} button in a field lists the available variables; in the body, typing {{ suggests them.

Body​

Under Body (JSON) in the action you write the JSON object your system expects, nested as deeply as needed:

{
"ticket": {
"subject": "Call from {{customer_phone}}: {{ticket_category}}",
"comment": { "body": "{{call_summary}}" },
"priority": "{{priority}}",
"custom_fields": [
{ "id": 360001, "value": "{{customer_number}}" },
{ "id": 360002, "value": "{{call_recording_url}}" }
],
"tags": ["phone-agent"]
}
}

Only your fields​

With Send only my fields switched on, the request carries just your body and your query parameters — the call payload is not added. Leave it off and your fields are sent together with the full call.

Selective sending​

A condition in plain language (“only if the caller reports a fault”) decides which calls trigger the request. Several actions can point to different systems or endpoints.

Connecting a ticket system​

Any ticket system with an HTTP API or an incoming webhook can receive calls — directly, without a piece of software in between. What is needed on your side:

  1. An endpoint reachable from the internet over HTTPS that accepts JSON.
  2. A credential for it (API key, token or basic auth), entered as a header in the action.
  3. If you filter by address — the two IP addresses above on your allow-list.

Then, in the action:

  1. Define your fields. Add Retrieval Variables such as customer number, ticket category, priority, callback requested. The agent fills them from the conversation.
  2. Write the body in the structure of your ticket API and place the variables where they belong.
  3. Switch on Send only my fields.
  4. Press Test API Configuration, then make a test call.

We are happy to prepare the body for your system together with you.

Testing​

Connection test. The Test API Configuration button in the action sends a sample request right away and shows whether your endpoint was reached.

Retry test — to see the mechanism with your own eyes:

  1. In the action, set a short schedule under Retries on failure, for example three pauses of 1 minute.
  2. Stop your endpoint or block our addresses in the firewall.
  3. Make a test call to the agent.
  4. Open CRM → Communications: the entry shows Retrying, the failed attempt with its error and the time of the next one.
  5. Start the endpoint again (or lift the block). The next attempt delivers the call and the entry turns to Delivered — or press Send again to deliver immediately.

Checklist for your endpoint​

  • Answer 2xx as soon as the request is stored; do the heavy work afterwards.
  • Treat X-Hanc-Delivery-Id as an idempotency key.
  • Answer 4xx/5xx when you could not take the request — we will come back.
  • Keep the certificate valid and the two source addresses allowed.