Log inStart Free Trial
Meta Tech Provider

Log WhatsApp messages to Airtable and send from a base

Airtable's incoming webhook trigger only accepts POST requests, so it cannot answer Meta's verification GET and cannot be a number's webhook destination itself. Point the destination at an n8n workflow that appends each message to a table. Sending works from inside Airtable: a Run a script automation can call the Cloud API with fetch and the number's token stored as a secret.

POST only

Airtable's When webhook received trigger accepts no other method, so it cannot answer a verification GET.

5 per second

Request limit on Airtable's incoming webhook trigger, with a 100 KB payload cap.

50 fetches

Requests one Airtable Run a script action can make, each timing out after 30 seconds.

Why can Airtable not receive WhatsApp webhooks directly?

Because Meta checks a destination before it delivers anything. It sends a GET request carrying a challenge value and expects the same value back as the response body. Airtable's When webhook received trigger only accepts POST requests and answers with its own fixed JSON, so the check cannot pass and Meta never starts delivering.

The answer is one step in between. An n8n Webhook node handles the verification and receives each message, and n8n's Airtable node appends a row: sender, profile name, text, message id, timestamp and the receiving phone number id. The same shape works in Make or Zapier.

The in-between step has a second benefit. Airtable's webhook trigger allows five requests a second, and a workflow tool can queue a burst that would otherwise be refused.

How do you send a WhatsApp template from an Airtable base?

With an automation whose action is Run a script. The trigger can be a record entering a view, a field changing or a button being clicked. The script reads the record's phone and fields through input.config() and calls the Cloud API messages endpoint with fetch. Airtable automation scripts run server-side, so there is no browser restriction in the way.

Store the access token as a secret in the script editor rather than in the code. Airtable redacts secrets from console output and only lets people with access to all of a script's secrets edit it.

Use a template for anything the customer has not prompted in the last 24 hours, since free text only delivers inside that window. The script can write the returned message id back to the record, which ties the send to the row.

Run a script action: send an approved template
const { phone, name } = input.config();
const token = input.secret("WHATSAPP_TOKEN");
const res = await fetch(
  "https://graph.facebook.com/v23.0/<PHONE_NUMBER_ID>/messages",
  {
    method: "POST",
    headers: { Authorization: "Bearer " + token, "Content-Type": "application/json" },
    body: JSON.stringify({
      messaging_product: "whatsapp",
      to: phone,
      type: "template",
      template: {
        name: "order_ready",
        language: { code: "en" },
        components: [{ type: "body", parameters: [{ type: "text", text: name }] }],
      },
    }),
  },
);
output.set("result", await res.json());

What should the messages table look like?

One row per message, with the WhatsApp message id as the primary field. Meta retries deliveries it thinks failed, and a workflow that looks the id up before appending never writes the same message twice.

Keep a direction field with inbound and outbound. On a Coexistence number, replies the team types in the WhatsApp Business app arrive at the same webhook as smb_message_echoes events, and logging them as outbound rows gives the base the full conversation rather than one side of it.

Link each message to a Contacts table keyed on the digits-only phone number, which is the form Meta sends. A rollup then shows the last inbound time per contact, and that single field is what an automation needs to decide between free text and a template.

Common mistakes

  • Setting an Airtable webhook URL as the number's destination. It accepts POST only, Meta's verification GET fails, and nothing is ever delivered.
  • Pasting the access token into the script body. Store it as a script secret so it stays out of the code and the logs.
  • Sending free text from a record automation to someone who has not written in 24 hours. Only an approved template delivers.
Doing this with EasyCoexistence

Connect the number at easycoexistence.com, point its webhook destination at the n8n workflow that writes to Airtable, and read the phone number id and token from the dashboard. From US$ 9 per number per month, falling to US$ 1 as you add numbers, with the first 3 days free.

Frequently asked questions

Is Run a script on the Airtable free plan?

Airtable lists the action on all plan types with varying limitations, and notes it is not available on a Team plan trial.

Can I skip n8n and use Make or Zapier?

Yes. Any of the three can receive the webhook, answer the verification and append the row. Airtable itself is the one piece that cannot be the destination.

Can an Airtable button send a WhatsApp message?

Yes. Use the When a button is clicked trigger with a Run a script action that calls the Cloud API, and the row's data fills the template.

Does EasyCoexistence store the messages?

No. Meta delivers each webhook to your n8n URL, and the only copy is the one your workflow writes to Airtable.

Keep reading

Ready to get started?

Set up WhatsApp Coexistence in minutes, not months. The app keeps working on the phone.

Start Free Trial

Verified on

WhatsApp and Airtable on the Cloud API