A field-sales team of 22 reps at a building-materials distributor in Nagpur logged every order into a shared Google Sheet. The sheet had 4,000 rows by August and nobody read it. The regional manager wanted one thing: a short WhatsApp message every Sunday evening with the week's numbers, per rep, in language his team actually reads. We built it in n8n: a cron pulls the sheet, Claude turns rows into a tight summary, and the WhatsApp Cloud API broadcasts it at 7pm Sunday. Here's the build, node JSON, credentials, error handling, and the ₹ cost.
The Answer in 60 Words
A Schedule Trigger fires Sunday 7pm IST. n8n reads the week's rows from Google Sheets, aggregates per rep in a Code node, and sends the table to Claude with a prompt that returns a WhatsApp-ready summary in mixed Hindi-English. A loop sends that text to each rep and the manager via the WhatsApp Cloud API using an approved template.
Why This Matters Now (August 2025)
WhatsApp's pricing model flipped on July 1, 2025 — from conversation-based to per-message pricing. India is one of the cheapest markets; a utility template runs a fraction of a rupee. Better still, utility templates sent inside the 24-hour customer-service window are now free. For a once-a-week internal rollup to 23 people, the WhatsApp bill is rounding-error small. That pricing change is what made a "just WhatsApp it to everyone" approach finally make sense for an internal report.
This is the EOD-rollup pattern we keep reaching for. It's a cousin of our FMCG field-sales EOD rollup and our Saturday sales rollup — same skeleton, different cadence and the Claude formatting step added.
What You'll Need (Prerequisites)
- n8n v1.6x with the timezone set to Asia/Kolkata (Settings → check
GENERIC_TIMEZONE) - A Google Cloud service account with the Sheets API enabled, shared on the sales sheet
- An Anthropic API key for Claude (we used Claude 3.5 Sonnet; Haiku works and is cheaper)
- A WhatsApp Business account with the Cloud API and one approved utility template
- A clean Google Sheet: one row per order, columns for rep, amount, product, date
- About 75 minutes
How Do You Set Up the Three Credentials?
Google Sheets: Create a service account in Google Cloud, download the JSON key, and in n8n add a "Google Service Account" credential pasting that JSON. Then share the sheet with the service account's email (it ends in .iam.gserviceaccount.com) as a Viewer.
Claude: n8n has an Anthropic credential type. Paste your API key. We call Claude through the HTTP Request node for full control over the system prompt and max tokens, but the native Anthropic node works too.
WhatsApp Cloud API: n8n's WhatsApp Business Cloud node takes an access token and your phone number ID from Meta's developer dashboard. Generate a permanent token via a Meta System User — the temporary 24-hour token will silently break your cron next week.
The Trigger Config: Schedule for Sunday 7pm IST
The Schedule Trigger uses a cron expression. With n8n's timezone set to Asia/Kolkata, 0 19 0 means 7:00pm every Sunday.
{
"parameters": {
"rule": {
"interval": [
{ "field": "cronExpression", "expression": "0 19 0" }
]
}
},
"id": "schedule-sunday-eod",
"name": "Every Sunday 7pm IST",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.1,
"position": [240, 300]
} GENERIC_TIMEZONE is UTC, 0 19 * * 0 fires at 12:30am Monday IST. Set the env var, restart n8n, and trigger a manual test run before trusting the cron.
Reading and Aggregating the Week's Rows
The Google Sheets node reads the data tab. We then aggregate in a Code node — one row per rep with total value, order count, and top product. Doing the maths in n8n keeps the Claude prompt small and cheap.
{
"parameters": {
"operation": "read",
"documentId": "={{ $env.SALES_SHEET_ID }}",
"sheetName": "Orders",
"options": {
"dataStartRow": 2
}
},
"name": "Google Sheets — Read Orders",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4,
"position": [460, 300],
"credentials": {
"googleApi": { "id": "4", "name": "Sheets service account" }
}
}The Code node filters to the last 7 days and rolls up per rep:
{
"parameters": {
"jsLanguage": "javaScript",
"jsCode": "const weekAgo = new Date(Date.now() - 72460601000);\nconst rows = $input.all().map(i => i.json);\nconst recent = rows.filter(r => new Date(r.date) >= weekAgo);\nconst byRep = {};\nfor (const r of recent) {\n const rep = r.rep || 'Unknown';\n byRep[rep] = byRep[rep] || { rep, total: 0, orders: 0 };\n byRep[rep].total += Number(r.amount) || 0;\n byRep[rep].orders += 1;\n}\nreturn Object.values(byRep).sort((a,b) => b.total - a.total).map(json => ({ json }));"
},
"name": "Code — Roll Up Per Rep",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [680, 300]
}How Do You Get Claude to Write a WhatsApp-Ready Summary?
The point of Claude here isn't analysis — the maths is already done. It's tone and language. The reps read a mix of Hindi and English, so a raw table lands flat. Claude turns the rollup into a short, readable message with the top three reps called out and a one-line nudge for anyone at zero.
The system prompt that worked after a few iterations: "You are writing a short weekly sales summary for a field-sales WhatsApp group in India. Input is JSON of reps with totals in rupees. Write under 90 words, mix natural Hindi and English the way Indian sales teams talk, lead with this week's total, name the top 3 reps, and end with one motivating line. No markdown, no emojis beyond one trophy."
It took three iterations to get the tone right. The first version read like a press release — "We are pleased to report total weekly sales of..." — and the group ignored it exactly the way they ignored the spreadsheet. The second was too casual and buried the numbers. The third, the one above, leads with the figure, names names, and closes with a single line of push. The lesson generalises: the maths was never the hard part. Getting 22 busy people on bikes to actually read the message was, and that's a writing problem, not a data problem. We spent more time on the prompt than on every other node combined, and it was the right place to spend it.
{
"parameters": {
"method": "POST",
"url": "https://api.anthropic.com/v1/messages",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{ "name": "anthropic-version", "value": "2023-06-01" }
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"model\": \"claude-3-5-sonnet-20241022\",\n \"max_tokens\": 400,\n \"system\": \"You write a short weekly field-sales summary for an Indian WhatsApp group. Under 90 words, natural Hindi-English mix, lead with the weekly total, name the top 3 reps, one motivating closing line. No markdown.\",\n \"messages\": [{ \"role\": \"user\", \"content\": \"{{ JSON.stringify($json) }}\" }]\n}"
},
"name": "Claude — Format Summary",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [900, 300],
"credentials": {
"httpHeaderAuth": { "id": "5", "name": "Anthropic API" }
}
} Broadcasting on WhatsApp Without Getting Blocked
WhatsApp won't let you send free-form text to people outside a 24-hour window. For a Sunday push to a list, you need an approved template with a variable slot. We registered a utility template like: "Weekly sales rollup 📊 {{1}}" and inject Claude's summary into {{1}}.
The WhatsApp node loops over the recipient list (reps + manager) and sends the template:
{
"parameters": {
"resource": "message",
"operation": "send",
"phoneNumberId": "={{ $env.WA_PHONE_ID }}",
"recipientPhoneNumber": "={{ $json.phone }}",
"messageType": "template",
"template": "weekly_sales_rollup",
"templateLanguage": "en",
"components": {
"componentValues": [
{ "type": "body", "parameter": "={{ $json.summary }}" }
]
}
},
"name": "WhatsApp — Send Template",
"type": "n8n-nodes-base.whatsApp",
"typeVersion": 1,
"position": [1120, 300],
"credentials": {
"whatsAppApi": { "id": "6", "name": "WhatsApp Cloud" }
}
}How Do You Handle Errors in a Weekly Cron Like This?
A cron that runs once a week is easy to forget until it's been silently broken for a month. Three guardrails.
1. Heartbeat to the manager. If zero rows match the week, send the manager a "no orders logged this week — is the sheet being updated?" message instead of failing quietly. Silence and success look identical otherwise.
2. Retry WhatsApp sends. Per-recipient sends get Retry On Fail (3 tries). One bad number shouldn't kill the broadcast to the other 22. We also wrap the send loop so a single failure routes to a "failed_sends" log, not a stopped workflow.
3. Token-expiry alarm. A monthly check-call to the WhatsApp API; if it 401s, n8n alerts. Permanent tokens can still be revoked when a Meta admin changes.
What Does This Cost Per Week?
The WhatsApp slice is the surprise: India's per-message utility rate is low enough that 23 messages a week barely registers. Claude on Haiku instead of Sonnet would push the API cost lower still. The infra is the same shared Hetzner box that runs our other workflows.
When NOT to Build This
Skip it if your team is under ~6 people — a manager can scan the sheet and post a message himself in two minutes, and a hand-written note carries more weight than an automated one. Skip the Claude step entirely if your team reads plain English fine; a Code node can format a clean text table and you save the API call and the prompt-tuning. And don't build it if your Google Sheet is messy — inconsistent rep names or text in amount columns will produce a confident, wrong summary. Fix the data entry first.
Real Example: The Nagpur Distributor
The building-materials distributor (₹60 cr revenue, 22 field reps across Vidarbha) asked our automation team for "something that makes the team actually look at the numbers." We shipped this in 4 working days. Reply rate to the Sunday message ran around 40% in the first month — reps started replying with reasons for slow weeks, which the manager hadn't been getting at all from a silent spreadsheet. The dashboard-thinking came from work like Radiant Finance, where surfacing the right number at the right moment beat building a fuller report nobody opened. The build reused the exact skeleton from our Saturday rollup, and the WhatsApp-template discipline came from the same playbook as our WhatsApp auto-reply build.
"Pehle sheet bhar dete the, koi dekhta nahi tha. Ab Sunday ko message aata hai aur Monday meeting already half done hoti hai."
Frequently Asked Questions
Why send a WhatsApp template instead of plain text?
WhatsApp blocks free-form business-initiated messages outside a 24-hour customer window. A pre-approved utility template with a variable slot is the only reliable way to push a scheduled broadcast. You drop Claude's summary into the template's {{1}} body parameter.
Do I need Claude at all, or can n8n format the message?
You don't strictly need it. A Code node can build a clean text table for free. We use Claude because the Nagpur team reads Hindi-English better than a formal table, and the conversational tone drove replies. If your team reads English fine, skip the API call.
How do I make sure the cron fires at 7pm IST and not UTC?
Set n8n's GENERIC_TIMEZONE to Asia/Kolkata and restart. Then the cron 0 19 0 means 7pm Sunday IST. If you leave it UTC, that expression fires at 12:30am Monday IST. Always do one manual test run to confirm.
What happens if no orders were logged that week?
The flow detects zero matching rows and sends the manager a heartbeat message asking whether the sheet is being updated, rather than failing silently. Silence and success look the same otherwise, which is how weekly crons rot unnoticed.
Why did my WhatsApp broadcast stop working after a day?
Almost always the temporary 24-hour access token from Meta's quick-start. Create a System User and generate a permanent token, then update the n8n credential. A monthly heartbeat call catches token revocation too.
How much does the WhatsApp portion cost in India?
Very little. After WhatsApp's July 1, 2025 move to per-message pricing, India utility templates are inexpensive, and 23 messages a week barely registers. Utility templates inside a 24-hour service window are free.
Want a weekly WhatsApp rollup for your sales team?
We build the Google Sheets → Claude → WhatsApp pipeline, register your templates, and self-host it on your infra — for Indian SMBs in 5 working days. Suitable if you have a team logging numbers nobody reads. No slides — just your sheet and our honest take.
Book a 20-min Call
Written by Hrishikesh Baidya, CTO at Softechinfra. Want this on your stack? Email contact@softechinfra.com.
