Configure Webhooks

Configuration

Webhooks are automatic notifications sent over the web, triggered by specific events. In our case the event is a new form response.

When a new form response is created we send a notification (along with the response data) to the configured webhook URL in real-time.

The webhook action offers 3 settings:

Method

Formcrafts supports two ways of sending webhooks:

  1. Form: This sends the webhook using the content-type of application/x-www-form-urlencoded. The data itself is encoded as key-value pairs, separated by &.

  2. JSON: This sends the data using the content-type of application/json. The data itself is encoded using JSON format.

Webhook URL

This must be a public URL that can accept POST requests. This is where we send the notification when a new form response is created.

Request signature

Your webhook URL is public, which means means that anyone can send data to this URL, which creates a security issue. To prevent this, Formcrafts can optionally send a signature along with the data. You can use this signature to verify that the data is indeed coming from Formcrafts, and hasn’t been tampered with.

The signature is sent via the x-formcrafts-signature header. To verify the signature, you need to do the following:

  1. Use the HMAC SHA256 algorithm to calculate the hash of the request body using the secret key.
  2. Encode the hash in base64 format.
  3. Prefix the hash with sha256=
  4. Compare the signature sent by Formcrafts with the one you calculated. If they match, then the request is valid.

Here is a code sample on achieving the above using Node.js with the Express framework.

const express = require('express')
const crypto = require('crypto')
const app = express()
const port = 3000

const verifySignature = function (receivedSignature, payload) {
  const hash = crypto
    .createHmac('sha256', "123")
    .update(payload)
    .digest('base64')
  return receivedSignature === `sha256=${hash}`
}

// When using "Form" type webhook
app.use(express.urlencoded({
  verify: (request, _, buffer) => {
    const signature = request.headers['x-formcrafts-signature']
    if (signature && verifySignature(signature, buffer) === false) {
      throw new Error("Invalid signature.");
    }
  },
  extended: true
}));

// When using "JSON" type webhook
app.use(express.json({
  verify: (request, _, buffer) => {
    const signature = request.headers['x-formcrafts-signature']
    if (signature && verifySignature(signature, buffer) === false) {
      throw new Error("Invalid signature.");
    }
  },
  extended: true
}));

app.post('/webhook', async (request, response) => {
  console.log('Received data', request.body)
  return response.status(200).send('OK')
})

app.listen(port, () => {
  console.log(`Webhook app listening on port ${port}`)
})

Logs

Formcrafts keeps a record of all successful and failed webhooks which you can view using the Logs button on the top-left corner of the form editor.

Learn more about Workflow logs.

Data structure

The data sent to the webhook URL in JSON format would look like this:

{
  "response_id": "1234",
  "created_at": "2024-02-23T20:12:30.081833+00:00",
  "form_id": "abcd1234",
  "form_name": "My form",
  "workspace_id": "e132bf87",
  "timezone": "America/Toronto",
  "page_url": "https://app.formcrafts.com/abcd1234?test=true",
  "test": true,
  "response_data": {
    "One line input": "Jack",
    "Number": "123",
    "Email": "[email protected]",
    "Phone": "+16479173435",
    "Comment": "This is a comment",
    "Hidden": "some_value",
    "Card": "100",
    "Datepicker": "2021-06-06",
    "Timepicker": "14:30",
    "NPS": "8",
    "Rating": "5",
    "Tabular": [
      [
        "Jane",
        "32",
        "Marketing"
      ]
    ],
    "Multiple Choice": [
      {
        "label": "Billing",
        "value": "billing"
      }
    ],
    "Dropdown": [
      {
        "label": "Canada",
        "value": "CA"
      }
    ],
    "Slider": {
      "label": "50 people",
      "value": "50"
    },
    "File upload": [
      {
        "id": "0b40f670-6881-49c1-97e5-3fb4c70a317e",
        "name": "some-image.png",
        "size": 92000,
        "mimetype": "image/png",
        "url": "https://app.formcrafts.com/protected/dashboard/file?id=0b40f670-6881-49c1-97e5-3fb4c70a317e"
      }
    ]
  }
}

For the Form method the data would be sent as key-value pairs, in this format:

response_id=1234&created_at=...

The data sent by JSON is more comprehensive and easier to work with.