Unthread provides webhooks which allow you to receive HTTP POST requests when data is created or updated.

Configuration

Create an HTTP endpoint capable of receiving and responding to POST requests containing JSON payloads. The endpoint must be publicly accessible and must use HTTPS. The endpoint should respond with a 200 status code within 30 seconds of receiving a request.

URL Verification

When the endpoint URL is given to Unthread, Unthread will emit a “url_verification” event. Your endpoint must respond to this request with a 200 status code within 3 seconds.

Security

To ensure security, your endpoint should validate that event payloads are signed with the signing secret available from the Unthread dashboard. This ensures that the events are coming from Unthread and not from a malicious source. Create an HMAC-SHA256 hash of the request body using the singing secret as the key and compare it to the signature included in the “X-Unthread-Signature” HTTP header. If the two values match, then the signature is considered valid.

Payload

Events will have the following structure:

{
  "event": "conversation_created", // The event type.
  "eventId": "49bac55d-5445-4e70-ad72-c87e2e8adb3f", // Unique ID for the event.
  "eventTimestamp": 1678732685142, // When the event took place, in milliseconds.
  "webhookTimestamp": 1678732685382, // When the event was sent, in milliseconds.
  "data": {
    // The event data, depends on the event type.
    "id": "b72c8bcd-0387-4a6d-92b3-14016c3c53e5"
  }
}

The following event types are supported:

  • 'conversation_created'
  • 'conversation_updated'
  • 'conversation_deleted'
  • 'message_created'

Retries

If the endpoint returns a status code other than 200 or it times out, the event will be retried up to 4 more times at increasing intervals. An “X-Unthread-Attempt-Number” HTTP header starting at 1 is included in every request to identify when a retry is occurring. If an endpoint fails consecutively more than 100 times or returns a 410 status code, it will be disabled automatically.

It is possible, though unlikely, that an event will be resent after succeeding. Your endpoint should be prepared to handle this case gracefully using the “eventId” property.

Examples

const { createHmac } = require('crypto');

// Example of how to get the rawBody property if using express:
/***
app.use(
  express.json({
    verify: (req, res, buf) => {
      req.rawBody = buf.toString();
    }
  })
);
***/

// Replace the value here with one obtained from your Unthread dashboard.
const SIGNING_SECRET = 'your_signing_secret_here';

function verifySignature(req) {
  // It's recommended to use raw request body content in the hash since JSON parsing might change it.
  const rawBody = req.rawBody;
	const hmac = createHmac('sha256', SIGNING_SECRET).update(rawBody).digest('hex');

	return return mac === req.get('x-unthread-signature');
}

function webhookHandler(req, res) {
	if (!verifySignature(req)) {
		res.sendStatus(403);
		return;
  }

	const { event, data } = req.body;

  if (event === 'url_verification') {
    // Respond within 3 seconds.
    res.status(200);
    return;
  }

  // Handle other event types here.

  // Default to returning 200.
	res.sendStatus(200);
}
import hashlib

# Replace the value here with one obtained from your Unthread dashboard.
SIGNING_SECRET = 'your_signing_secret_here'

def verify_signature(request):
    hmac = hashlib.sha256(SIGNING_SECRET.encode('utf-8'), request.get_data(), digestmod=hashlib.sha256).hexdigest()

    return hmac == request.headers.get('x-unthread-signature')

@app.route('/webhook', methods=['POST'])
def webhook():
    if not verify_signature(request):
        return 'Invalid signature', 403

    body = request.get_json()
    event = body.get('event')

    if event == 'url_verification':
        # Respond within 3 seconds.
        return 'OK', 200

		# Handle other event types here.

    # Default to returning 200.
    return 'OK', 200

Zapier

A webhook trigger is available as part of Unthread’s integration with Zapier. You will need to create a connection to Unthread using your Unthread API key and you will also need to provide your webhook signing secret. The Zapier integration will automatically configure your webhook within Unthread. The integration will automatically validate webhook event signatures and ignore any events with invalid signatures.

Make (Integromat)

A webhook trigger is available as part of Unthread’s integration with Make. You will need to create a connection to Unthread using your Unthread API key and you will also need to provide your webhook signing secret. The Zapier integration will automatically configure your webhook within Unthread. The integration will NOT automatically validate webhook event signatures however it is possible to configure your scenario to validate the signature. Add a “Transform to JSON” step and pass in the “payload” property from the Unthread webhook step. Then add a “Webhook Response” step with the following expression in the “Status” field: if(sha256(<json property from transform step>; "hex"; <signingSecret property from webhook step>) = <signature property from webhook step>; 200; 403). This will return a 403 status code if the signature is invalid.