How to POST to a webhook in 5 different programming languages

Josh Sherman
6 min read
Software Development PHP Node.js

With the release of inbound webhooks for CrowdSync workflows last week, it seemed fitting to do a write up on how to POST to a webhook.

So what is a webhook, anyway?

The Wikipedia definition is that webhooks are “used-defined HTTP callbacks”.

Kind of a stuffy definition if you ask me. Webhooks are endpoints (URLs) that allow you to bridge services together programmatically. You can setup your system to automatically send data to another service via a webhook.

A real world example would be if you were collecting information for event attendees via Google Forms. Let’s say you want to put each person into a CrowdSync workflow to make it easier to onboard them into you event, you could setup webooks to tie things together!

Now that we know what a webhook is, let’s talk about how you actually implement a webhook. In effort to cover as many bases as possible, I’m going to cover POSTing to a webhook in 5 popular, open source languages, Node.js, Python, Go, PHP and Ruby.

For the sake of consistency and to show off our latest addition, the following examples will be for CrowdSync’s inbound webhook. The code snippets themselves can easily be modified to support webhooks from other platforms like Zapier or IFTTT.

Please note that these examples make a couple of hard assumptions about the webhook you are working with.

First, it’s assumed that the webhook you are hitting is served up over HTTPS. Just about everybody has made this shift, so it shouldn’t be a big deal.

The other assumption is that the webhook is going to talk back in JSON format. Most modern systems default to returning JSON so also not a big thing.

If you are working with a webhook that isn’t using HTTPS and/or doesn’t return JSON you will need to make some adjustments to the code samples.

Also, one last note. I strived to use as little external dependencies as possible for these examples. You are welcome.


package main

import (

func main() {
	var data map[string]interface{}

	endpoint := ""

	form := url.Values{
		"primaryFirstName": []string{"CrowdSync"},
		"primaryLastName":  []string{"Support"},
		"primaryEmail":     []string{"[email protected]"},

	req, err := http.NewRequest("POST", endpoint, strings.NewReader(form.Encode()))

	if err != nil {

	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")

	client := &http.Client{}
	res, err := client.Do(req)

	if err != nil {

	defer res.Body.Close()
	body, err := ioutil.ReadAll(res.Body)

	if err != nil {

	json.Unmarshal([]byte(string(body)), &data)



const https = require('https');
const querystring = require('querystring');

const payload = querystring.stringify({
  primaryFirstName: 'CrowdSync',
  primaryLastName: 'Support',
  primaryEmail: '[email protected]',

const options = {
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
    'Content-Length': Buffer.byteLength(payload),
  hostname: '',
  method: 'POST',
  path: '/hooks/test',

const request = https.request(options, function (res) {
  res.on('data', function (data) {
    if (res.statusCode !== 200) {
      throw new Error('Not OK (non-200 status code received)');

    if (data) {
      data = JSON.parse(data);

      console.log('Response:', data);

      // Do some other awesome Node.js stuff here...

request.on('error', function (e) {
  throw new Error(e.message);




$curl = curl_init();
$url = '';

curl_setopt_array($curl, [
    CURLOPT_URL => $url,
    CURLOPT_HEADER => false,
      'primaryFirstName' => 'CrowdSync',
      'primaryLastName' => 'Support',
      'primaryEmail' => '[email protected]',

$response = curl_exec($curl);

if ($error = curl_error($curl)) {
  throw new Exception($error);

$response = json_decode($response, true);

var_dump('Response:', $response);

// Do some other awesome PHP stuff here...


import json
import requests

url = ''
payload = {
  'primaryFirstName': 'CrowdSync',
  'primaryLastName': 'Support',
  'primaryEmail': '[email protected]',

response =, data=payload);

if response.status_code != 200:
  raise Exception('Not OK (non-200 status code received)')

response = json.loads(response.text);

print 'Response:', response


require 'json'
require 'net/http'

response = Net::HTTP.post_form(
  'primaryFirstName' => 'CrowdSync',
  'primaryLastName' => 'Support',
  'primaryEmail' => '[email protected]',

if response.code != '200'
  raise 'Not OK (non-200 status code received)'

response = JSON.parse(response.body)

puts "Response: #{response}"

That’s all folks, enjoy!

Join the Conversation

Good stuff? Want more?

Weekly emails about technology, development, and sometimes sauerkraut.

100% Fresh, Grade A Content, Never Spam.

About Josh

Husband. Father. Pug dad. Musician. Founder of Holiday API, Head of Engineering and Emoji Specialist at Mailshake, and author of the best damn Lorem Ipsum Library for PHP.

Currently Reading

Parasie Eve

Previous Reads

Buy Me a Coffee Become a Sponsor

Related Articles