Airtable webhooks: automation trigger, Run a script and the Webhooks API
Airtable webhooks come in three forms: the When webhook received automation trigger (POST, 100KB), a Run a script action that calls fetch, and the Webhooks API, whose webhooks expire after 7 days unless refreshed. Test each with a free webhooks.sh bin: no signup, 48 hours, 100 requests a day.
Airtable has three different things called webhooks: the When webhook received trigger that starts an automation, a Run a script action that sends an HTTP request with fetch(), and the Webhooks API that pings your server when a base changes. Below: how each works, testing with a free bin, verifying the MAC header, and the expiry and retry rules.
Which Airtable webhook you need
If data is coming into Airtable from another app, use the When webhook received automation trigger. If Airtable needs to tell another system about a record, use Run a script to send a request, and if you run a server that needs to follow every change in a base, use the Webhooks API.
| Option | Direction | What travels | Main limits |
|---|---|---|---|
| When webhook received | Into Airtable | POST with a JSON object or form data | 100KB, 5 requests a second |
Run a script with fetch | Out of Airtable | Any request your script builds | 50 fetch calls a run, 30 seconds each |
| Webhooks API | Out of Airtable | A short ping; you fetch the changes | Expires after 7 days, 10 per base |
Trigger an automation with When webhook received
For an Airtable automation webhook, the When webhook received trigger gives you a unique URL and waits for one successful example request before you can click Run test and map fields into later steps. A request fails if it breaks one of Airtable's rules:
- It uses a method other than
POST. Content-Typeis missing, or isn'tapplication/jsonorx-www-form-urlencoded.- The JSON body has an array at the top level instead of an object.
- The payload is over 100KB.
Point the sending app at a free webhooks.sh bin first to see its method, headers and body. Then replay a clean POST with a top-level JSON object to the Airtable URL with curl; a valid request returns {"success": true}, and you can select Run test.
Airtable doesn't support signature verification on these URLs, so anyone with the URL can trigger your automation. Every run also counts toward your workspace's monthly automation runs (100 on Free, 25,000 on Team, 100,000 on Business), and the trigger takes 5 requests per second.
# 1. Create a free bin and point the sending app at it
curl -X POST https://webhooks.sh/v1/bins
# 2. Send the captured body to Airtable as the example
curl -X POST "<airtable-webhook-url>" \
-H "Content-Type: application/json" \
-d @payload.json
Send a webhook from Airtable with Run a script
There is no built-in Airtable send webhook action that posts to an arbitrary URL. To send record data out of an automation, add a Run a script action, map the record fields in as input variables, read them with input.config(), and POST them with fetch().
Point your script at https://<bin>.webhooks.page/airtable first so you can see the exact headers and JSON body your script produces before you aim it at a real API.
Airtable's scripting fetch() differs from browser fetch() in ways that bite:
- It doesn't follow redirects, so use the final URL.
- There is no
FormData, no cookies, noRefererheader, and no streaming. - The response payload is capped at 4.5MB.
- A run can make up to 50
fetch()calls, each times out after 30 seconds, and the script timeout is currently 120 seconds.
const { recordId, status } = input.config();
const res = await fetch("https://<bin>.webhooks.page/airtable", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ recordId, status }),
});
console.log(res.status, await res.text());
The Webhooks API: pings and the MAC header
The Airtable Webhooks API doesn't send changed records to your server. It sends a small POST ping with the base id, the webhook id and a timestamp; your server then calls list webhook payloads (GET .../webhooks/{webhookId}/payloads) with a cursor to pull up to 50 payloads at a time. Pings are at-least-once and can be spurious or coalesced, so track the cursor instead of counting pings.
To see a live ping, set notificationUrl to your bin's ingest URL when you create the webhook with POST https://api.airtable.com/v0/bases/{baseId}/webhooks. The X-Airtable-Content-MAC header stays visible, since webhooks.sh only redacts headers whose names contain authorization, cookie, key, token or secret.
The creation response includes macSecretBase64, which Airtable shows only once, so store it right away. Each ping carries hmac-sha256= plus the hex HMAC-SHA256 of the raw body, keyed with the base64-decoded secret, in X-Airtable-Content-MAC; recompute it on your server and compare in constant time. The webhook security guide covers signature checks in more depth.
import crypto from "node:crypto";
export function verifyAirtable(rawBody, header, secretBase64) {
const secret = Buffer.from(secretBase64, "base64");
const expected = "hmac-sha256=" + crypto
.createHmac("sha256", secret)
.update(rawBody, "utf8")
.digest("hex");
const a = Buffer.from(expected);
const b = Buffer.from(header || "");
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
Expiry, retries and limits
Two Webhooks API rules break integrations quietly after they go live:
- Webhooks created with a personal access token or OAuth token expire after 7 days. Calling refresh webhook or list webhook payloads while it's active resets the clock to 7 days from that call.
- If your
notificationUrlkeeps failing, Airtable retries up to 13 times with exponential backoff from 10 seconds (about a day), then drops the ping and disables notifications until you re-enable them with the toggle notifications endpoint. Payloads keep generating meanwhile.
Airtable asks for HTTP 200 or 204 with an empty body, and counts a ping as failed on a connection error, more than 25 seconds, or any other status. A free bin answers 200 with a small JSON body like {"ok":true,"delivery_id":"..."}, which matches none of those failure conditions, so a test webhook pointed at a bin stays out of the retry loop.
| Rule | Value |
|---|---|
| Webhook lifetime | 7 days, extended 7 days by refresh or list payloads |
| Webhooks per base | 10, or 2 per OAuth integration |
| Ping timeout | 25 seconds |
| Ping retries | Up to 13, backoff from 10 seconds, about 1 day |
| Payloads per list request | 50 |
| Payload retention | 1 week |
| Rate limit | 5 requests a second per base, then 429 and a 30-second wait |
Keep the test URL
A free bin lasts 48 hours and takes 100 requests a day of up to 100KB each, plenty for setting up an automation or inspecting pings. To keep the URL, claim the bin with a free Google sign-in before it expires; the timer stops and it keeps 30 days of rolling history.
Solo ($12 a month) adds named endpoints on webhooks.host, 250,000 requests a month, 5MB bodies, the wsh CLI relay to localhost and forwarding to up to 3 verified HTTPS URLs; see pricing.
FAQ
How do I trigger an Airtable automation with a webhook?
Choose the When webhook received trigger, send one example POST with a JSON object to the URL Airtable gives you, and check for the {"success": true} response. Then click Run test to load the fields for later steps.
Can Airtable send a webhook when a record changes?
Not with a built-in no-code action. You either add a Run a script action to an automation and call fetch() to POST the record fields, or use the Webhooks API so Airtable pings your server whenever the base changes.
Why does my Airtable webhook expire after 7 days?
Webhooks API webhooks created with a personal access token or OAuth token expire 7 days after creation. Calling refresh webhook or list webhook payloads while it's still active extends the expiry to 7 days from that call.
Does the Airtable webhook ping include the changed records?
No, the POST to your notificationUrl only contains the base id, the webhook id, and a timestamp. Your server has to call list webhook payloads (GET .../webhooks/{webhookId}/payloads) with a cursor to fetch the actual record or schema changes.
What is the payload limit for Airtable's When webhook received trigger?
The When webhook received trigger accepts payloads up to 100KB and only allows POST requests. If you send application/json, the top level of the body must be a JSON object, not an array.
How do I verify an Airtable webhook?
For the Webhooks API, base64-decode macSecretBase64, compute the HMAC-SHA256 of the raw request body, and compare the hex result against the hmac-sha256= value in the X-Airtable-Content-MAC header. The When webhook received automation trigger does not support signature verification.
Last updated
Try it in 10 seconds.
Create a free bin at view.webhooks.page — no signup, no install. Point your sender at the URL and watch requests land live. Bins expire after 48 hours.