Connect Retell AI to n8n: A Practical Build Guide
A hands-on guide to connecting Retell AI to n8n: the two integration patterns you need, a real appointment-booking flow, latency tips, and production gotchas.

If you want to connect Retell AI to n8n, the mental model that makes everything click is this: Retell owns the voice, n8n owns the brain. I've built a handful of these phone agents now, and the ones that feel magical to callers are never the ones crammed into a single no-code canvas. They're the ones where each tool does the job it's actually good at.
Retell handles the hard real-time stuff: turn-taking, barge-in when the caller interrupts, speech-to-text and text-to-speech, the whole live audio loop. n8n handles your business logic — the CRM lookup, the calendar check, the SMS confirmation. Clean separation of concerns. You get logic you can version, self-host, and reuse across projects instead of rebuilding it inside a proprietary flow.
By the end of this guide you'll have built a working inbound agent that greets a known caller by name, answers questions with live data, and books an appointment on a real calendar.
Why pair Retell AI with n8n?
This combo earns its keep in a few specific situations. You already run n8n and don't want a second automation platform. You need real access to a CRM, calendar, or database that a closed voice platform gates behind a marketplace. Or you simply want orchestration logic you can put in Git and self-host near your data.
A monolithic no-code voice platform is fine until you hit its edges. The moment you need a branching booking flow, a fallback when an API fails, or an integration nobody built a native node for, you're fighting the tool. n8n gives you that escape hatch on day one.
Prerequisites:
- A Retell account with at least one agent configured
- A reachable n8n instance — n8n Cloud or a self-hosted webhook URL that's publicly accessible over HTTPS
- One downstream tool wired up: Google Calendar, HubSpot, or even a Google Sheet to start
The two integration patterns you actually need
Nearly every Retell AI n8n integration reduces to two patterns. Learn both and you can build almost anything.
Pattern A — Custom Function (real-time). Mid-conversation, the agent calls out to n8n, pauses, waits for a response, and speaks the result. This is how you do a live lookup ("let me check the calendar…") or take an action during the call. The agent is literally blocked on your response, so speed matters.
Pattern B — Webhook (fire-and-forget). Retell fires an event to n8n on call_started, call_ended, or call_analyzed. n8n does whatever it needs — log the transcript, update the CRM, ping Slack — and Retell doesn't wait. Nothing is time-critical here.
How to choose: if the agent needs data or an action during the conversation, use a custom function. If you're recording something or triggering follow-up after the fact, use a webhook.
Caller ──audio──> Retell (voice loop)
│
│ Pattern A: custom function (blocking)
├──POST args──> n8n Webhook ──> lookup/action
│ <──JSON response── (agent speaks it)
│
│ Pattern B: call events (async)
└──POST event──> n8n Webhook ──> log / CRM / Slack
Step 1 — Stand up the n8n webhook endpoint
Add a Webhook node, set the method to POST, and — this is the part people get wrong on launch day — copy the Production URL, not the Test URL. The test URL only listens while you have the editor open with "Listen for test event" active. Point Retell at it and your agent goes silent in production because nothing is listening.
The Retell payload arrives as JSON. For a custom function call you'll get the call object, the agent_id, and an args object holding whatever parameters your function defined. For call events you get the full call record including transcript and analysis.
Return the response Retell expects. For a quick reply you can set the Webhook node's "Respond" option to "Immediately" and return a static body, but for a real lookup you want a Respond to Webhook node at the end of your flow so you control the exact JSON after the work is done.
Secure it before you trust anything. Have Retell send a shared secret header, then verify it in an IF node before processing the payload. A public webhook with no auth is an open door — treat it like one. If you want a deeper walkthrough of hardening endpoints, I've written more on the blog.
Step 2 — Wire a Retell Custom Function to n8n
In the Retell agent, define the function: a clear name, a plain-English description, and a tight JSON parameter schema. The schema is what the LLM fills in, so keep it small and unambiguous — { "phone_number": "string" } is far more reliable than a sprawling object with ten optional fields. The model calls the function well when the shape is obvious.
Point the function URL at your n8n Production webhook and map the arguments. Retell will pass them through as args.
Write the description like an instruction, not a label. Something like "Call this to check open appointment slots when the caller asks to book" tells the model when to fire it. Vague descriptions cause two failure modes: the agent never calls the function, or it calls it on every single turn and the conversation drags.
Speed is non-negotiable here. The round trip should stay well under a second — the caller is sitting in silence while you work. That means favoring cached or in-memory lookups over a cold query against a slow database mid-call. If a lookup is genuinely slow, pre-warm it on call_started instead.
Step 3 — Build a real use case: book an appointment
Here's the flow end to end.
Greet the known caller. On the inbound lookup function, take the caller's phone_number, query your CRM or sheet, and return their name. The agent greets them personally: "Hi Sarah, thanks for calling back." Small touch, huge perceived intelligence.
Check availability. When the caller asks to book, the agent calls an availability function. Inside n8n, query Google Calendar or Cal.com for free slots and return two or three options as a short list. Don't dump twenty slots — the agent has to read them aloud.
Confirm and create. The caller picks a slot, the agent calls a booking function, and n8n creates the event. Branch on the result: on success, return a confirmation; on failure (double-booked, API error), return a clear error so the agent can recover — "That slot just filled, want the next one?" — instead of freezing.
Send written proof. After booking, trigger an SMS or email from n8n so the caller has a confirmation they can look at later. People trust a booking they can see.
Step 4 — Capture transcripts and outcomes after the call
Subscribe to the call_ended and call_analyzed webhooks. The latter gives you Retell's post-call analysis — transcript, sentiment, and any structured fields you configured the agent to extract.
Store all of it. Push transcript, sentiment, and structured outcome fields to a database or sheet. Then route on outcome: booked calls go to the CRM, failed or frustrated calls get flagged to a Slack channel so a human can follow up the same day.
Post-call logging is the cheapest quality lever you have. Before you touch a single prompt, read ten real transcripts. You'll learn more from where the agent actually stumbled than from any amount of speculative prompt tuning.
Gotchas, latency, and going to production
A few things that will bite you if you skip them:
| Trap | Fix |
|---|---|
| Silent agent | You used the test webhook URL, or the handler returned nothing. Always return valid JSON. |
| Double bookings | Webhooks retry. Dedupe on call_id so a replayed event doesn't book twice. |
| Slow responses | Co-locate n8n near your Retell region and keep function handlers lean. |
| Surprise bills | Log every function call, watch per-minute spend, and load-test before a real number goes live. |
Idempotency deserves emphasis. Retell can and will retry a webhook, so any action with a side effect — creating an event, sending an SMS — needs a dedupe check keyed on the call. Treat every handler as if it might run twice.
Wrap-up and next steps
Two patterns carry the whole architecture: custom functions for anything real-time, webhooks for anything after the call. Once those feel natural, the extensions are fun — RAG-backed answers so the agent quotes your docs, outbound campaigns, multi-agent routing that hands specialized calls to specialized agents.
Here's my honest take. Managed voice platforms are great right up to the point where you need real integrations and recoverable logic. That's exactly where custom orchestration with n8n starts paying for itself.
If you'd rather have this wired up correctly the first time — endpoints secured, latency budget respected, idempotency handled — get in touch and I'll help you ship it.
FAQ
Do I need to self-host n8n to use it with Retell?
No. n8n Cloud works fine as long as your webhook URL is publicly reachable over HTTPS. Self-hosting mainly helps when you want data residency, lower latency near your region, or to avoid per-execution pricing at scale.
How fast does the n8n response need to be for a Retell custom function?
Aim to stay well under one second. The caller hears silence while the function runs, so favor cached or in-memory lookups over slow live queries. Pre-warm anything heavy on the call_started event.
What's the difference between a Retell custom function and a webhook?
A custom function runs mid-call and blocks the agent until n8n responds — use it for live lookups and actions. A webhook fires on call events and doesn't wait — use it for logging, CRM updates, and post-call follow-ups.
How do I stop the agent from double-booking?
Dedupe on call_id. Webhooks can retry, so wrap any side-effecting action in an idempotency check before it writes to your calendar or sends a message.
USMAN://CTA
Got a build like this in mind?
I ship AI voice agents, automations, and full-stack products. Let's talk about yours.
START A PROJECT