Automation Blog

How to Make an HTTP POST Request in a Zapier Code Step with Headers and Parameters

How to fire a webhook or API POST request from a Zapier JavaScript or Python Code step — covering request headers, JSON body construction, Bearer token authentication, and response handling, with ready-to-use code snippets for the most common patterns.

ZapierCode StepsAPI

By Troy Tessalone · · 5 minutes

Automation Guide

A practical field guide from Automation Ace.

How to Make an HTTP POST Request in a Zapier Code Step with Headers and Parameters

Zapier's Webhooks by Zapier action handles most outbound HTTP POST requests, but there are cases where a Code step is the better tool: when the request body requires dynamic construction from multiple fields, when you need conditional logic around the request, when you are making multiple requests in sequence, or when the response requires parsing before its values are usable. Code steps in Zapier have access to a global fetch function (JavaScript) and the requests library (Python) — both capable of full HTTP control including headers, body, and authentication. This guide provides ready-to-use patterns for the most common POST request scenarios.

JavaScript: Basic POST with JSON Body

The global fetch function in Zapier JavaScript Code steps handles POST requests with a JSON body:

const response = await fetch('https://api.example.com/endpoint', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer ' + inputData.api_token
  },
  body: JSON.stringify({
    name: inputData.name,
    email: inputData.email,
    message: inputData.message
  })
});

if (!response.ok) {
  const errorBody = await response.text();
  throw new Error(`Request failed: ${response.status} ${errorBody}`);
}

const data = await response.json();

output = {
  status: String(response.status),
  id: data.id || '',
  response: JSON.stringify(data)
};

Pass api_token, name, email, and message as input data fields mapped from previous Zap steps. The throw new Error() causes the Zap step to fail with a visible error message in the run history when the API returns a non-2xx status code — useful for debugging.

JavaScript: POST with Custom Headers

Some APIs require multiple custom headers — API keys in non-standard header names, versioning headers, or request identifiers:

const response = await fetch('https://api.example.com/webhook', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Api-Key': inputData.api_key,
    'X-Api-Version': '2025-01',
    'X-Request-Id': inputData.request_id,
    'Accept': 'application/json'
  },
  body: JSON.stringify({
    event: inputData.event_type,
    payload: {
      record_id: inputData.record_id,
      timestamp: new Date().toISOString()
    }
  })
});

const data = await response.json();
output = { success: response.ok ? 'true' : 'false', response_id: data.id || '' };

JavaScript: POST with Basic Auth

For APIs that use HTTP Basic authentication (username and password encoded in the Authorization header):

const credentials = btoa(inputData.username + ':' + inputData.password);

const response = await fetch('https://api.example.com/submit', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Basic ' + credentials
  },
  body: JSON.stringify({ data: inputData.payload })
});

const data = await response.json();
output = { status: String(response.status), result: JSON.stringify(data) };

btoa() is available as a global in Zapier's JavaScript Code step environment for base64 encoding.

JavaScript: POST with Form-Encoded Body

Some APIs — particularly OAuth token endpoints and legacy systems — expect application/x-www-form-urlencoded bodies rather than JSON:

const params = new URLSearchParams({
  grant_type: 'client_credentials',
  client_id: inputData.client_id,
  client_secret: inputData.client_secret,
  scope: 'read write'
});

const response = await fetch('https://api.example.com/oauth/token', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
  },
  body: params.toString()
});

const data = await response.json();
output = { access_token: data.access_token || '', expires_in: String(data.expires_in || '') };

Python: POST with JSON Body and Bearer Token

For Python Code steps, the requests library is available and handles JSON bodies and headers cleanly:

import requests

url = 'https://api.example.com/endpoint'
headers = {
    'Authorization': f"Bearer {input_data['api_token']}",
    'Content-Type': 'application/json'
}
payload = {
    'name': input_data['name'],
    'email': input_data['email'],
    'source': 'zapier'
}

response = requests.post(url, json=payload, headers=headers)
response.raise_for_status()  # raises exception on 4xx/5xx

data = response.json()
return {
    'status': str(response.status_code),
    'id': str(data.get('id', '')),
    'response': str(data)
}

The requests library's json=payload parameter automatically serializes the payload and sets Content-Type: application/json. raise_for_status() causes the Code step to fail visibly on non-2xx responses. For a full reference of available Python libraries, see Python libraries in Zapier Code steps.

When to Use a Code Step vs. Webhooks by Zapier for POST Requests

Use Webhooks by Zapier when the POST request is straightforward — a single endpoint, simple headers, and a flat request body that maps directly from Zap fields. Webhooks by Zapier handles this with no code required. See how to use APIs in Zapier steps for configuration details.

Use a Code step when:

  • The request body needs dynamic construction — nested objects, arrays, conditional fields
  • You need to make multiple sequential POST requests and use the response from one to build the next
  • You need response parsing logic before the data is usable in downstream steps
  • Error handling needs to be more nuanced than "fail the Zap on non-2xx"
  • You want to fire the request to the Zapier Storage API or another internal Zapier service
The global fetch in Zapier's JavaScript Code steps is a full HTTP client — headers, body, method, authentication, and response handling all work as expected. Once you have the pattern for a POST with a JSON body and Bearer token, almost every API call you will ever need follows the same structure with minor variations in the header names and body shape.

For the GET request equivalent, see how to make an HTTP GET request in a Zapier Code step. For more on what is available in JavaScript Code steps, see JavaScript libraries in Zapier Code steps. For help building an API integration workflow, talk to Automation Ace.

ZapierCode StepsAPI

Disclaimer: This article may include links to apps, products, or services. Some links may be affiliate links, which means Automation Ace may earn a commission at no extra cost to you.

Build Better Systems

Ready to automate with confidence?

Share your tools, process, and goals. Automation Ace can design the workflow, integration, AI assist, or code bridge that fits your business.

Start a Project →