mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	docs: Rename "webhooks" to "incoming webhooks".
I only renamed references that I thought were absolutely necessary and only if the resulting sentence structure wasn't awkward. If the renaming resulted in awkward structure, I replaced the term "webhook" with "integration" (but only in some very obvious cases). Fixes #9500.
This commit is contained in:
		@@ -25,7 +25,7 @@ paths will be familiar to Django developers.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
* `zerver/views/*.py` Most [Django views](https://docs.djangoproject.com/en/1.8/topics/http/views/).
 | 
					* `zerver/views/*.py` Most [Django views](https://docs.djangoproject.com/en/1.8/topics/http/views/).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* `zerver/webhooks/` Webhook views and tests for [Zulip webhook integrations](
 | 
					* `zerver/webhooks/` Webhook views and tests for [Zulip's incoming webhook integrations](
 | 
				
			||||||
  https://zulipchat.com/api/integration-guide).
 | 
					  https://zulipchat.com/api/integration-guide).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* `zerver/tornado/views.py` Tornado views.
 | 
					* `zerver/tornado/views.py` Tornado views.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,4 +35,4 @@ object as `request.client`.
 | 
				
			|||||||
In most integrations, `request.client` is then passed to
 | 
					In most integrations, `request.client` is then passed to
 | 
				
			||||||
`check_send_stream_message`, where it is used to keep track of which client
 | 
					`check_send_stream_message`, where it is used to keep track of which client
 | 
				
			||||||
sent the message (which in turn is used by analytics). For more
 | 
					sent the message (which in turn is used by analytics). For more
 | 
				
			||||||
information, see [the webhook walkthrough](https://zulipchat.com/api/webhook-walkthrough).
 | 
					information, see [the incoming webhook walkthrough](https://zulipchat.com/api/webhook-walkthrough).
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -181,9 +181,9 @@ The [three different integration models](https://zulipchat.com/api/integration-g
 | 
				
			|||||||
basically differ in where they perform the main functions of a
 | 
					basically differ in where they perform the main functions of a
 | 
				
			||||||
**World Reader**.
 | 
					**World Reader**.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### Webhook integrations
 | 
					#### Incoming webhook integrations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
In a **webhook** integration, the deployment model is usually this::
 | 
					In an **incoming webhook** integration, the deployment model is usually this::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**3rd party hardware**:
 | 
					**3rd party hardware**:
 | 
				
			||||||
- detect event
 | 
					- detect event
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -88,7 +88,7 @@ Note the `zh-hans` prefix--that url pattern gets added by `i18n_patterns`.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Our example is a REST API endpoint. It's a PUT to `/users`.
 | 
					Our example is a REST API endpoint. It's a PUT to `/users`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
With the exception of Webhooks (which we do not usually control the
 | 
					With the exception of incoming webhooks (which we do not usually control the
 | 
				
			||||||
format of), legacy endpoints, and logged-out endpoints, Zulip uses REST
 | 
					format of), legacy endpoints, and logged-out endpoints, Zulip uses REST
 | 
				
			||||||
for its API. This means that we use:
 | 
					for its API. This means that we use:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -154,7 +154,7 @@ mind. They are used extensively by the web client, and use POST.
 | 
				
			|||||||
You can see them in
 | 
					You can see them in
 | 
				
			||||||
[zproject/legacy_urls.py](https://github.com/zulip/zulip/blob/master/zproject/legacy_urls.py).
 | 
					[zproject/legacy_urls.py](https://github.com/zulip/zulip/blob/master/zproject/legacy_urls.py).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Webhook integrations may not be RESTful
 | 
					### Incoming webhook integrations may not be RESTful
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Zulip endpoints that are called by other services for integrations have
 | 
					Zulip endpoints that are called by other services for integrations have
 | 
				
			||||||
to conform to the service's request format. They are likely to use
 | 
					to conform to the service's request format. They are likely to use
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -345,9 +345,9 @@ These endpoints make use of some older authentication decorators,
 | 
				
			|||||||
`authenticated_json_api_view`, `authenticated_json_post_view`, and
 | 
					`authenticated_json_api_view`, `authenticated_json_post_view`, and
 | 
				
			||||||
`authenticated_json_view`, so you may see them in the code.
 | 
					`authenticated_json_view`, so you may see them in the code.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Webhook integration endpoints
 | 
					## Incoming webhook integrations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Webhooks are called by other services, often to send a message as part
 | 
					Incoming webhooks are called by other services, often to send a message as part
 | 
				
			||||||
of those services' integrations. They are most often POST requests, and
 | 
					of those services' integrations. They are most often POST requests, and
 | 
				
			||||||
often there is very little you can customize about them. Usually you can
 | 
					often there is very little you can customize about them. Usually you can
 | 
				
			||||||
expect that the webhook for a service will allow specification for the
 | 
					expect that the webhook for a service will allow specification for the
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,7 +10,7 @@ guide should help you find the API you need:
 | 
				
			|||||||
  Zulip's native integrations with Zapier and IFTTT often allow
 | 
					  Zulip's native integrations with Zapier and IFTTT often allow
 | 
				
			||||||
  integrating a new service with Zulip without writing any code.
 | 
					  integrating a new service with Zulip without writing any code.
 | 
				
			||||||
* If you'd like to send content into Zulip, you can
 | 
					* If you'd like to send content into Zulip, you can
 | 
				
			||||||
  [write a native incoming webhook integration](/api/integration-guide#webhook-integrations)
 | 
					  [write a native incoming webhook integration](/api/integration-guide#incoming-webhook-integrations)
 | 
				
			||||||
  or use [Zulip's API for sending messages](/api/stream-message).
 | 
					  or use [Zulip's API for sending messages](/api/stream-message).
 | 
				
			||||||
* If you're building an interactive bot that reacts to activity inside
 | 
					* If you're building an interactive bot that reacts to activity inside
 | 
				
			||||||
  Zulip, you'll want to look at Zulip's
 | 
					  Zulip, you'll want to look at Zulip's
 | 
				
			||||||
@@ -19,4 +19,3 @@ guide should help you find the API you need:
 | 
				
			|||||||
* If you'd like to do something else, check out the full
 | 
					* If you'd like to do something else, check out the full
 | 
				
			||||||
  [REST API](/api/rest), generally starting with
 | 
					  [REST API](/api/rest), generally starting with
 | 
				
			||||||
  [installing the API client bindings](/api/installation-instructions).
 | 
					  [installing the API client bindings](/api/installation-instructions).
 | 
				
			||||||
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,9 +30,9 @@ Usually, this involves a few steps:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
* Finally, generate a message sent by the integration and take a
 | 
					* Finally, generate a message sent by the integration and take a
 | 
				
			||||||
  screenshot of the message to provide an example message in the
 | 
					  screenshot of the message to provide an example message in the
 | 
				
			||||||
  documentation. If your new integration is a webhook integration,
 | 
					  documentation. If your new integration is an incoming webhook
 | 
				
			||||||
  you can generate such a message from your test fixtures
 | 
					  integration, you can generate such a message from your test
 | 
				
			||||||
  using `send_webhook_fixture_message`:
 | 
					  fixtures using `send_webhook_fixture_message`:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ```
 | 
					  ```
 | 
				
			||||||
  ./manage.py send_webhook_fixture_message \
 | 
					  ./manage.py send_webhook_fixture_message \
 | 
				
			||||||
@@ -61,13 +61,13 @@ Here are a few common macros used to document Zulip's integrations:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
* `{!create-stream.md!}` macro - Recommends that users create a dedicated
 | 
					* `{!create-stream.md!}` macro - Recommends that users create a dedicated
 | 
				
			||||||
  stream for a given integration. Usually the first step in setting up an
 | 
					  stream for a given integration. Usually the first step in setting up an
 | 
				
			||||||
  integration or webhook. For an example rendering, see **Step 1** of
 | 
					  integration or incoming webhook. For an example rendering, see **Step 1** of
 | 
				
			||||||
  [the docs for Zulip's GitHub integration][GitHub].
 | 
					  [the docs for Zulip's GitHub integration][GitHub].
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* `{!create-bot-construct-url.md!}` macro - Instructs users to create a bot
 | 
					* `{!create-bot-construct-url.md!}` macro - Instructs users to create a bot
 | 
				
			||||||
  for a given integration and construct a webhook URL using the bot API key
 | 
					  for a given integration and construct a webhook URL using the bot API key
 | 
				
			||||||
  and stream name. The URL is generated automatically for every webhook by using
 | 
					  and stream name. The URL is generated automatically for every incoming webhook
 | 
				
			||||||
  attributes in the [WebhookIntegration][1] class.
 | 
					  by using attributes in the [WebhookIntegration][1] class.
 | 
				
			||||||
  This macro is usually used right after `{!create-stream!}`. For an example
 | 
					  This macro is usually used right after `{!create-stream!}`. For an example
 | 
				
			||||||
  rendering, see **Step 2** of [the docs for Zulip's GitHub integration][GitHub].
 | 
					  rendering, see **Step 2** of [the docs for Zulip's GitHub integration][GitHub].
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,7 +11,7 @@ On this page you'll find:
 | 
				
			|||||||
* An overview of the different [types of integrations](#types-of-integrations)
 | 
					* An overview of the different [types of integrations](#types-of-integrations)
 | 
				
			||||||
  possible with Zulip.
 | 
					  possible with Zulip.
 | 
				
			||||||
* [General advice](#general-advice) for writing integrations.
 | 
					* [General advice](#general-advice) for writing integrations.
 | 
				
			||||||
* Details about writing [webhook integrations](#webhook-integrations).
 | 
					* Details about writing [incoming webhook integrations](#incoming-webhook-integrations).
 | 
				
			||||||
* Details about writing [Python script and plugin
 | 
					* Details about writing [Python script and plugin
 | 
				
			||||||
  integrations](#python-script-and-plugin-integrations).
 | 
					  integrations](#python-script-and-plugin-integrations).
 | 
				
			||||||
* A guide to
 | 
					* A guide to
 | 
				
			||||||
@@ -19,7 +19,7 @@ On this page you'll find:
 | 
				
			|||||||
  separate page.
 | 
					  separate page.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
A detailed walkthrough of a simple "Hello World" integration can be
 | 
					A detailed walkthrough of a simple "Hello World" integration can be
 | 
				
			||||||
found in the [webhook walkthrough](webhook-walkthrough).
 | 
					found in the [incoming webhook walkthrough](webhook-walkthrough).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Contributions to this guide are very welcome, so if you run into any
 | 
					Contributions to this guide are very welcome, so if you run into any
 | 
				
			||||||
issues following these instructions or come up with any tips or tools
 | 
					issues following these instructions or come up with any tips or tools
 | 
				
			||||||
@@ -32,7 +32,7 @@ to share your ideas!
 | 
				
			|||||||
We have several different ways that we integrate with 3rd party
 | 
					We have several different ways that we integrate with 3rd party
 | 
				
			||||||
products, ordered here by which types we prefer to write:
 | 
					products, ordered here by which types we prefer to write:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
1. **[Webhook integrations](#webhook-integrations)** (examples:
 | 
					1. **[Incoming webhook integrations](#incoming-webhook-integrations)** (examples:
 | 
				
			||||||
   Freshdesk, GitHub), where the third-party service supports posting
 | 
					   Freshdesk, GitHub), where the third-party service supports posting
 | 
				
			||||||
   content to a particular URI on our site with data about the event.
 | 
					   content to a particular URI on our site with data about the event.
 | 
				
			||||||
   For these, you usually just need to create a new python package in
 | 
					   For these, you usually just need to create a new python package in
 | 
				
			||||||
@@ -86,11 +86,11 @@ products, ordered here by which types we prefer to write:
 | 
				
			|||||||
  spot why something isn't working or if the service is using custom HTTP
 | 
					  spot why something isn't working or if the service is using custom HTTP
 | 
				
			||||||
  headers.
 | 
					  headers.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Webhook integrations
 | 
					## Incoming webhook integrations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
A webhook allows a third-party service to push data to you when something
 | 
					An incoming webhook allows a third-party service to push data to you when something
 | 
				
			||||||
happens. It's different from making a REST API call, where you send a request
 | 
					happens. It's different from making a REST API call, where you send a request
 | 
				
			||||||
to the service's API and wait for a response. With a webhook, the third-party
 | 
					to the service's API and wait for a response. With an incoming webhook, the third-party
 | 
				
			||||||
service sends you an HTTP POST when it has something for you. Your webhook
 | 
					service sends you an HTTP POST when it has something for you. Your webhook
 | 
				
			||||||
integration defines the URI the service uses to communicate with Zulip, and
 | 
					integration defines the URI the service uses to communicate with Zulip, and
 | 
				
			||||||
handles that incoming data.
 | 
					handles that incoming data.
 | 
				
			||||||
@@ -133,7 +133,7 @@ For a quick guide, read on.
 | 
				
			|||||||
    [this guide](https://zulip.readthedocs.io/en/latest/testing/testing.html)
 | 
					    [this guide](https://zulip.readthedocs.io/en/latest/testing/testing.html)
 | 
				
			||||||
    for more details on the Zulip test runner.*
 | 
					    for more details on the Zulip test runner.*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* Once you've gotten your webhook working and passing a test, capture
 | 
					* Once you've gotten your incoming webhook working and passing a test, capture
 | 
				
			||||||
    payloads for the other common types of posts the service's webhook
 | 
					    payloads for the other common types of posts the service's webhook
 | 
				
			||||||
    will make, and add tests for them; usually this part of the
 | 
					    will make, and add tests for them; usually this part of the
 | 
				
			||||||
    process is pretty fast.  Webhook integration tests should all use
 | 
					    process is pretty fast.  Webhook integration tests should all use
 | 
				
			||||||
@@ -146,8 +146,8 @@ For a quick guide, read on.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
### Files that need to be created
 | 
					### Files that need to be created
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Select a name for your webhook and use it consistently. The examples below are
 | 
					Select a name for your incoming webhook and use it consistently. The examples
 | 
				
			||||||
for a webhook named 'MyWebHook'.
 | 
					below are for a webhook named 'MyWebHook'.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* `static/images/integrations/logos/mywebhook.svg`: An image to represent
 | 
					* `static/images/integrations/logos/mywebhook.svg`: An image to represent
 | 
				
			||||||
  your integration in the user interface. Generally this should be the logo of the
 | 
					  your integration in the user interface. Generally this should be the logo of the
 | 
				
			||||||
@@ -175,7 +175,7 @@ for a webhook named 'MyWebHook'.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
* `zerver/lib/integrations.py`: Add your integration to
 | 
					* `zerver/lib/integrations.py`: Add your integration to
 | 
				
			||||||
`WEBHOOK_INTEGRATIONS` to register it.  This will automatically
 | 
					`WEBHOOK_INTEGRATIONS` to register it.  This will automatically
 | 
				
			||||||
register a url for the webhook of the form `api/v1/external/mywebhook`
 | 
					register a url for the incoming webhook of the form `api/v1/external/mywebhook`
 | 
				
			||||||
and associate with the function called `api_mywebhook_webhook` in
 | 
					and associate with the function called `api_mywebhook_webhook` in
 | 
				
			||||||
`zerver/webhooks/mywebhook/view.py`.
 | 
					`zerver/webhooks/mywebhook/view.py`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,9 +3,9 @@
 | 
				
			|||||||
* [Overview](/api/integration-guide)
 | 
					* [Overview](/api/integration-guide)
 | 
				
			||||||
* [Existing integrations](/integrations)
 | 
					* [Existing integrations](/integrations)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Writing webhook integrations
 | 
					## Incoming webhooks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* [Overview](/api/integration-guide#webhook-integrations)
 | 
					* [Overview](/api/integration-guide#incoming-webhook-integrations)
 | 
				
			||||||
* [Walkthrough](/api/webhook-walkthrough)
 | 
					* [Walkthrough](/api/webhook-walkthrough)
 | 
				
			||||||
* [Documenting integrations](/api/integration-docs-guide)
 | 
					* [Documenting integrations](/api/integration-docs-guide)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
# Webhook walkthrough
 | 
					# Incoming webhook walkthrough
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Below, we explain each part of a simple webhook integration, called
 | 
					Below, we explain each part of a simple incoming webhook integration,
 | 
				
			||||||
**Hello World**.  This webhook sends a "hello" message to the `test`
 | 
					called **Hello World**.  This integration sends a "hello" message to the `test`
 | 
				
			||||||
stream and includes a link to the Wikipedia article of the day, which
 | 
					stream and includes a link to the Wikipedia article of the day, which
 | 
				
			||||||
it formats from json data it receives in the http request.
 | 
					it formats from json data it receives in the http request.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -10,7 +10,7 @@ integration.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
## Step 0: Create fixtures
 | 
					## Step 0: Create fixtures
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The first step in creating a webhook is to examine the data that the
 | 
					The first step in creating an incoming webhook is to examine the data that the
 | 
				
			||||||
service you want to integrate will be sending to Zulip.
 | 
					service you want to integrate will be sending to Zulip.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You can use <http://requestb.in> or a similar tool to capture
 | 
					You can use <http://requestb.in> or a similar tool to capture
 | 
				
			||||||
@@ -25,8 +25,9 @@ A test fixture is a small file containing test data, one for each test.
 | 
				
			|||||||
Fixtures enable the testing of webhook integration code without the need to
 | 
					Fixtures enable the testing of webhook integration code without the need to
 | 
				
			||||||
actually contact the service being integrated.
 | 
					actually contact the service being integrated.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Because `Hello World` is a very simple webhook that does one thing, it requires
 | 
					Because `Hello World` is a very simple integration that does one
 | 
				
			||||||
only one fixture, `zerver/webhooks/helloworld/fixtures/hello.json`:
 | 
					thing, it requires only one fixture,
 | 
				
			||||||
 | 
					`zerver/webhooks/helloworld/fixtures/hello.json`:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -35,8 +36,8 @@ only one fixture, `zerver/webhooks/helloworld/fixtures/hello.json`:
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
When writing your own webhook integration, you'll want to write a test function
 | 
					When writing your own incoming webhook integration, you'll want to write a test function
 | 
				
			||||||
for each distinct message condition your webhook supports. You'll also need a
 | 
					for each distinct message condition your integration supports. You'll also need a
 | 
				
			||||||
corresponding fixture for each of these tests. Depending on the type of data
 | 
					corresponding fixture for each of these tests. Depending on the type of data
 | 
				
			||||||
the 3rd party service sends, your fixture may contain JSON, URL encoded text, or
 | 
					the 3rd party service sends, your fixture may contain JSON, URL encoded text, or
 | 
				
			||||||
some other kind of data. See [Step 4: Create tests](#step-4-create-tests) or
 | 
					some other kind of data. See [Step 4: Create tests](#step-4-create-tests) or
 | 
				
			||||||
@@ -52,7 +53,7 @@ to create an empty `__init__.py` file in that directory via e.g.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
## Step 2: Create main webhook code
 | 
					## Step 2: Create main webhook code
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The majority of the code for your webhook integration will be in a single
 | 
					The majority of the code for your new integration will be in a single
 | 
				
			||||||
python file, `zerver/webhooks/mywebhook/view.py`.
 | 
					python file, `zerver/webhooks/mywebhook/view.py`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The Hello World integration is in `zerver/webhooks/helloworld/view.py`:
 | 
					The Hello World integration is in `zerver/webhooks/helloworld/view.py`:
 | 
				
			||||||
@@ -99,20 +100,22 @@ access request variables with `REQ()`. You can find more about `REQ` and request
 | 
				
			|||||||
variables in [Writing views](
 | 
					variables in [Writing views](
 | 
				
			||||||
https://zulip.readthedocs.io/en/latest/tutorials/writing-views.html#request-variables).
 | 
					https://zulip.readthedocs.io/en/latest/tutorials/writing-views.html#request-variables).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You must pass the name of your webhook to the `api_key_only_webhook_view`
 | 
					You must pass the name of your integration to the
 | 
				
			||||||
decorator so your webhook can access the `user_profile` and `request.client`
 | 
					`api_key_only_webhook_view` decorator; that name will be used to
 | 
				
			||||||
(Zulip's analogue of UserAgent) fields from the request. Here we have used
 | 
					describe your integration in Zulip's analytics (e.g. the `/stats`
 | 
				
			||||||
`HelloWorld`. To be consistent with Zulip code style, use the name of the
 | 
					page). Here we have used `HelloWorld`. To be consistent with other
 | 
				
			||||||
product you are integrating in camel case, spelled as the product spells
 | 
					integrations, use the name of the product you are integrating in camel
 | 
				
			||||||
its own name (except always first letter upper-case).
 | 
					case, spelled as the product spells its own name (except always first
 | 
				
			||||||
 | 
					letter upper-case).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The `api_key_only_webhook_view` decorator indicates that the 3rd party service will
 | 
					The `api_key_only_webhook_view` decorator indicates that the 3rd party service will
 | 
				
			||||||
send the authorization as an API key in the query parameters. If your service uses
 | 
					send the authorization as an API key in the query parameters. If your service uses
 | 
				
			||||||
HTTP Basic authentication, you would instead use the `authenticated_rest_api_view`
 | 
					HTTP Basic authentication, you would instead use the `authenticated_rest_api_view`
 | 
				
			||||||
decorator.
 | 
					decorator.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You should name your webhook function as such `api_webhookname_webhook` where
 | 
					You should name your webhook function as such
 | 
				
			||||||
`webhookname` is the name of your webhook and is always lower-case.
 | 
					`api_webhookname_webhook` where `webhookname` is the name of your
 | 
				
			||||||
 | 
					integration and is always lower-case.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
At minimum, the webhook function must accept `request` (Django
 | 
					At minimum, the webhook function must accept `request` (Django
 | 
				
			||||||
[HttpRequest](https://docs.djangoproject.com/en/1.8/ref/request-response/#django.http.HttpRequest)
 | 
					[HttpRequest](https://docs.djangoproject.com/en/1.8/ref/request-response/#django.http.HttpRequest)
 | 
				
			||||||
@@ -151,8 +154,8 @@ Finally, we return a 200 http status with a JSON format success message via
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
## Step 3: Create an api endpoint for the webhook
 | 
					## Step 3: Create an api endpoint for the webhook
 | 
				
			||||||
 | 
					
 | 
				
			||||||
In order for a webhook to be externally available, it must be mapped to a url.
 | 
					In order for an incoming webhook to be externally available, it must be mapped
 | 
				
			||||||
This is done in `zerver/lib/integrations.py`.
 | 
					to a url. This is done in `zerver/lib/integrations.py`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Look for the lines beginning with:
 | 
					Look for the lines beginning with:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -256,7 +259,7 @@ and the value you set for `STREAM_NAME` must match. The test helpers use `STREAM
 | 
				
			|||||||
to create the destination stream, and then create the message to send using the
 | 
					to create the destination stream, and then create the message to send using the
 | 
				
			||||||
value from the fixture. If these don't match, the test will fail.
 | 
					value from the fixture. If these don't match, the test will fail.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
`URL_TEMPLATE` defines how the test runner will call your webhook, in the same way
 | 
					`URL_TEMPLATE` defines how the test runner will call your incoming webhook, in the same way
 | 
				
			||||||
 you would provide a webhook URL to the 3rd party service. `api_key={api_key}` says
 | 
					 you would provide a webhook URL to the 3rd party service. `api_key={api_key}` says
 | 
				
			||||||
that an API key is expected.
 | 
					that an API key is expected.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -318,7 +321,7 @@ DONE!
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
## Step 5: Create documentation
 | 
					## Step 5: Create documentation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Next, we add end-user documentation for our webhook integration.  You
 | 
					Next, we add end-user documentation for our integration.  You
 | 
				
			||||||
can see the existing examples at <https://zulipchat.com/integrations>
 | 
					can see the existing examples at <https://zulipchat.com/integrations>
 | 
				
			||||||
or by accessing `/integrations` in your Zulip development environment.
 | 
					or by accessing `/integrations` in your Zulip development environment.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -388,7 +391,7 @@ request:
 | 
				
			|||||||
3. Take a look at your git history to ensure your commits have been clear and
 | 
					3. Take a look at your git history to ensure your commits have been clear and
 | 
				
			||||||
   logical (see [Version Control](
 | 
					   logical (see [Version Control](
 | 
				
			||||||
   https://zulip.readthedocs.io/en/latest/contributing/version-control.html) for tips). If not,
 | 
					   https://zulip.readthedocs.io/en/latest/contributing/version-control.html) for tips). If not,
 | 
				
			||||||
   consider revising them with `git rebase --interactive`. For most webhooks,
 | 
					   consider revising them with `git rebase --interactive`. For most incoming webhooks,
 | 
				
			||||||
   you'll want to squash your changes into a single commit and include a good,
 | 
					   you'll want to squash your changes into a single commit and include a good,
 | 
				
			||||||
   clear commit message.
 | 
					   clear commit message.
 | 
				
			||||||
4. Push code to your fork.
 | 
					4. Push code to your fork.
 | 
				
			||||||
@@ -416,7 +419,7 @@ be a successful test of an error condition. To correctly test these cases, you
 | 
				
			|||||||
must explicitly code your test's execution (using other helpers, as needed)
 | 
					must explicitly code your test's execution (using other helpers, as needed)
 | 
				
			||||||
rather than call the usual helper function.
 | 
					rather than call the usual helper function.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Here is an example from the WordPress webhook:
 | 
					Here is an example from the WordPress integration:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
def test_unknown_action_no_data(self) -> None:
 | 
					def test_unknown_action_no_data(self) -> None:
 | 
				
			||||||
@@ -438,7 +441,7 @@ def test_unknown_action_no_data(self) -> None:
 | 
				
			|||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
In a normal test, `send_and_test_stream_message` would handle all the setup
 | 
					In a normal test, `send_and_test_stream_message` would handle all the setup
 | 
				
			||||||
and then check that the webhook's response matches the expected result. If
 | 
					and then check that the incoming webhook's response matches the expected result. If
 | 
				
			||||||
the webhook returns an error, the test fails. Instead, explicitly do the
 | 
					the webhook returns an error, the test fails. Instead, explicitly do the
 | 
				
			||||||
setup it would have done, and check the result yourself.
 | 
					setup it would have done, and check the result yourself.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -446,8 +449,8 @@ Here, `subscribe_to_stream` is a test helper that uses `TEST_USER_EMAIL` and
 | 
				
			|||||||
`STREAM_NAME` (attributes from the base class) to register the user to receive
 | 
					`STREAM_NAME` (attributes from the base class) to register the user to receive
 | 
				
			||||||
messages in the given stream. If the stream doesn't exist, it creates it.
 | 
					messages in the given stream. If the stream doesn't exist, it creates it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
`client_post`, another helper, performs the HTTP POST that calls the webhook.
 | 
					`client_post`, another helper, performs the HTTP POST that calls the incoming
 | 
				
			||||||
As long as `self.url` is correct, you don't need to construct the webhook
 | 
					webhook. As long as `self.url` is correct, you don't need to construct the webhook
 | 
				
			||||||
URL yourself. (In most cases, it is.)
 | 
					URL yourself. (In most cases, it is.)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
`assert_json_error` then checks if the result matches the expected error.
 | 
					`assert_json_error` then checks if the result matches the expected error.
 | 
				
			||||||
@@ -548,5 +551,5 @@ recommend raising `UnexpectedWebhookEventType` (found in
 | 
				
			|||||||
raise UnexpectedWebhookEventType(webhook_name, event_type)
 | 
					raise UnexpectedWebhookEventType(webhook_name, event_type)
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
`webhook_name` is the name of the webhook that raises the exception. `event_type`
 | 
					`webhook_name` is the name of the integration that raises the exception.
 | 
				
			||||||
is the name of the unexpected webhook event.
 | 
					`event_type` is the name of the unexpected webhook event.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -92,8 +92,8 @@ the escape key.
 | 
				
			|||||||
An **integration** is a tool that combines Zulip with another service or
 | 
					An **integration** is a tool that combines Zulip with another service or
 | 
				
			||||||
application. Zulip offers a variety of integrations for version control, issue
 | 
					application. Zulip offers a variety of integrations for version control, issue
 | 
				
			||||||
tracker, CI system, monitoring tools, and other tools used for development. The
 | 
					tracker, CI system, monitoring tools, and other tools used for development. The
 | 
				
			||||||
three types of integrations that Zulip supports are webhook integrations, Python
 | 
					three types of integrations that Zulip supports are incoming webhook integrations,
 | 
				
			||||||
script integrations, and plugin integrations.
 | 
					Python script integrations, and plugin integrations.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### mention
 | 
					### mention
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user