The Problem with Airtable Automations
If you are building complex workflows in Airtable, you eventually hit a wall. You need to send data to a webhook (like Zapier or Make) or fetch data from an external API (like OpenAI or Stripe).
Usually, you have two options:
- Use the native "Send to Webhook" action (which is limited and can’t handle responses).
- Write a custom JavaScript for every single automation.
I got tired of writing the same fetch() boilerplate code over and over again. So, I built a solution.
Introducing the Universal Webhook Script
I’ve developed a robust, "copy-paste" JavaScript solution for Airtable Automations. This script acts as a universal HTTP client, allowing you to send GET or POST requests to any external API or Webhook directly from Airtable.
It bridges the gap between standard Airtable features and complex backend requirements.
Why use this script?
Unlike the standard automation actions, this script is designed for power users and developers who need flexibility without the headache of writing code from scratch.
- It’s Method Agnostic: It automatically handles
POSTrequests (sending JSON bodies) andGETrequests (converting inputs to URL query parameters). - Dynamic Payloads: You don’t need to edit the code to change the data you are sending. Any input variable you add to the automation is automatically sent as data.
- Built-in Security: It supports
Authorizationheaders, meaning you can safely use Bearer Tokens or Basic Auth for secure APIs. - Error Safety: The script intentionally fails the automation run if the API returns a 4xx or 5xx error. This ensures you never miss a failed sync—something native webhooks often overlook.
- Response Handling: It captures the API status code and raw response body, allowing you to use that data in the next steps of your automation.
The Script
Here is the full code. You can copy this directly into your Airtable "Run a script" action.
1const config = input.config();23// 1. CONFIGURATION4const { webhookUrl, method, authHeader, ...payload } = config;56if (!webhookUrl) throw new Error("❌ Error: 'webhookUrl' input is required.");78const httpMethod = (method || "POST").toUpperCase();910// 2. PREPARE REQUEST11let fetchOptions = {12 method: httpMethod,13 headers: {14 "Content-Type": "application/json",15 "Accept": "application/json"16 }17};1819if (authHeader) fetchOptions.headers["Authorization"] = authHeader;2021let finalUrl = webhookUrl;2223if (httpMethod === "GET") {24 const queryString = new URLSearchParams(payload).toString();25 if (queryString) {26 const separator = finalUrl.includes("?") ? "&" : "?";27 finalUrl = `${finalUrl}${separator}${queryString}`;28 }29 delete fetchOptions.body;30} else {31 fetchOptions.body = JSON.stringify(payload);32}3334console.log(`🚀 Sending ${httpMethod} to: ${finalUrl}`);3536// 3. EXECUTE37try {38 const response = await fetch(finalUrl, fetchOptions);39 console.log(`✅ Status: ${response.status} ${response.statusText}`);4041 const contentType = response.headers.get("content-type");42 let responseData;4344 if (contentType && contentType.includes("application/json")) {45 responseData = await response.json();46 } else {47 responseData = await response.text();48 }4950 console.log(`🔁 Response:`, responseData);5152 if (!response.ok) {53 throw new Error(`Request failed [${response.status}]: ${JSON.stringify(responseData)}`);54 }5556 output.set("status", response.status);57 output.set("responseBody", typeof responseData === 'object' ? JSON.stringify(responseData) : responseData);5859} catch (error) {60 console.error(`❌ Webhook Error: ${error.message}`);61 throw error;62}
Configuration Guide
Once you have pasted the code above, the magic happens in the Input Variables section of the Script Editor. You simply define the following system inputs:
webhookUrl(Required): The destination URL or API Endpoint (e.g., your Zapier hook).method(Optional):GETorPOST. If you leave this blank, it defaults toPOST.authHeader(Optional): Your API key or token (e.g.,Bearer sk_test_123).
The "Magic" Payload: Any other variable you add allows you to pass dynamic data. For example, if you add inputs for email and orderId, the script automatically formats them into a JSON body (for POST) or URL parameters (for GET).
Use Case Examples
1. Sending Data to Zapier/Make If you want to trigger a Make scenario, simply set the webhookUrl and add your data fields as inputs.
- webhookUrl:
https://hooks.zapier.com/... - email:
[Record Email] - name:
[Record Name]
2. Fetching Data from an External API Need to look up customer details? Set the method to GET.
- webhookUrl:
https://api.example.com/v1/customers - method:
GET - authHeader:
Bearer my-secret-token - email:
john@example.com
The result: The script will automatically format this request to https://api.example.com/v1/customers?email=john@example.com and return the data found.
Conclusion
This script is part of my effort to bridge the gap between standard Airtable features and complex backend requirements. It is open-source and available on GitHub if you want to contribute or fork it.
