Raven

Raven

Open in ChatGPT
Ask ChatGPT about this page
Open in Claude
Ask Claude about this page

Webhooks

A webhook sends a request to another system when something happens in Raven, such as a new message or a new channel. Set them up in Settings > Webhooks.

To post into Raven from another system, use an incoming webhook instead.

Create a webhook

  1. Open Settings > Webhooks.
  2. Click Create.
  3. Fill in the General tab.
  4. If you like, add a condition on the Conditions tab.
  5. On the Data tab, pick the fields to send.
  6. If the other system needs them, add headers on the Headers tab.
  7. Click Create.

A new webhook in Settings

Set up the Data and Headers tabs before you click Create.

General

Field What it does
Name A name for the webhook. It can't be changed after you create the webhook.
Request URL The URL Raven sends the request to. Up to 140 characters.
Request Timeout How many seconds Raven waits for a response. The default is 5.
Trigger Event The event that sends the request. It can't be changed after you create the webhook.
Enable Security? Signs each request with a secret. See Check the signature below.
Webhook Secret The secret used to sign requests. Shows when Enable Security? is on.

Trigger events

Trigger Event Sent when
Message Sent A message is posted.
Message Edited A message is edited.
Message Deleted A message is deleted.
Message Reacted On Someone adds a reaction to a message.
Channel Created A channel is created.
Channel Deleted A channel is deleted.
User Added A user is added to Raven. Creating an agent counts too.
User Deleted A Raven user is deleted.

Conditions

Turn on Trigger this webhook based on a condition to send the request only for some events. Then pick a field in Trigger On.

The Conditions tab

Trigger On What it checks Works with
Channel The message was posted in this channel. Message Sent, Message Edited, Message Deleted
User The message or reaction was sent by this user. Message Sent, Message Edited, Message Deleted, Message Reacted On
Channel Type The channel is Public, Private, Open, a direct message or a self message. Channel Created, Channel Deleted
Custom A Python expression you write. The request is sent when it is true. Every trigger event

In a custom condition, doc is the record that changed. For example:

doc.channel_id == "lumen-cycles-support"
doc.owner == "maya@lumencycles.com"

Data

Click Add and pick a field to send. Each field is sent under its field name, shown in the Key column. The list of fields depends on the trigger event.

Click the info button on a row to see what the field holds. Click Preview and pick an example to see the request body.

Headers

Click Add to send a header with each request. Enter a Key and a Value. A header with no value is not sent.

Raven does not set a Content-Type header. If the other system needs one, add Content-Type with the value application/json.

The request

Raven sends a POST request. The body is a JSON object with the fields from the Data tab. For Message Sent with the fields channel_id, owner and text, the body looks like this:

{
 "channel_id": "lumen-cycles-support",
 "owner": "maya@lumencycles.com",
 "text": "<p>The rear hub on order 4127 is back in stock.</p>"
}

Message text is HTML.

If the request fails, Raven tries again up to 3 times: after 5 minutes, 30 minutes and 2 hours. Every request is logged in Desk, under Webhook Request Log.

Check the signature

With Enable Security? on, each request has an X-Frappe-Webhook-Signature header. Raven computes it like this:

  1. Take the request body, exactly as sent, as UTF-8 bytes.
  2. Compute its HMAC-SHA256, with the webhook secret as the key.
  3. Encode the result in base64.

To check a request, do the same with the raw body you received and compare the two values. Do not parse the JSON and encode it again first, because the bytes may change.

This receiver uses Flask. It checks the signature, then reads the fields:

import base64
import hashlib
import hmac
import json

from flask import Flask, abort, request

app = Flask(__name__)
WEBHOOK_SECRET = "the secret you entered in Raven"


@app.post("/raven")
def raven_webhook():
	raw_body = request.get_data()
	digest = hmac.new(WEBHOOK_SECRET.encode("utf8"), raw_body, hashlib.sha256).digest()
	expected = base64.b64encode(digest).decode()
	received = request.headers.get("X-Frappe-Webhook-Signature", "")

	if not hmac.compare_digest(expected, received):
		abort(401)

	# Raven sends no Content-Type header, so parse the body yourself.
	data = json.loads(raw_body)
	print(data.get("channel_id"), data.get("text"))
	return "", 204

Reply with a 2xx status. A 4xx or 5xx status, or no reply within the timeout, counts as a failure, and Raven tries again later.

Delete a webhook

  1. Open Settings > Webhooks and click the webhook.
  2. Click ⋮ next to Save.
  3. Click Delete, then confirm.
Last updated 1 week ago
Was this helpful?
Thanks!