Receiving OPTIONS instead of POST request when calling API from Airtable automation

I’m trying to send data from an Airtable automation to my Node.js API endpoint but I’m getting a weird issue. When the script runs, my API receives an OPTIONS request instead of the POST request I’m sending. This causes a 405 error.

The strange part is that my API works perfectly when I test it using Postman with the same data.

Airtable gives me this error:

TypeError: Failed to fetch
at main on line 27
This error might be related to Cross-Origin Resource Sharing (CORS)

My server logs show:

OPTIONS /api/data-receiver 405 Method Not Allowed

Here’s my Airtable automation code:

let contacts = base.getTable('Contacts');
let gridView = contacts.getView('Main View');

let allRecords = await gridView.selectRecordsAsync()
let currentRecord = allRecords.records[0]

var payload = {
  customer: {
    "name": currentRecord.getCellValueAsString('fullName'),
    "surname": currentRecord.getCellValueAsString('familyName'),
    "emailAddress": currentRecord.getCellValueAsString('contactEmail'),
  }
}

console.log(JSON.stringify(payload))

let apiResponse = await fetch('https://myapi.example.com/api/data-receiver', {
  method: 'POST',
  body: JSON.stringify(payload),
  headers: {
    "Content-Type": 'application/json',
    "Accept": "application/json",
  }
})

let jsonResponse = await apiResponse.json()
console.log("API Response:", jsonResponse)

await contacts.updateRecordAsync(currentRecord.id, {
  apiResult: jsonResponse,
});

My Node.js endpoint (api/data-receiver.js):

export default async function handler(request, response) {
  const { method } = request;
  console.log("HTTP Method:", method)
  
  switch (method) {
    case "POST":
      console.log("Request body", request.body)
      return processData(request, response);
    case "OPTIONS":
      response.setHeader("Allow", "POST");
      response.setHeader("Allow", ["GET", "POST", "PUT", "DELETE", "OPTIONS"]);
      response.status(405).end(`Method ${method} Not Allowed`);
  }
}

const processData = async (request, response) => {
  console.log("Processing request: ", request.body)
  response.status(200).json("Success")
}

I added the OPTIONS case recently to debug this issue. Any ideas why Airtable is sending OPTIONS instead of POST?

Been dealing with this exact headache for years. The browser sends a preflight OPTIONS request to check if your cross-origin POST is allowed.

Your OPTIONS handler is telling the browser “nope, not allowed” with that 405 response. Browser sees this, gives up, and never sends your actual POST.

Here’s my usual fix:

case "OPTIONS":
  response.setHeader("Access-Control-Allow-Origin", "*");
  response.setHeader("Access-Control-Allow-Methods", "POST, OPTIONS");
  response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
  response.status(200).end();
  break;

Also add those same CORS headers to your POST response so the browser can read the result.

I’ve seen teams waste entire sprints on CORS issues like this. There’s a solid walkthrough covering all the edge cases:

Once your OPTIONS request returns 200 with proper headers, your POST will follow right behind.

Had the exact same nightmare with Airtable automations last month. Your fetch call isn’t the problem - it’s CORS preflight behavior that gets everyone at first. Your OPTIONS handler returns 405, which basically slams the door on the browser’s preflight check. The browser thinks “server doesn’t support cross-origin requests” and gives up before trying your POST. I fixed it by making my OPTIONS case return 200 with proper CORS headers. But here’s another gotcha - you need Access-Control-Allow-Origin on your actual POST response too. Otherwise the browser won’t let your Airtable script read the response data even if the request works. Postman working makes sense since it doesn’t enforce CORS like browsers do. Fix the preflight and your automation should work exactly like your Postman tests.

this looks like a preflight issue, but you’ve got two different Allow headers set up - that’s probably confusing the browser. Just return a 200 status on OPTIONS requests with your CORS headers and ditch that 405 response completely. the browser won’t send your POST until it gets permission first.

your CORS setup’s broken. the OPTIONS handler is returning 405, which kills the preflight request. use response.status(200).end() instead of throwing that 405 error. browsers send OPTIONS first to check CORS, then fire the actual POST if it passes.

Your API’s throwing a 405 error on the OPTIONS preflight request that Airtable sends before making the actual POST. This happens with cross-origin requests when there are custom headers or specific content types involved - totally normal browser behavior. Right now your OPTIONS handler isn’t set up properly. You need to handle OPTIONS requests by adding the right CORS headers (Access-Control-Allow-Origin, Access-Control-Allow-Methods, Access-Control-Allow-Headers) and returning a 200 status with response.status(200).end(). Once you fix the OPTIONS handling, your POST should work fine.

This topic was automatically closed 4 days after the last reply. New replies are no longer allowed.