Log every WhatsApp lead directly into an Airtable base, look up records by email or phone before personalising a message, and keep your Airtable CRM in sync with WhatsApp conversations automatically.
Before following this guide, read the External API Request step foundation guide. It covers every field so this guide can focus on Airtable-specific values.
Legacy API keys (starting with key...) stopped working on 1 February 2024. The only authentication method today is a Personal Access Token (PAT), created at airtable.com/create/tokens. If any guide tells you to go to Account settings to find your API key, it is outdated.
Airtable PATs have two separate permission dimensions: scopes (what the token can do) and base access (which bases it can reach). Both must be configured. Adding scopes but forgetting to add the base to the token causes 403. Adding the base but forgetting the write scope causes 403. Check both before debugging anything else.
data.records:read,
data.records:write, and
schema.bases:read.Airtable Web API: airtable.com/developers
The Base ID and table name form the API URL for every request.
Base URL pattern:
https://api.airtable.com/v0/{baseId}/{tableName}
Base ID: in your browser URL when inside a base.
https://airtable.com/app123abc456/tblXXXXX/...
Base ID = app123abc456 (starts with 'app')
Table name: the tab name in Airtable, e.g. 'Leads' or 'Contacts'.
URL-encode spaces: 'WhatsApp Leads' -> 'WhatsApp%20Leads'
Full example URL:
https://api.airtable.com/v0/app123abc456/LeadsWhen a customer opts in or provides their details on WhatsApp, create a record immediately.
Body:
{{
"fields": {{
"Name": "Priya Sharma",
"Email": "priya@example.com",
"Phone": "+919820000001",
"Source": "WhatsApp",
"Status": "New"
}}
}}
Response (HTTP 200):
{{
"id": "recAbCdEfGhIjKl",
"createdTime": "2026-06-23T08:30:00.000Z",
"fields": {{
"Name": "Priya Sharma",
"Email": "priya@example.com",
"Phone": "+919820000001",
"Source": "WhatsApp",
"Status": "New"
}}
}}
Map: id -> record_id
Field names must match the column headers in your Airtable table exactly,
including capitalisation.If your Airtable column is called 'Full Name', use 'Full Name' in the fields object. 'Name' and 'full name' will fail silently or create a new field. Check the exact column names in your Airtable base before mapping.
To check whether a WhatsApp contact already exists in Airtable before creating a duplicate, use a filtered GET request.
URL (decoded for readability):
GET https://api.airtable.com/v0/app123abc456/Leads
?filterByFormula={{Email}}='priya@example.com'
URL-encoded (what you actually send):
?filterByFormula=%7BEmail%7D%3D%22priya%40example.com%22
Response:
{{
"records": [
{{
"id": "recAbCdEfGhIjKl",
"fields": {{
"Name": "Priya Sharma",
"Email": "priya@example.com",
"Status": "Contacted"
}}
}}
]
}}
records is empty -> contact not found -> create new record
records has items -> map records[0].id, records[0].fields.*Trigger: Customer messages 'DEMO' on WhatsApp.
Bot collects:
{{customer_name}} = Priya Sharma
{{customer_email}} = priya@example.com
{{customer_phone}} = +919820000001
Step 1 — Check if record exists (GET):
GET https://api.airtable.com/v0/app123abc456/Leads
?filterByFormula={{Email}}='priya@example.com'
Authorization: Bearer pat...
Response: records = [] (not found)
Conditions: if records not empty -> use records[0].id, send existing-contact reply
if records empty -> run Step 2
Step 2 — Create record (POST):
POST https://api.airtable.com/v0/app123abc456/Leads
Body: {{fields: {{Name:"Priya Sharma", Email:"priya@example.com",
Phone:"+919820000001", Source:"WhatsApp", Status:"New"}}}}
Response: {{id: 'recAbCdEfGhIjKl', fields: {{...}}}}
Bot replies:
'Thanks Priya! We have added you to our demo list.
Our team will reach you at +919820000001 within 24 hours.'| Symptom | Likely cause | Fix |
|---|---|---|
| 401 Unauthorized | PAT missing or wrong format | Ensure the header is 'Authorization: Bearer pat...' with a space after Bearer. Copy the PAT again from airtable.com/create/tokens. Tokens starting with 'key...' are the old disabled keys. |
| 403 Forbidden | Missing scope or base not added to token | Check both dimensions: (1) data.records:write scope is added to the token, (2) the specific base is added under Access in the token settings. Both are required. |
| Field not saved, 422 error | Field name mismatch | The field name in the POST body must match the column header exactly, including capitalisation and spacing. Check the exact name in your Airtable table. |
| Empty records on GET search | filterByFormula syntax or URL encoding wrong | Test with a simplified formula first: filterByFormula=1. Then add field filters. URL-encode curly braces as %7B/%7D and spaces as %20. |
| Duplicate records being created | Not checking before creating | Add a GET lookup step before POST. If records is not empty, update the existing record instead of creating a new one. |
| Table not found | Table name in URL doesn't match | Use the exact table name from the Airtable tab. URL-encode spaces. You can also use the table ID (starting with tbl) from the URL instead of the name. |
Log WhatsApp data to a Google Sheet as a lightweight Airtable alternative.
Read guide →Free trial, no credit card. If you get stuck, we answer live on WhatsApp.