Softechinfra
Productivity

n8n + Twilio + Claude: A Missed-Call Auto-Callback Flow for B2B Sales (12 Nodes)

A Gurugram B2B sales team was losing 30% of inbound calls after hours. This 12-node n8n flow catches the missed call, qualifies the caller with Claude over SMS, and books a Cal.com slot.

Hrishikesh BaidyaHrishikesh Baidya
July 29, 202514 min read
n8n + Twilio + Claude: A Missed-Call Auto-Callback Flow for B2B Sales (12 Nodes)

A Gurugram B2B sales team missed roughly 30% of inbound calls — after hours, lunch breaks, everyone already on a call. Each missed call was a prospect who often did not call back. We built a 12-node n8n workflow that fires the instant a call goes unanswered: it texts the caller, uses Claude to qualify their reply over SMS, and if they are a fit, sends a Cal.com booking link straight to their phone. The team now recovers most missed calls without a human lifting a finger until the meeting is booked. This post is the full build — Twilio webhook setup, the Claude qualifier prompt, the Cal.com booking node, error handling, and per-call cost in ₹.

~30%
Inbound Calls Were Missed
12
n8n Nodes
<15 sec
Missed Call → SMS Sent

What does this missed-call callback flow do?

When a call goes unanswered, Twilio's status callback fires an n8n webhook. The flow sends an SMS asking what the caller needs, waits for their reply on a second webhook, passes the reply to Claude to classify intent and qualification, and branches: qualified callers get a Cal.com booking link by SMS, unqualified ones get a polite deflection, and any caller can opt to have a human call back. Tested on n8n v1.62 with Twilio and Claude Haiku 4.5, July 2025.

Why automate missed-call callbacks for B2B?

In B2B sales, a missed inbound call is a warm lead that picked up the phone — the highest-intent signal you get. Twilio's voice webhooks let you catch the missed call in real time; Twilio's docs stress that webhook handling must be idempotent because events can be delivered more than once. Pairing that with a Claude qualifier means you respond in seconds, at 11 PM or on a Sunday, when a human SDR is asleep. We have built voice-adjacent flows like this before, including on TalkDrill, our in-house English-speaking app, where we run a Twilio-based voice AI pipeline on the same stack.

Related build: For inbound-call routing rather than missed-call recovery, see Build an n8n Receptionist: Auto-Route Inbound Calls in Under 100 Nodes. This post handles the narrower, higher-value case of the call you already missed.

The 12 nodes, grouped

📞
Nodes 1–3: Catch Miss
Webhook for Twilio's call-status callback, an IF to filter for no-answer or busy status, and a Twilio node to send the opening SMS.
⏳
Nodes 4–6: Await Reply
A second Webhook for the inbound SMS reply, a Set node to capture the message body and caller number, and a dedup check.
🤖
Nodes 7–9: Qualify
An HTTP node to Claude to classify intent and qualification, and a Switch on the returned label (qualified, nurture, human).
📅
Nodes 10–12: Book or Deflect
A Cal.com slots fetch, a Twilio SMS with the booking link or a deflection, and an Error Trigger for failures.

Step 1: Set up the Twilio, Claude, and Cal.com credentials

Twilio uses your Account SID and Auth Token from the Twilio Console, set as an n8n Twilio credential. You buy an Indian phone number and configure two webhooks on it: the voice status callback pointing at n8n's first webhook, and the messaging webhook pointing at the second. Claude uses an Anthropic API key. Cal.com uses an API key from your Cal.com settings, hitting the v2 bookings API.

Idempotency warning: Twilio can deliver the same status callback more than once. If you do not dedup, one missed call sends two or three SMS messages, which looks broken to the prospect and burns your SMS budget. Store a hash of the Twilio CallSid in a database or Sheets node and skip any callback whose CallSid you have already processed in the last hour.

Step 2: The Twilio missed-call webhook and opening SMS

Twilio posts the call status as form-encoded data to your webhook with CallStatus, CallSid, and From. Node 2 filters for the statuses that mean "missed," and node 3 sends the first SMS. The opening-SMS Twilio node:

