Back to blog
Tutorial

Automated customer service with Claude API + n8n (for clinics that don't sleep)

By Flávio Emanuel · · 9 min read

Dental clinics get messages constantly. Someone wants info about treatment. Someone wants to book. Someone sends “what’s the price?”. Half arrive after the clinic closes.

I solved this for a clinic in São Paulo. A bot running 24/7 that qualifies leads, collects info, and hands off to a human when needed. Result: 60% of leads arrive already categorized. The support team saves 3 hours a day answering repetitive questions.

I’ll show you how to build it.

What you’re going to build

An n8n workflow that:

  1. Receives WhatsApp messages
  2. Passes them to Claude for analysis
  3. Claude responds or qualifies as “needs human”
  4. If qualified, passes to support queue

Cost per conversation: $0.003 (May 2026). If you process 1000 conversations per month, that’s $3. The team’s time savings? About $12 per day.

Initial setup

You’ll need:

  1. Claude API account (with balance)
  2. n8n running (self-hosted or n8n.cloud)
  3. WhatsApp Business account or Twilio WhatsApp
  4. A database (can be Supabase, Firebase, or PostgreSQL)

I’m assuming you already have n8n running. If not, quick setup: docker run -it -p 5678:5678 n8nio/n8n.

The prompt that works for a clinic

This is the heart of the system. Everything depends on a well-crafted prompt:

You are a dental clinic support assistant. 
Your job is: receive messages from possible patients and qualify them.

CLINIC CONTEXT:
- Location: São Paulo, south zone
- Specialties: cosmetic, implants, cleaning
- Hours: Mon-Fri, 8am-6pm
- WhatsApp booking link: [calendar link]

YOUR MISSION:
1. Answer simple questions (hours, location, procedures)
2. Collect info: name, procedure type, phone
3. When someone wants to book, give them the calendar link
4. If conversation gets complex, hand off to human

WHEN TO HAND OFF TO HUMAN:
- Patient is in pain/emergency
- Needs detailed diagnosis
- Wants to negotiate price
- Is unhappy
- Asks health questions you're unsure about

RULES:
- Always be friendly, never robotic
- If you don't know, say honestly
- Don't invent procedure info
- If patient says "pain", mark as EMERGENCY

ALWAYS RESPOND IN PORTUGUESE.

End each response with a meta:
[META: interaction_type] where type can be: INFORMATION, BOOKING, QUALIFIED, EMERGENCY

Each meta defines what happens with the conversation.

n8n workflow step by step

Start with a blank workflow in n8n.

Step 1: WhatsApp Trigger

Add a “Webhook” node configured to receive POST from your WhatsApp provider.

{
  "from": "5511987654321",
  "body": "What's the price of cleaning?"
}

Step 2: Code to extract data

Create a Function node that processes the message:

const message = $input.all()[0].body.body;
const phone = $input.all()[0].body.from;

return {
  message,
  phone,
  timestamp: new Date().toISOString(),
};

Step 3: Call Claude API

Add an HTTP Request node configured like this:

Method: POST
URL: https://api.anthropic.com/v1/messages
Authorization Header: Bearer {your_api_key}

Body (JSON):
{
  "model": "claude-3-5-sonnet-20241022",
  "max_tokens": 300,
  "messages": [
    {
      "role": "user",
      "content": "{{$node.ProcessMessage.json.message}}"
    }
  ],
  "system": "[your prompt from above]"
}

Claude responds. The node returns something like:

{
  "content": [
    {
      "type": "text",
      "text": "Hi! Cleaning costs R$200 and takes 30 minutes. Want to book? [link]"
    }
  ]
}

Step 4: Extract the meta

Use regex to pull that [META: ...]:

const response = $input.all()[0].json.content[0].text;
const metaMatch = response.match(/\[META: (\w+)\]/);
const meta = metaMatch ? metaMatch[1] : "UNKNOWN";

return { meta, response };

Step 5: Switch based on meta

Use a Switch node:

  • If meta === "EMERGENCY": go to “Human Handoff - Urgent”
  • If meta === "QUALIFIED": go to “Qualified - Create Lead”
  • If meta === "BOOKING": go to “Sent Link”
  • If meta === "INFORMATION": respond and continue

Step 6: Respond on WhatsApp

HTTP Request node to send back:

Method: POST
URL: [your WhatsApp webhook]

Body:
{
  "to": "{{$node.ProcessMessage.json.phone}}",
  "body": "{{$node.ExtractMeta.json.response}}"
}

Step 7: Save to Supabase

Before responding, save everything:

Method: POST
URL: https://your-supabase.supabase.co/rest/v1/messages

Body:
{
  "phone": "{{$node.ProcessMessage.json.phone}}",
  "incoming_message": "{{$node.ProcessMessage.json.message}}",
  "response": "{{$node.ExtractMeta.json.response}}",
  "meta": "{{$node.ExtractMeta.json.meta}}",
  "timestamp": "{{$node.ProcessMessage.json.timestamp}}"
}

Step 8: Notify team if handoff

If meta === "EMERGENCY" or meta === "QUALIFIED", send to Slack/email:

[NEW LEAD - CLINIC]
Name: {{extracted from history}}
Type: {{meta}}
Message: {{original message}}
Reply at: https://clinic.com/dashboard/leads/{{id}}

Real cost per conversation

In May 2026, Claude 3.5 Sonnet pricing:

  • Input: $3 per 1 million tokens
  • Output: $15 per 1 million tokens

A typical 5-exchange conversation (5 user messages + 5 bot replies):

  • Input: ~400 tokens per conversation (prompt + message)
  • Output: ~150 tokens per reply = 750 total

Math:

  • (400 input tokens / 1M) * $3 = $0.0012
  • (750 output tokens / 1M) * $15 = $0.01125
  • Total: ~$0.0124 per conversation

So about $0.012 per conversation.

If 1000 conversations per month: ~$12. Team’s time saved? About 30 hours. Support hourly cost: $20/hour = $600 saved. ROI: 50x.

How to avoid hallucination

The biggest risk is Claude inventing info about procedures the clinic doesn’t offer. Three techniques:

1. Restrictive context system

You KNOW ONLY:
- Cleaning: R$200
- Whitening: R$500
- Implant: consultation needed

Any question about other procedure: "We don't offer that service. 
Want to know what we do? [link]"

2. Response validation

Before sending, use another Claude call to validate:

Generated response: "Implant costs R$3000"
Validate: is this in our procedures database? YES/NO

If NO: reject and replace with "We don't have that info available"

3. Human in the loop for critical info

If meta is “EMERGENCY” or “CUSTOM_PROCEDURE”, always hand off to human. Don’t take the risk.

Metrics that matter

After the system runs for a week, analyze:

Qualification rate: % of conversations that came out “qualified” (name + phone + procedure type) = your bot’s success rate.

At the clinic I set up: 62% qualification. That means 62% of conversations that went in came out with info the team could use.

Escalation rate: % of messages that went to human. Should be between 10-25%. Above 40% means your prompt is escalating too much. Below 5% might mean stuff is slipping through.

Average response time: how fast does your bot respond? Should be seconds. If minutes, something’s slow.

Completion rate: how many conversations got enough info for follow-up? Could the clinic actually book based on what the bot collected?

Extra integrations to consider

  1. Google Calendar: bot collects desired date/time, checks availability, books directly
  2. Stripe: customer wants to pay now? Bot generates invoice, charges via link
  3. Slack: bot sends real-time notifications to team, don’t wait for dashboard checks
  4. Custom CRM: each qualified conversation becomes a new contact in your CRM

Prompt tuning: iteration is key

The first prompt will be okay. Not great. Run for a week, see real conversations that failed, adjust.

Examples of tweaks:

  • Week 1: bot escalating too much. You make the prompt more assertive.
  • Week 2: bot can’t handle price questions well. You structure pricing section better.
  • Week 3: patients want to book but link doesn’t arrive right. You simplify the call-to-action.

Each iteration improves.

Real operational costs

  • Claude API: $12-30/month (depending on volume)
  • n8n.cloud: $0 (free) or $4/month (pro)
  • WhatsApp Business: $0.07 per message (sent by you)
  • Supabase: $0 (free) or $5/month

Total per month: $12-40.

Team’s time savings: $600+.

Checklist: clinic chatbot deployment

  • Prompt is clinic-specific (not generic)?
  • Three meta types defined (INFORMATION, QUALIFIED, EMERGENCY)?
  • Each response includes meta at end (for routing)?
  • Supabase/database ready to save conversations?
  • WhatsApp webhook tested (can receive messages)?
  • Claude API node authenticated and calling correctly?
  • Switch logic routing correctly to different metas?
  • Support team knows where to find new leads?
  • Hallucination validation in place (for procedures)?
  • You tested with 10-20 real messages before going live?

Security checklist for API integrations

When connecting Claude API to customer service tools, security matters:

  • Never log customer messages (they’re private)
  • Never store API responses in plain text
  • Rate limit customer requests (prevent abuse)
  • Validate input before sending to Claude (prevents injection attacks)
  • Use environment variables for API keys, never hardcode
  • Monitor unusual patterns (detect compromised keys)

A breached API key costs you money and customer trust. Spend 1 hour setting up security properly at the start. Saves you 100 hours of debugging later.

Measuring success

How do you know if Claude API + N8N customer service system is working?

Metrics to track: average response time, customer satisfaction (add a quick feedback button), percentage of issues resolved without human intervention.

If a customer submits a request at 3pm and Claude answers at 3:02pm with 85% accuracy, that’s working. If humans are needed 30% of the time, that’s also working (most systems need human escalation).

Red flag: if humans are needed 80% of the time. That means your system isn’t helping.

Track these metrics monthly and adjust the system.

Read also: n8n automations and webhooks | WhatsApp Business API for dental clinics | Pricing AI automation

Next step

Need a dev who truly delivers?

Whether it's a one-time project, team reinforcement, or a long-term partnership. Let's talk.

Chat on WhatsApp

I reply within 2 hours during business hours.