NNabeel Hassan

Blog · July 9, 2026 · 8 min read

How to Connect Retell AI to n8n: The Webhook Architecture I Ship

By Nabeel Hassan — Founder, Null Studio · ICPC World Finalist

TL;DR: Connect Retell AI to n8n with two webhooks pointing in opposite directions. Retell fires inbound webhooks to n8n on call events (started, ended, analyzed) and on mid-call custom functions; n8n calls back out to Retell's REST API to place outbound calls or update agents. Keep every piece of business logic — booking, CRM writes, SMS — in n8n, not in the voice prompt. That's the pattern I use in production, and here's exactly how to wire it.

I build AI voice agents for US clients, and the question I get most from other developers is "how does the voice platform actually do anything?" The agent answers the phone, but who checks the calendar, writes the CRM contact, sends the confirmation text? The answer, in my stack, is always n8n. Retell handles the conversation; n8n handles everything the conversation triggers. This guide is the exact integration I ship, including the parts that break in production.

Why n8n sits behind the voice agent

A voice platform like Retell is very good at one thing: turning a phone call into a structured conversation. It is not where your booking logic, your CRM, or your SMS should live. I explained the full reasoning in how I build production AI voice agents with Retell, but the short version is this: if you bake business logic into the voice prompt, you have married the platform. Keep that logic in n8n and the voice layer becomes swappable. Switching or A/B-testing platforms later is a change to one webhook, not a rebuild.

So the mental model is two arrows:

Get those two directions right and everything else is detail. I standardized on n8n as that glue layer for reasons I laid out in n8n vs Make vs Zapier.

Direction 1: Retell to n8n (the inbound webhook)

This is where most of the work happens. Retell can call your webhook on lifecycle events and on custom functions you define inside the agent.

Set up the n8n side first

  1. In n8n, add a Webhook node. Set the method to POST and copy the production URL it generates. If you are self-hosting, make sure the URL is publicly reachable — Retell's servers have to hit it, so localhost will not work. For local development I tunnel with a service like ngrok and swap the URL for the real one before going live.
  2. Add a Respond to Webhook node so Retell gets a clean 200 back. For mid-call functions this response is the answer the agent speaks, so it matters.

Point Retell at it

In the Retell dashboard, open your agent and set the webhook URL to the n8n production URL. Retell will now POST a JSON body on each event. The payload includes an event field — call_started, call_ended, call_analyzed — and the full call object with the transcript, metadata, and any dynamic variables you passed in.

A useful habit: add a Switch node right after the webhook that branches on {{ $json.event }}. Each event wants different handling. call_ended is usually where I write the contact and transcript to the CRM; call_analyzed is where I read Retell's post-call analysis (sentiment, whether a booking happened, custom extraction fields) and route accordingly.

The mid-call custom function

This is the powerful part. Inside the Retell agent you can define a custom function — for example check_availability or book_appointment. When the caller asks for a Tuesday slot, the agent calls that function, which hits your n8n webhook mid-conversation, waits for the response, and speaks the result back.

The flow for a booking function looks like this:

Caller: "Do you have anything Tuesday afternoon?"
  → Retell fires custom function `check_availability` → n8n webhook
  → n8n queries Google Calendar / GHL calendar
  → n8n responds { "slots": ["2pm", "3:30pm"] }
  → Agent: "I have 2pm or 3:30 on Tuesday — which works?"

The critical constraint here is latency. The caller is sitting in silence while n8n runs. Keep mid-call function workflows lean: one lookup, a fast response, no chained API calls that take four seconds. If a step is genuinely slow, have the agent say "give me one moment" and design for it. I keep anything non-blocking — sending the confirmation SMS, writing the CRM note — out of the mid-call path and move it to the call_ended branch instead.

Direction 2: n8n to Retell (the outbound call)

The reverse direction uses Retell's REST API. The most common use is placing an outbound call — the backbone of the missed-call callback system I build, which I documented fully in missed-call textback with GoHighLevel + Retell.

In n8n, use an HTTP Request node:

  1. Method POST to Retell's create-phone-call endpoint.
  2. Authorization header with your Retell API key. Store it in n8n credentials, never inline in the node — this is the mistake I see most often in shared workflows.
  3. Body: the from_number (your registered Twilio number), the to_number (the lead), the agent_id, and a retell_llm_dynamic_variables object carrying anything the agent should know before it dials — the caller's name, what they enquired about, the business name.

Those dynamic variables are how you personalize the call without editing the agent. The agent prompt references {{customer_name}}; n8n fills it at call time. One agent, infinitely reusable across contacts.

The full loop, end to end

Here is how the two directions combine in a real missed-call callback:

Missed call in GHL → GHL webhook → n8n
  → n8n HTTP Request → Retell create-phone-call (with lead's name + context)
  → Retell dials the lead, agent talks
  → mid-call: agent calls `book_appointment` → n8n webhook → GHL calendar → responds
  → call_ended → Retell webhook → n8n
  → n8n writes transcript + outcome to the GHL contact, sends SMS confirmation

Every arrow in that diagram is one of the two webhook directions above. Nothing exotic, just discipline about where each piece of logic lives.

Production gotchas I have hit

Where to go from here

Once the two directions are solid, everything else is composition: swap the CRM node, add a Slack alert when a caller is angry, branch on the post-call analysis to tag hot leads. The voice agent stays simple and the intelligence lives in n8n where you can see it, test it, and change it without touching the prompt.

If you want the wider picture — platform choice, the testing pipeline, what an agent like this costs to run — I have written those up in Retell vs Vapi vs Bland and how much an AI receptionist costs in 2026.


I build production AI voice agents and the n8n automation systems behind them for US clients through Null Studio. If you want yours wired up properly — webhooks, compliance, and all — book a call.

FAQ

How do you connect Retell AI to n8n?

With two webhooks pointing in opposite directions. Retell fires inbound webhooks to an n8n Webhook node on call events (started, ended, analyzed) and on mid-call custom functions; n8n calls back out to Retell's REST API via an HTTP Request node to place outbound calls or update agents. Keep all business logic — booking, CRM writes, SMS — in n8n rather than the voice prompt.

Can Retell AI call an n8n webhook during a live call?

Yes. You define a custom function in the Retell agent (for example check_availability) that hits your n8n webhook mid-conversation, waits for the response, and speaks the result back to the caller. Keep those mid-call workflows lean — the caller is in silence while n8n runs, so latency matters. Move anything non-blocking, like sending SMS, to the call_ended branch instead.

Why keep business logic in n8n instead of the Retell prompt?

Because it keeps the voice platform swappable. If booking, CRM writes and SMS live in n8n rather than baked into Retell, switching or A/B-testing voice platforms later is a change to one webhook, not a rebuild. It also means you can test and change the logic without touching the agent prompt.

Building something in this space?

I take on AI-agent, automation and product work through Null Studio — scoped fast, shipped fast.

Book a discovery call →

Keep reading