{
    "parameters": {
      "resource": "sms",
      "operation": "send",
      "from": "={{ $env.TWILIO_NUMBER }}",
      "to": "={{ $json.body.From }}",
      "message": "Hi, this is the team at Acme. Sorry we missed your call. What can we help with? Reply here and we'll sort it out — or reply CALL and a person will ring you back."
    },
    "name": "Send Opening SMS",
    "type": "n8n-nodes-base.twilio",
    "typeVersion": 1
  }

The filter in node 2 checks {{ $json.body.CallStatus }} against no-answer, busy, and failed. Verify by calling your Twilio number and letting it ring out — the opening SMS should arrive within about 15 seconds. Inbound calls to an Indian Twilio number are billed per minute, but a missed call you do not answer costs nothing for the call leg itself.

Step 3: The Claude qualifier node

Node 7 sends the caller's SMS reply to Claude and asks for a single classification label plus a one-line reason. Keeping the output structured is what makes the downstream Switch reliable. The Claude HTTP node body:

{
    "parameters": {
      "method": "POST",
      "url": "https://api.anthropic.com/v1/messages",
      "sendHeaders": true,
      "headerParameters": {
        "parameters": [
          { "name": "x-api-key", "value": "={{ $credentials.anthropicApi.apiKey }}" },
          { "name": "anthropic-version", "value": "2023-06-01" },
          { "name": "Content-Type", "value": "application/json" }
        ]
      },
      "sendBody": true,
      "specifyBody": "json",
      "jsonBody": "={{ JSON.stringify({\n  model: 'claude-haiku-4-5',\n  max_tokens: 150,\n  system: 'You qualify inbound B2B sales texts. Reply ONLY as JSON: {\"label\":\"qualified|nurture|human\",\"reason\":\"...\"}. qualified = a real buying need at a company; nurture = vague or student/job-seeker; human = explicitly asks for a callback or is upset.',\n  messages: [ { role: 'user', content: $json.sms_body } ]\n}) }}"
    },
    "name": "Claude Qualify",
    "type": "n8n-nodes-base.httpRequest",
    "typeVersion": 4.2
  }

Verify by sending test replies: "I need a quote for 200 seats" should return qualified, while "do you have jobs" should return nurture. Parse the JSON out of Claude's response in a small Code node before the Switch — Claude returns the JSON inside a content block, not at the top level.

Step 4: Book a Cal.com slot or deflect

For qualified callers, node 10 fetches the next available Cal.com slots and node 11 texts the booking link. Cal.com's v2 booking flow needs an eventTypeId, a start time, and the attendee details. The SMS for a qualified caller:

{
    "parameters": {
      "resource": "sms",
      "operation": "send",
      "from": "={{ $env.TWILIO_NUMBER }}",
      "to": "={{ $json.caller }}",
      "message": "=Great — sounds like a fit. Grab a 20-min slot with our team here: {{ $json.cal_booking_url }} . Reply CALL if you'd rather we ring you."
    },
    "name": "Send Booking SMS",
    "type": "n8n-nodes-base.twilio",
    "typeVersion": 1
  }

  • Twilio number bought and both webhooks configured
  • Status filter set to no-answer, busy, failed
  • CallSid dedup to prevent duplicate SMS
  • Claude returns a strict JSON label, parsed before the Switch
  • Cal.com event type ID and API key in place
  • CALL keyword routes to a human-callback branch
  • DLT registration done for Indian SMS sender IDs

How do you handle errors and edge cases?

Four things break this flow. First, duplicate Twilio callbacks — the CallSid dedup from Step 1 is mandatory, not optional. Second, Claude returning malformed JSON — wrap the parse in a try/catch Code node that defaults to the human branch on any parse failure, so an unclear case always reaches a person. Third, a caller who never replies to the opening SMS — that is fine, the flow simply ends, but log it so you can see the reply rate. Fourth, Indian SMS regulation: India requires DLT (Distributed Ledger Technology) registration of sender IDs and templates, so your Twilio messaging must use a registered template or it will be blocked by Indian carriers.

