Getting OPTIONS request instead of POST when sending data from Airtable to my endpoint

I’m having trouble sending data from an Airtable automation script to my backend API. When I test the API directly with Postman, everything works fine and I can send POST requests without any issues.

But when I try to make the same request from my Airtable script, something weird happens. Instead of receiving a POST request on my server, I’m getting an OPTIONS request which returns a 405 error.

The error message in Airtable mentions CORS issues and says “Failed to fetch”. My server logs show “OPTIONS /webhook/submit 405 Method Not Allowed”.

Here’s my Airtable automation code:

let dataTable = base.getTable('Users');
let mainView = dataTable.getView('Main View');

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

var payload = {
  userInfo: {
    "name": currentRecord.getCellValueAsString('Name'),
    "surname": currentRecord.getCellValueAsString('Surname'),
    "userEmail": currentRecord.getCellValueAsString('Email'),
  }
}

let apiResponse = await fetch('https://my-app.ngrok.io/webhook/submit', {
  method: 'POST',
  body: JSON.stringify(payload),
  headers: {
    "Content-Type": 'application/json',
    "Accept": "application/json",
  }
})

let responseData = await apiResponse.json()

await dataTable.updateRecordAsync(currentRecord.id, {
  apiResponse: responseData,
});

My backend handler looks like this:

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

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

I added the OPTIONS case to see what’s happening, but I’m not sure how to fix this CORS issue. Any ideas what I’m doing wrong?

your OPTIONS handler is rejecting the request with a 405 instead of allowing it. change your OPTIONS case to return a 200 status with the right CORS headers - res.setHeader('Access-Control-Allow-Origin', '*') and res.setHeader('Access-Control-Allow-Methods', 'POST'). the browser sends OPTIONS first to check if POST’s allowed.

Your OPTIONS handler is the problem - you’re sending a 405 error when you should return a 200 with proper CORS headers. Browsers send a preflight OPTIONS request before the actual POST to check permissions. Fix it by changing your OPTIONS case to: res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'POST'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type'); res.status(200).end();. This tells the browser the preflight is good, so your POST will go through.