2018-07-04 02:08:27 +02:00
|
|
|
# Incoming webhook integrations
|
|
|
|
|
2018-10-12 01:54:13 +02:00
|
|
|
An incoming webhook allows a third-party service to push data to Zulip when
|
2023-12-20 01:43:13 +01:00
|
|
|
something happens. There are several ways to set up an incoming webhook in
|
2019-05-21 04:17:11 +02:00
|
|
|
Zulip:
|
2018-07-04 02:08:27 +02:00
|
|
|
|
2019-05-21 04:17:11 +02:00
|
|
|
* Use our [REST API](/api/rest) endpoint for [sending
|
|
|
|
messages](/api/send-message). This works great for internal tools
|
|
|
|
or cases where the third-party tool wants to control the formatting
|
|
|
|
of the messages in Zulip.
|
2020-05-09 20:22:11 +02:00
|
|
|
* Use one of our supported [integration
|
2021-05-07 02:55:31 +02:00
|
|
|
frameworks](/integrations/meta-integration), such as the
|
2020-05-09 20:22:11 +02:00
|
|
|
[Slack-compatible incoming webhook](/integrations/doc/slack_incoming),
|
2023-12-20 01:43:13 +01:00
|
|
|
[Zapier integration](/integrations/doc/zapier), or
|
2020-05-09 20:22:11 +02:00
|
|
|
[IFTTT integration](/integrations/doc/ifttt).
|
2023-12-20 01:43:13 +01:00
|
|
|
* Implementing an incoming webhook integration (detailed on this page),
|
2019-05-21 04:17:11 +02:00
|
|
|
where all the logic for formatting the Zulip messages lives in the
|
|
|
|
Zulip server. This is how most of [Zulip's official
|
2023-03-23 03:47:14 +01:00
|
|
|
integrations](/integrations/) work, because they enable Zulip to
|
2019-05-21 04:17:11 +02:00
|
|
|
support third-party services that just have an "outgoing webhook"
|
|
|
|
feature (without the third party needing to do any work specific to
|
|
|
|
Zulip).
|
|
|
|
|
|
|
|
In an incoming webhook integration, the third-party service's
|
2023-12-20 01:43:13 +01:00
|
|
|
"outgoing webhook" feature sends an `HTTP POST` to a special URL when
|
2019-05-21 04:17:11 +02:00
|
|
|
it has something for you, and then the Zulip "incoming webhook"
|
|
|
|
integration handles that incoming data to format and send a message in
|
|
|
|
Zulip.
|
|
|
|
|
|
|
|
New official Zulip webhook integrations can take just a few hours to
|
|
|
|
write, including tests and documentation, if you use the right
|
|
|
|
process.
|
2018-07-04 02:08:27 +02:00
|
|
|
|
2018-10-12 01:54:13 +02:00
|
|
|
## Quick guide
|
|
|
|
|
|
|
|
* Set up the
|
|
|
|
[Zulip development environment](https://zulip.readthedocs.io/en/latest/development/overview.html).
|
|
|
|
|
2021-04-09 03:50:04 +02:00
|
|
|
* Use [Zulip's JSON integration](/integrations/doc/json),
|
|
|
|
<https://webhook.site/>, or a similar site to capture an example
|
2018-10-12 01:54:13 +02:00
|
|
|
webhook payload from the third-party service. Create a
|
2021-04-09 03:50:04 +02:00
|
|
|
`zerver/webhooks/<mywebhook>/fixtures/` directory, and add the
|
2023-12-20 01:43:13 +01:00
|
|
|
captured JSON payload as a test fixture.
|
2018-10-12 01:54:13 +02:00
|
|
|
|
2023-12-20 01:43:13 +01:00
|
|
|
* Create an `Integration` object, and add it to the `WEBHOOK_INTEGRATIONS`
|
|
|
|
list in `zerver/lib/integrations.py`. Search for `WebhookIntegration` in that
|
|
|
|
file to find an existing one to copy.
|
2018-10-12 01:54:13 +02:00
|
|
|
|
2023-12-20 01:43:13 +01:00
|
|
|
* Write a draft webhook handler in `zerver/webhooks/<mywebhook>/view.py`. There
|
|
|
|
are a lot of examples in the `zerver/webhooks/` directory that you can copy.
|
|
|
|
We recommend templating from a short one, like `zendesk`.
|
2018-10-12 01:54:13 +02:00
|
|
|
|
2023-12-20 01:43:13 +01:00
|
|
|
* Write a test for your fixture in `zerver/webhooks/<mywebhook>/tests.py`.
|
|
|
|
Run the test for your integration like this:
|
2018-07-04 02:08:27 +02:00
|
|
|
|
|
|
|
```
|
2018-10-12 01:54:13 +02:00
|
|
|
tools/test-backend zerver/webhooks/<mywebhook>/
|
2018-07-04 02:08:27 +02:00
|
|
|
```
|
|
|
|
|
2018-10-12 01:54:13 +02:00
|
|
|
Iterate on debugging the test and webhooks handler until it all
|
|
|
|
works.
|
|
|
|
|
|
|
|
* Capture payloads for the other common types of `POST`s the third-party
|
|
|
|
service will make, and add tests for them; usually this part of the
|
|
|
|
process is pretty fast.
|
|
|
|
|
2023-12-20 01:43:13 +01:00
|
|
|
* Document the integration in `zerver/webhooks/<mywebhook>/doc.md`(required for
|
|
|
|
getting it merged into Zulip). You can use existing documentation, like
|
|
|
|
[this one](https://raw.githubusercontent.com/zulip/zulip/main/zerver/webhooks/github/doc.md),
|
|
|
|
as a template. This should not take more than 15 minutes, even if you don't speak English
|
2018-10-12 01:54:13 +02:00
|
|
|
as a first language (we'll clean up the text before merging).
|
2018-07-04 02:08:27 +02:00
|
|
|
|
2018-10-12 01:54:13 +02:00
|
|
|
## Hello world walkthrough
|
2018-07-04 02:08:27 +02:00
|
|
|
|
2018-10-17 05:08:27 +02:00
|
|
|
Check out the [detailed walkthrough](incoming-webhooks-walkthrough) for step-by-step
|
2018-10-12 01:54:13 +02:00
|
|
|
instructions.
|
2018-07-04 02:08:27 +02:00
|
|
|
|
2018-10-12 01:54:13 +02:00
|
|
|
## Checklist
|
|
|
|
|
|
|
|
### Files that need to be created
|
2018-07-04 02:08:27 +02:00
|
|
|
|
|
|
|
Select a name for your incoming webhook and use it consistently. The examples
|
2018-10-12 01:54:13 +02:00
|
|
|
below are for a webhook named `MyWebHook`.
|
|
|
|
|
|
|
|
* `zerver/webhooks/mywebhook/__init__.py`: Empty file that is an obligatory
|
|
|
|
part of every python package. Remember to `git add` it.
|
2023-12-20 01:43:13 +01:00
|
|
|
* `zerver/webhooks/mywebhook/view.py`: The main webhook integration function,
|
|
|
|
called `api_mywebhook_webhook`, along with any necessary helper functions.
|
|
|
|
* `zerver/webhooks/mywebhook/fixtures/message_type.json`: Sample JSON payload data
|
2018-07-04 02:08:27 +02:00
|
|
|
used by tests. Add one fixture file per type of message supported by your
|
2018-10-12 01:54:13 +02:00
|
|
|
integration.
|
2022-02-08 00:13:33 +01:00
|
|
|
* `zerver/webhooks/mywebhook/tests.py`: Tests for your webhook.
|
2021-05-07 02:55:31 +02:00
|
|
|
* `zerver/webhooks/mywebhook/doc.md`: End-user documentation explaining
|
2018-10-12 01:54:13 +02:00
|
|
|
how to add the integration.
|
|
|
|
* `static/images/integrations/logos/mywebhook.svg`: A square logo for the
|
|
|
|
platform/server/product you are integrating. Used on the documentation
|
|
|
|
pages as well as the sender's avatar for messages sent by the integration.
|
2023-12-20 01:43:13 +01:00
|
|
|
* `static/images/integrations/mywebhook/001.png`: A screenshot of a message
|
2021-05-07 02:55:31 +02:00
|
|
|
sent by the integration, used on the documentation page. This can be
|
|
|
|
generated by running `tools/generate-integration-docs-screenshot --integration mywebhook`.
|
|
|
|
* `static/images/integrations/bot_avatars/mywebhook.png`: A square logo for the
|
|
|
|
platform/server/product you are integrating which is used to create the avatar
|
|
|
|
for generating screenshots with. This can be generated automatically from
|
|
|
|
`static/images/integrations/logos/mywebhook.svg` by running
|
|
|
|
`tools/setup/generate_integration_bots_avatars.py`.
|
2018-10-12 01:54:13 +02:00
|
|
|
|
|
|
|
### Files that need to be updated
|
2018-07-04 02:08:27 +02:00
|
|
|
|
|
|
|
* `zerver/lib/integrations.py`: Add your integration to
|
2018-10-12 01:54:13 +02:00
|
|
|
`WEBHOOK_INTEGRATIONS`. This will automatically register a
|
|
|
|
URL for the incoming webhook of the form `api/v1/external/mywebhook` and
|
|
|
|
associate it with the function called `api_mywebhook_webhook` in
|
2021-05-07 02:55:31 +02:00
|
|
|
`zerver/webhooks/mywebhook/view.py`. Also add your integration to
|
|
|
|
`DOC_SCREENSHOT_CONFIG`. This will allow you to automatically generate
|
|
|
|
a screenshot for the documentation by running
|
|
|
|
`tools/generate-integration-docs-screenshot --integration mywebhook`.
|
2018-10-17 03:51:53 +02:00
|
|
|
|
2021-05-06 16:02:36 +02:00
|
|
|
## Common Helpers
|
|
|
|
|
|
|
|
* If your integration will receive a test webhook payload, you can use
|
|
|
|
`get_setup_webhook_message` to create our standard message for test payloads.
|
|
|
|
You can import this from `zerver/lib/webhooks/common.py`, and it will generate
|
|
|
|
a message like this: "GitHub webhook is successfully configured! 🎉"
|
|
|
|
|
2018-10-17 03:51:53 +02:00
|
|
|
## General advice
|
|
|
|
|
|
|
|
* Consider using our Zulip markup to make the output from your
|
2023-12-20 01:43:13 +01:00
|
|
|
integration especially attractive or useful (e.g. emoji, Markdown
|
|
|
|
emphasis, or @-mentions).
|
2018-10-17 03:51:53 +02:00
|
|
|
|
|
|
|
* Use topics effectively to ensure sequential messages about the same
|
|
|
|
thing are threaded together; this makes for much better consumption
|
|
|
|
by users. E.g. for a bug tracker integration, put the bug number in
|
|
|
|
the topic for all messages; for an integration like Nagios, put the
|
|
|
|
service in the topic.
|
|
|
|
|
|
|
|
* Integrations that don't match a team's workflow can often be
|
|
|
|
uselessly spammy. Give careful thought to providing options for
|
|
|
|
triggering Zulip messages only for certain message types, certain
|
|
|
|
projects, or sending different messages to different streams/topics,
|
|
|
|
to make it easy for teams to configure the integration to support
|
|
|
|
their workflow.
|
|
|
|
|
|
|
|
* Consistently capitalize the name of the integration in the
|
|
|
|
documentation and the Client name the way the vendor does. It's OK
|
|
|
|
to use all-lower-case in the implementation.
|
|
|
|
|
|
|
|
* Sometimes it can be helpful to contact the vendor if it appears they
|
|
|
|
don't have an API or webhook we can use; sometimes the right API
|
|
|
|
is just not properly documented.
|
|
|
|
|
|
|
|
* A helpful tool for testing your integration is
|
|
|
|
[UltraHook](http://www.ultrahook.com/), which allows you to receive webhook
|
|
|
|
calls via your local Zulip development environment. This enables you to do end-to-end
|
|
|
|
testing with live data from the service you're integrating and can help you
|
|
|
|
spot why something isn't working or if the service is using custom HTTP
|
|
|
|
headers.
|
2023-11-01 14:24:27 +01:00
|
|
|
|
2024-03-21 17:37:57 +01:00
|
|
|
## URL specification
|
2023-11-01 14:24:27 +01:00
|
|
|
|
2024-03-21 17:37:57 +01:00
|
|
|
The base URL for an incoming webhook integration bot, where
|
2023-11-01 14:24:27 +01:00
|
|
|
`INTEGRATION_NAME` is the name of the specific webhook integration and
|
|
|
|
`API_KEY` is the API key of the bot created by the user for the
|
2024-03-21 17:37:57 +01:00
|
|
|
integration, is:
|
2023-11-01 14:24:27 +01:00
|
|
|
|
2024-03-21 17:37:57 +01:00
|
|
|
```
|
|
|
|
{{ api_url }}/v1/external/INTEGRATION_NAME?api_key=API_KEY
|
|
|
|
```
|
|
|
|
|
|
|
|
The list of existing webhook integrations can be found by browsing the
|
|
|
|
[Integrations documentation](/integrations/) or in
|
|
|
|
`zerver/lib/integrations.py` at `WEBHOOK_INTEGRATIONS`.
|
2023-11-01 14:24:27 +01:00
|
|
|
|
|
|
|
Parameters accepted in the URL include:
|
|
|
|
|
2024-03-21 17:37:57 +01:00
|
|
|
### api_key *(required)*
|
|
|
|
|
|
|
|
The API key of the bot created by the user for the integration. To get a
|
|
|
|
bot's API key, see the [API keys](/api/api-keys) documentation.
|
|
|
|
|
|
|
|
### stream
|
|
|
|
|
|
|
|
The stream for the integration to send notifications to. Can be either
|
|
|
|
the stream ID or the [URL-encoded][url-encoder] stream name. By default
|
|
|
|
the integration will send direct messages to the bot's owner.
|
|
|
|
|
|
|
|
!!! tip ""
|
|
|
|
|
|
|
|
A stream ID can be found when [browsing streams][browse-streams]
|
|
|
|
in the web app via the URL.
|
2023-11-01 14:24:27 +01:00
|
|
|
|
2024-03-21 17:37:57 +01:00
|
|
|
### topic
|
2023-11-01 14:24:27 +01:00
|
|
|
|
2024-03-21 17:37:57 +01:00
|
|
|
The topic in the specified stream for the integration to send
|
|
|
|
notifications to. The topic should also be [URL-encoded][url-encoder].
|
|
|
|
By default the integration will have a topic configured for stream
|
|
|
|
messages.
|
2023-11-28 18:12:31 +01:00
|
|
|
|
2024-03-21 17:37:57 +01:00
|
|
|
### only_events, exclude_events
|
2023-11-28 18:12:31 +01:00
|
|
|
|
2024-03-21 17:37:57 +01:00
|
|
|
Some incoming webhook integrations support these parameters to filter
|
|
|
|
which events will trigger a notification. You can append either
|
|
|
|
`&only_events=["event_a","event_b"]` or
|
|
|
|
`&exclude_events=["event_a","event_b"]` (or both, with different events)
|
|
|
|
to the URL, with an arbitrary number of supported events.
|
2023-11-01 14:24:27 +01:00
|
|
|
|
2024-03-21 17:37:57 +01:00
|
|
|
You can use UNIX-style wildcards like `*` to include multiple events.
|
|
|
|
For example, `test*` matches every event that starts with `test`.
|
2024-03-19 17:03:01 +01:00
|
|
|
|
2024-03-21 17:37:57 +01:00
|
|
|
!!! tip ""
|
2024-03-19 17:03:01 +01:00
|
|
|
|
2024-03-21 17:37:57 +01:00
|
|
|
For a list of supported events, see a specific [integration's
|
|
|
|
documentation](/integrations) page.
|
2023-11-01 14:24:27 +01:00
|
|
|
|
2023-11-28 18:12:31 +01:00
|
|
|
[browse-streams]: /help/browse-and-subscribe-to-streams
|
2023-11-01 14:24:27 +01:00
|
|
|
[add-bot]: /help/add-a-bot-or-integration
|
|
|
|
[url-encoder]: https://www.urlencoder.org/
|
2024-02-10 00:10:17 +01:00
|
|
|
|
|
|
|
## Related articles
|
|
|
|
|
|
|
|
* [Integrations overview](/api/integrations-overview)
|
|
|
|
* [Incoming webhook walkthrough](/api/incoming-webhooks-walkthrough)
|
|
|
|
* [Non-webhook integrations](/api/non-webhook-integrations)
|