India SMS gotcha: Transactional SMS to Indian numbers must go through DLT-registered templates, and Twilio supports this but you must register your content templates with your operator first. An unregistered message silently fails on Jio and Airtel. Budget two to three days for DLT approval before go-live — it is the single most common launch delay on Indian SMS projects.

How much does this cost per recovered call?

The per-call cost is two SMS messages plus one small Claude call. Indian transactional SMS is priced per message depending on your route, Claude Haiku 4.5 costs very little for a 150-token classification, and the missed-call leg itself is free. Here is the per-call cost breakdown:

Cost per recovered call — July 2025 2 SMS (DLT transactional) Claude Haiku qualify Missed-call leg — free

At this cost per recovered call, the math is lopsided: a single recovered B2B deal pays for years of the workflow. SMS is the dominant cost, so a chattier flow with five back-and-forth messages costs more — keep the conversation to two or three turns. Our AI and automation team tunes the turn count per client.

When should you not build this?

If your call volume is tiny — say under five inbound calls a day — a human callback is cheaper and warmer than building this. If your buyers strongly prefer voice and find SMS impersonal (common in some traditional industries), the text-first approach can backfire; offer the CALL keyword prominently. And if you have not finished DLT registration, do not launch — unregistered SMS to Indian numbers fails silently, which is worse than no automation because you will not know leads are dropping.

Real example: the Gurugram B2B team

The client sold a SaaS product into mid-market companies and ran a 4-person inside-sales team that could not cover evenings and weekends. Before the flow, after-hours calls just rang out. After we shipped it, a meaningful share of those previously-dead calls now book a Cal.com slot before anyone arrives at the office the next morning. The Claude qualifier also filters out the job-seekers and students who used to waste SDR time. We saw the same speed-of-response lift building the lead pipeline for Radiant Finance, where every minute of delay cost conversions.

The calls we missed at 9 PM were the ones we cared about most, and they almost never called back. Recovering them with a text and a booking link, before anyone is even awake, changed the math on our after-hours coverage.

— Hrishikesh, CTO at Softechinfra

Frequently asked questions

Do I need DLT registration to send SMS in India?

Yes, for transactional SMS to Indian numbers. India mandates DLT registration of sender IDs and message templates. Twilio supports this, but you must register your content templates with your operator first or messages fail silently on Jio and Airtel. Budget two to three days for approval.

What if Claude returns malformed JSON?

Wrap the JSON parse in a try/catch Code node that defaults to the human-callback branch on any failure. That way an unclear or unparseable case always reaches a real person rather than getting silently dropped.

How do I stop duplicate SMS from duplicate webhooks?

Store a hash of the Twilio CallSid in a database or Sheets node and skip any callback whose CallSid you processed in the last hour. Twilio can deliver the same status callback multiple times, so this dedup is mandatory.

Can the caller reach a human instead of the bot?

Yes. The opening SMS offers a CALL keyword. Any reply containing CALL routes to a human-callback branch that notifies an SDR in Slack with the caller's number, bypassing the Claude qualifier entirely.

How much does each recovered call cost?

About four rupees: two transactional SMS messages plus one small Claude Haiku classification. The missed-call leg itself is free since you never answered it. SMS is the dominant cost, so keep the conversation to two or three turns.

How long does it take to build?

A working v1 takes 5 to 7 working days of wiring, plus two to three days of DLT registration that runs in parallel. We never launch Indian SMS flows before DLT approval lands.

Want this missed-call callback flow live on your Twilio number?

We ship a self-hosted n8n missed-call recovery workflow for B2B sales teams in 7 working days, with DLT registration handled. Suitable if you miss after-hours inbound calls and lose the lead. No slides — bring your call data and we will model the recovery.

Book a 20-min Call

Tags:
n8nTwilioClaudeCal.comB2B salesvoice automationSMSno-code
Share this post:
Hrishikesh Baidya

Hrishikesh Baidya

CTO at Softechinfra specializing in Python, system architecture, and building secure, scalable software solutions.