Build a Webhook with Python

In order to build your webhook faster, we provide a Python micro-framework to let you focus on your webhook functionalities.

🚧

Read Webhooks reference first!

Before following this guide, please ensure you have read the introduction of the Webhooks reference first. It will help you understand how it work.

Installation

You can install this framework like any other python packages using pip :

pip install clustaar.webhook

Webhook Basics

Activation in a step

Simply activate the use webhook toggle in the desired step:

995

Minimal code example

Here is a webhook that will trigger an handler function each times it receives a conversation.step_reached event.

from clustaar.webhook import Webhook, events
from clustaar.schemas.models import StepReachedResponse, ConversationSession

def handler(request, response, notification):
    session = ConversationSession(values={"name": "John"})
    return StepReachedResponse(actions=[], session=session)


app = Webhook()
app.on(events.CONVERSATION_STEP_REACHED, handler)

Return Actions

Most of the time, you will want to return actions. The simplest case being to return actions as they were configured in the step.

from clustaar.webhook import Webhook, events
from clustaar.schemas.models import StepReachedResponse, ConversationSession

def handler(request, response, notification):
    session = notification.event.session
    actions = notification.event.step.actions # an array of actions

    return StepReachedResponse(actions=actions, session=session)


app = Webhook()
app.on(events.CONVERSATION_STEP_REACHED, handler)

And if you want to build your own actions or session, you will have to use clustaar.schemas:

from clustaar.webhook import Webhook, events
from clustaar.schemas.models import StepReachedResponse, ConversationSession, SendTextAction

def handler(request, response, notification):
    session_value = notification.event.session.values.get("key", None) # get a session value

    notification.event.session.values["key"] = "data" # update or create a session value
    session = ConversationSession(values={"name": "John"}) # or create a new session and erase the previous

    text_action = SendTextAction(alternatives=["hello", "bye"])

    return StepReachedResponse(actions=[text_action], session=session)


app = Webhook()
app.on(events.CONVERSATION_STEP_REACHED, handler)

Routing

Event

Routing is achieved by specifying an event name to the on() method while configuring your webhook :

app.on(events.CONVERSATION_STEP_REACHED, handler)

Filters

If you want to add some condition to route events based on the request received you can use filters.

In this example, handler will receive the requests only when the event is of type events.CONVERSATION_STEP_REACHED and the value of the JSON key data.step.id equals "507f191e810c19729de860ea" :

from clustaar.webhook.filters import JSONKeyEquals
app.on(events.CONVERSATION_STEP_REACHED,
       handler,
       filters=JSONKeyEquals("data.step.id", "507f191e810c19729de860ea"))

JSONKeyEquals

Validates that a JSON key equals an expected value.

data = {
    "user": {
        "id": 1
    }
}
filter = JSONKeyEquals("user.id", 1)
assert filter(data)
data["user"]["id"] = 2
assert not filter(data)

JSONKeyIn

Validates that a key is present in a defined set of values.

data = {
    "user": {
        "id": 1
    }
}
filter = JSONKeyIn("user.id", [1, 2])
assert filter(data)
data["user"]["id"] = 2
assert filter(data)
data["user"]["id"] = 3
assert not filter(data)

JSONKeyExists

Validates that a JSON key is present.

data = {
    "user": {
        "id": 1
    }
}
filter = JSONKeyExists("user.id")
assert filter(data)
del data["user"]["id"]
assert not filter(data)

StepID

Validates that the data.step.id matches the expected id.

data = {
	"data": {
	    "step": {
	        "id": "507f191e810c19729de860ea"
	    }
    }
}
filter = StepID("507f191e810c19729de860ea")
assert filter(data)
del data["data"]["step"]["id"]
assert not filter(data)

If you pass a list of step IDs to the StepID filter it will validate the the data.step.id is present in the list.

Security

Request signature

If you want to validate the signature of the requests sent by clustaar, you need to provide a private key.
This private key must be set in your bot's webhook configuration.

app = Webhook(private_key="XXXXXXXXXX")

Authentication

If you want to add some authentication to your application you can pass the HTTP basic authentication credentials that you defined in your webhook configuration.

app = Webhook(auth_username="XXXXXXXXXX", auth_password="YYYYYYYYY")