snapshot of https://github.com/zulip/zulip.git @ 48c69911c7dd4e03b20552eb3bd77ad8151c1357 (2026-09-15)
Some checks failed
Code scanning / CodeQL (push) Failing after 15s
Zulip production suite / Ubuntu 22.04 production build (push) Failing after 26s
Zulip production suite / Debian 12 production install with custom db name and user (push) Has been skipped
Zulip production suite / Ubuntu 22.04 production install and PostgreSQL upgrade with pgroonga (push) Has been skipped
Zulip production suite / Ubuntu 24.04 production install (push) Has been skipped
Zulip production suite / Ubuntu 26.04 production install (push) Has been skipped
Zulip production suite / Debian 13 production install (push) Has been skipped
Zulip production suite / 7.0 Version Upgrade (push) Has been skipped
Zulip production suite / 8.0 Version Upgrade (push) Has been skipped
Zulip production suite / 6.0 Version Upgrade (push) Has been skipped
Zulip production suite / 10.0 Version Upgrade (push) Has been skipped
Zulip production suite / 9.0 Version Upgrade (push) Has been skipped
Zulip production suite / 12.0 Version Upgrade (push) Has been skipped
Zulip production suite / 11.0 Version Upgrade (push) Has been skipped
GitHub Actions Security Analysis with zizmor / zizmor (push) Failing after 3s
Zulip CI / Debian 12 (Python 3.11, backend + documentation) (push) Failing after 26s
Zulip CI / Ubuntu 22.04 (Python 3.10, backend + frontend) (push) Failing after 3s
Zulip CI / Ubuntu 24.04 (Python 3.12, backend) (push) Failing after 25s
Zulip CI / Ubuntu 26.04 (Python 3.14, backend) (push) Failing after 25s
Zulip CI / Debian 13 (Python 3.13, backend) (push) Failing after 28s
Zulip production suite / Required jobs (push) Has been cancelled
Zulip CI / Required jobs (push) Has been cancelled
API Documentation Update Check / check-feature-level-updated (push) Has been cancelled
API Documentation Update Check / notify-if-api-docs-changed (push) Has been cancelled
Some checks failed
Code scanning / CodeQL (push) Failing after 15s
Zulip production suite / Ubuntu 22.04 production build (push) Failing after 26s
Zulip production suite / Debian 12 production install with custom db name and user (push) Has been skipped
Zulip production suite / Ubuntu 22.04 production install and PostgreSQL upgrade with pgroonga (push) Has been skipped
Zulip production suite / Ubuntu 24.04 production install (push) Has been skipped
Zulip production suite / Ubuntu 26.04 production install (push) Has been skipped
Zulip production suite / Debian 13 production install (push) Has been skipped
Zulip production suite / 7.0 Version Upgrade (push) Has been skipped
Zulip production suite / 8.0 Version Upgrade (push) Has been skipped
Zulip production suite / 6.0 Version Upgrade (push) Has been skipped
Zulip production suite / 10.0 Version Upgrade (push) Has been skipped
Zulip production suite / 9.0 Version Upgrade (push) Has been skipped
Zulip production suite / 12.0 Version Upgrade (push) Has been skipped
Zulip production suite / 11.0 Version Upgrade (push) Has been skipped
GitHub Actions Security Analysis with zizmor / zizmor (push) Failing after 3s
Zulip CI / Debian 12 (Python 3.11, backend + documentation) (push) Failing after 26s
Zulip CI / Ubuntu 22.04 (Python 3.10, backend + frontend) (push) Failing after 3s
Zulip CI / Ubuntu 24.04 (Python 3.12, backend) (push) Failing after 25s
Zulip CI / Ubuntu 26.04 (Python 3.14, backend) (push) Failing after 25s
Zulip CI / Debian 13 (Python 3.13, backend) (push) Failing after 28s
Zulip production suite / Required jobs (push) Has been cancelled
Zulip CI / Required jobs (push) Has been cancelled
API Documentation Update Check / check-feature-level-updated (push) Has been cancelled
API Documentation Update Check / notify-if-api-docs-changed (push) Has been cancelled
This commit is contained in:
31
api_docs/api-doc-template.md
Normal file
31
api_docs/api-doc-template.md
Normal file
@@ -0,0 +1,31 @@
|
||||
{generate_api_header(API_ENDPOINT_NAME)}
|
||||
|
||||
## Usage examples
|
||||
|
||||
{start_tabs}
|
||||
|
||||
{generate_code_example(python)|API_ENDPOINT_NAME|example}
|
||||
|
||||
{generate_code_example(javascript)|API_ENDPOINT_NAME|example}
|
||||
|
||||
{tab|curl}
|
||||
|
||||
{generate_code_example(curl)|API_ENDPOINT_NAME|example}
|
||||
|
||||
{end_tabs}
|
||||
|
||||
## Parameters
|
||||
|
||||
{generate_api_arguments_table|zulip.yaml|API_ENDPOINT_NAME}
|
||||
|
||||
{generate_parameter_description(API_ENDPOINT_NAME)}
|
||||
|
||||
## Response
|
||||
|
||||
{generate_return_values_table|zulip.yaml|API_ENDPOINT_NAME}
|
||||
|
||||
{generate_response_description(API_ENDPOINT_NAME)}
|
||||
|
||||
#### Example response(s)
|
||||
|
||||
{generate_code_example|API_ENDPOINT_NAME|fixture}
|
||||
153
api_docs/api-keys.md
Normal file
153
api_docs/api-keys.md
Normal file
@@ -0,0 +1,153 @@
|
||||
# API keys and `zuliprc` files
|
||||
|
||||
An **API key** is how a user or bot can identify their account to Zulip.
|
||||
|
||||
A **`zuliprc` file** is a configuration file written in the [INI file
|
||||
format](https://en.wikipedia.org/wiki/INI_file), which contains key-value
|
||||
pairs, such as an API key and other configuration values, that are
|
||||
necessary for using the Zulip API with a specific user or bot account on
|
||||
a Zulip server, for example:
|
||||
|
||||
```
|
||||
[api]
|
||||
key=<bot API key>
|
||||
email=<bot email address>
|
||||
site=<Zulip server's URL>
|
||||
...
|
||||
```
|
||||
|
||||
For the official
|
||||
clients, such as the [Python bindings](/api/configuring-python-bindings),
|
||||
we recommend [downloading a `zuliprc` file](#download-a-zuliprc-file).
|
||||
|
||||
## Get an API key
|
||||
|
||||
{start_tabs}
|
||||
|
||||
{tab|for-a-bot}
|
||||
|
||||
{settings_tab|your-bots}
|
||||
|
||||
1. In the **Actions** column, click the **manage bot**
|
||||
(<i class="zulip-icon zulip-icon-user-cog"></i>) icon,
|
||||
and scroll down to **API key**.
|
||||
|
||||
1. Click the **copy**
|
||||
(<i class="zulip-icon zulip-icon-copy"></i>) icon to
|
||||
copy the bot's API key to your clipboard.
|
||||
|
||||
!!! warn ""
|
||||
|
||||
Anyone with a bot's API key can impersonate the bot, so be careful with it!
|
||||
|
||||
{tab|for-yourself}
|
||||
|
||||
{settings_tab|account-and-privacy}
|
||||
|
||||
1. Under **API key**, click **Manage your API key**.
|
||||
|
||||
1. Enter your password, and click **Get API key**. If you don't know your
|
||||
password, click **reset it** and follow the instructions from there.
|
||||
|
||||
1. Copy your API key.
|
||||
|
||||
!!! warn ""
|
||||
|
||||
Anyone with your API key can impersonate you, so be doubly careful with it.
|
||||
|
||||
{end_tabs}
|
||||
|
||||
## Invalidate an API key
|
||||
|
||||
To invalidate an existing API key, you have to generate a new key. Generating a
|
||||
new API key will immediately log you out of this account on all mobile devices.
|
||||
|
||||
{start_tabs}
|
||||
|
||||
{tab|for-a-bot}
|
||||
|
||||
{settings_tab|your-bots}
|
||||
|
||||
1. In the **Actions** column, click the **manage bot**
|
||||
(<i class="zulip-icon zulip-icon-user-cog"></i>) icon,
|
||||
and scroll down to **API key**.
|
||||
|
||||
1. Click the **generate new API key**
|
||||
(<i class="zulip-icon zulip-icon-refresh-cw"></i>) icon.
|
||||
|
||||
{tab|for-yourself}
|
||||
|
||||
{settings_tab|account-and-privacy}
|
||||
|
||||
1. Under **API key**, click **Manage your API key**.
|
||||
|
||||
1. Enter your password, and click **Get API key**. If you don't know your
|
||||
password, click **reset it** and follow the instructions from there.
|
||||
|
||||
1. Click **Generate new API key**
|
||||
|
||||
{end_tabs}
|
||||
|
||||
### Download a `zuliprc` file
|
||||
|
||||
{start_tabs}
|
||||
|
||||
{tab|for-a-bot}
|
||||
|
||||
{settings_tab|your-bots}
|
||||
|
||||
1. In the **Actions** column, click the **manage bot**
|
||||
(<i class="zulip-icon zulip-icon-user-cog"></i>) icon,
|
||||
and scroll down to **Zuliprc configuration**.
|
||||
|
||||
1. Click the **download**
|
||||
(<i class="zulip-icon zulip-icon-download"></i>) icon
|
||||
to download the bot's `zuliprc` file, or the **copy**
|
||||
(<i class="zulip-icon zulip-icon-copy"></i>) icon to
|
||||
copy the file's content to your clipboard.
|
||||
|
||||
!!! warn ""
|
||||
|
||||
Anyone with a bot's API key can impersonate the bot, so be careful with it!
|
||||
|
||||
{tab|for-yourself}
|
||||
|
||||
{settings_tab|account-and-privacy}
|
||||
|
||||
1. Under **API key**, click **Manage your API key**.
|
||||
|
||||
1. Enter your password, and click **Get API key**. If you don't know your
|
||||
password, click **reset it** and follow the
|
||||
instructions from there.
|
||||
|
||||
1. Click **Download zuliprc** to download your `zuliprc` file.
|
||||
|
||||
1. (optional) If you'd like your credentials to be used by default
|
||||
when using the Zulip API on your computer, move the `zuliprc` file
|
||||
to `~/.zuliprc` in your home directory.
|
||||
|
||||
!!! warn ""
|
||||
|
||||
Anyone with your API key can impersonate you, so be doubly careful with it.
|
||||
|
||||
{end_tabs}
|
||||
|
||||
### Configuration keys and environment variables
|
||||
|
||||
The keys you can use in a `zuliprc` file (and their equivalent
|
||||
[environment variables](https://en.wikipedia.org/wiki/Environment_variable))
|
||||
can be found in the following table:
|
||||
|
||||
| `zuliprc` key | Environment variable | Required | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `key` | `ZULIP_API_KEY` | Yes | The user's [API key](#get-an-api-key). |
|
||||
| `email` | `ZULIP_EMAIL` | Yes | The email address of the user who owns the API key mentioned above. |
|
||||
| `site` | `ZULIP_SITE` | No | URL where the Zulip server is located. |
|
||||
| `client_cert_key` | `ZULIP_CERT_KEY` | No | Path to the SSL/TLS private key that the binding should use to connect to the server. |
|
||||
| `client_cert`| `ZULIP_CERT` | No* | The public counterpart of `client_cert_key`/`ZULIP_CERT_KEY`. _*This setting is required if a cert key has been set._ |
|
||||
| `client_bundle` | `ZULIP_CERT_BUNDLE` | No | Path where the server's PEM-encoded certificate is located. CA certificates are also accepted, in case those CA's have issued the server's certificate. Defaults to the built-in CA bundle trusted by Python. |
|
||||
| `insecure` | `ZULIP_ALLOW_INSECURE` | No | Allows connecting to Zulip servers with an invalid SSL/TLS certificate. Please note that enabling this will make the HTTPS connection insecure. Defaults to `false`. |
|
||||
|
||||
## Related articles
|
||||
|
||||
* [Configuring the Python bindings](/api/configuring-python-bindings)
|
||||
4709
api_docs/changelog.md
Normal file
4709
api_docs/changelog.md
Normal file
File diff suppressed because it is too large
Load Diff
60
api_docs/client-libraries.md
Normal file
60
api_docs/client-libraries.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# Client libraries
|
||||
|
||||
These API client libraries make it easy to work with Zulip's REST API
|
||||
in your favorite language.
|
||||
|
||||
## Official libraries
|
||||
|
||||
These libraries are maintained by members of the Zulip core team. The
|
||||
Python library is the most complete and best documented.
|
||||
|
||||
* [Python](https://github.com/zulip/python-zulip-api)
|
||||
* [JavaScript](https://github.com/zulip/zulip-js)
|
||||
|
||||
## User maintained libraries
|
||||
|
||||
The Zulip core team doesn't have the resources to maintain
|
||||
high-quality libraries for every programming language. We've
|
||||
collected a list of user-maintained libraries for popular languages:
|
||||
|
||||
* [Clojure](https://github.com/thieman/clojure-zulip)
|
||||
* [C#](https://github.com/zulip/zulip-csharp)
|
||||
* [Go](https://github.com/ifo/gozulipbot)
|
||||
* [Java](https://github.com/taliox/zulip-java-rest)
|
||||
* [Kotlin](https://gitlab.com/ppiag/kzulip)
|
||||
* [PHP](https://github.com/mrferos/zulip-php-client)
|
||||
* [Ruby](https://github.com/raws/wonder-llama)
|
||||
* [Swift](https://github.com/zulip/swift-zulip-api)
|
||||
|
||||
### Contributing
|
||||
|
||||
Contributing to improve language libraries is appreciated, as is
|
||||
writing new ones. If you actively maintain a Zulip language binding
|
||||
and would like it to be listed here (or would like to collaborate with
|
||||
us in making it an official library), post in [this
|
||||
topic][integrations-thread] in
|
||||
[the Zulip development community](https://zulip.com/development-community/)
|
||||
or submit a pull request [updating this
|
||||
page](https://zulip.readthedocs.io/en/latest/documentation/api.html).
|
||||
|
||||
[integrations-thread]: https://chat.zulip.org/#narrow/channel/127-integrations/topic/API.20client.20libraries/
|
||||
|
||||
### Outdated
|
||||
|
||||
!!! tip ""
|
||||
|
||||
The following projects are not actively maintained. Since
|
||||
Zulip's core APIs have been stable for 5 years, even very
|
||||
old libraries can be useful.
|
||||
|
||||
* [Lua](https://github.com/deckycoss/zulua)
|
||||
* [Erlang](https://github.com/femnad/tuplre)
|
||||
* [PHP](https://github.com/federicoq/zulip-php)
|
||||
* [Go](https://github.com/decached/go-zulip)
|
||||
* [Haskell](https://github.com/yamadapc/hzulip)
|
||||
* [Chicken Scheme](https://github.com/yamadapc/zulip-scheme)
|
||||
* [Scala](https://github.com/cqfd/zulip-scala)
|
||||
* [EventMachine](https://github.com/cqfd/zulip_machine)
|
||||
* [Ruby](https://github.com/verg/zulip-rb)
|
||||
* [Perl](https://github.com/Stantheman/WebService-Zulip)
|
||||
* [.Net](https://github.com/Shayan-To/ZulipClientApi)
|
||||
30
api_docs/configuring-python-bindings.md
Normal file
30
api_docs/configuring-python-bindings.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# Configuring the Python bindings
|
||||
|
||||
Zulip provides a set of tools that allows interacting with its API more
|
||||
easily, called the [Python bindings](https://pypi.python.org/pypi/zulip/).
|
||||
One of the most notable use cases for these bindings are bots developed
|
||||
using Zulip's [bot framework](/help/writing-bots).
|
||||
|
||||
In order to use them, you need to configure them with your identity
|
||||
(account, API key, and Zulip server URL). There are a few ways to
|
||||
achieve that:
|
||||
|
||||
- Using a [`zuliprc` file](/api/api-keys#download-a-zuliprc-file), referenced via
|
||||
the `--config-file` option or the `config_file` option to the
|
||||
`zulip.Client` constructor (recommended for bots).
|
||||
- Using a [`zuliprc` file](/api/api-keys#download-a-zuliprc-file) in your home
|
||||
directory at `~/.zuliprc` (recommended for your own API key).
|
||||
- Using the [environment
|
||||
variables](https://en.wikipedia.org/wiki/Environment_variable)
|
||||
documented [here](/api/api-keys#configuration-keys-and-environment-variables).
|
||||
- Using the `--api-key`, `--email`, and `--site` variables as command
|
||||
line parameters.
|
||||
- Using the `api_key`, `email`, and `site` parameters to the
|
||||
`zulip.Client` constructor.
|
||||
|
||||
## Related articles
|
||||
|
||||
* [Installation instructions](/api/installation-instructions)
|
||||
* [API keys](/api/api-keys)
|
||||
* [Running bots](/help/running-bots)
|
||||
* [Deploying bots](/help/deploying-bots)
|
||||
210
api_docs/construct-narrow.md
Normal file
210
api_docs/construct-narrow.md
Normal file
@@ -0,0 +1,210 @@
|
||||
# Construct a narrow
|
||||
|
||||
A **narrow** is a set of filters for Zulip messages, that can be based
|
||||
on many different factors (like sender, channel, topic, search
|
||||
keywords, etc.). Narrows are used in various places in the Zulip
|
||||
API (most importantly, in the API for fetching messages).
|
||||
|
||||
It is simplest to explain the algorithm for encoding a search as a
|
||||
narrow using a single example. Consider the following search query
|
||||
(written as it would be entered in the Zulip web app's search box).
|
||||
It filters for messages sent to channel `announce`, not sent by
|
||||
`iago@zulip.com`, and containing the words `cool` and `sunglasses`:
|
||||
|
||||
```
|
||||
channel:announce -sender:iago@zulip.com cool sunglasses
|
||||
```
|
||||
|
||||
This query would be JSON-encoded for use in the Zulip API using JSON
|
||||
as a list of simple objects, as follows:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"operator": "channel",
|
||||
"operand": "announce"
|
||||
},
|
||||
{
|
||||
"operator": "sender",
|
||||
"operand": "iago@zulip.com",
|
||||
"negated": true
|
||||
},
|
||||
{
|
||||
"operator": "search",
|
||||
"operand": "cool sunglasses"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
The Zulip help center article on [searching for messages](/help/search-for-messages)
|
||||
documents the majority of the search/narrow options supported by the
|
||||
Zulip API.
|
||||
|
||||
Note that many narrows, including all that lack a `channel` or `channels`
|
||||
operator, search the current user's personal message history. See
|
||||
[searching shared history](/help/search-for-messages#search-shared-history)
|
||||
for details.
|
||||
|
||||
Clients should note that the `is:unread` filter takes advantage of the
|
||||
fact that there is a database index for unread messages, which can be an
|
||||
important optimization when fetching messages in certain cases (e.g.,
|
||||
when [adding the `read` flag to a user's personal
|
||||
messages](/api/update-message-flags-for-narrow)).
|
||||
|
||||
Note: When the value of `realm_empty_topic_display_name` found in
|
||||
the [POST /register](/api/register-queue) response is used as an operand
|
||||
for the `"topic"` operator in the narrow, it is interpreted
|
||||
as an empty string.
|
||||
|
||||
## Changes
|
||||
|
||||
* In Zulip 12.0 (feature level 489), support was added for a new
|
||||
filter, `channels:archived`, which returns messages the current user
|
||||
received in channels that have been [archived](/help/archive-a-channel).
|
||||
|
||||
* In Zulip 12.0 (feature level 446), add the `mentions` operator,
|
||||
matching messages that contain a direct personal mention of the
|
||||
specified user.
|
||||
|
||||
* In Zulip 10.0 (feature level 366), support was added for a new
|
||||
`is:muted` operator combination, matching messages in topics and
|
||||
channels that the user has [muted](/help/mute-a-topic).
|
||||
|
||||
* Before Zulip 10.0 (feature level 334), empty string was not a valid
|
||||
topic name for channel messages.
|
||||
|
||||
* In Zulip 9.0 (feature level 271), support was added for a new filter
|
||||
operator, `with`, which uses a [message ID](#message-ids) for its
|
||||
operand, and is designed for creating permanent links to topics.
|
||||
|
||||
* In Zulip 9.0 (feature level 265), support was added for a new
|
||||
`is:followed` filter, matching messages in topics that the current
|
||||
user is [following](/help/follow-a-topic).
|
||||
|
||||
* In Zulip 9.0 (feature level 250), support was added for two filters
|
||||
related to stream messages: `channel` and `channels`. The `channel`
|
||||
operator is an alias for the `stream` operator. The `channels`
|
||||
operator is an alias for the `streams` operator. Both `channel` and
|
||||
`channels` return the same exact results as `stream` and `streams`
|
||||
respectively.
|
||||
|
||||
* In Zulip 9.0 (feature level 249), support was added for a new filter,
|
||||
`has:reaction`, which returns messages that have at least one [emoji
|
||||
reaction](/help/emoji-reactions).
|
||||
|
||||
* In Zulip 7.0 (feature level 177), support was added for three filters
|
||||
related to direct messages: `is:dm`, `dm` and `dm-including`. The
|
||||
`dm` operator replaced and deprecated the `pm-with` operator. The
|
||||
`is:dm` filter replaced and deprecated the `is:private` filter. The
|
||||
`dm-including` operator replaced and deprecated the `group-pm-with`
|
||||
operator.
|
||||
|
||||
* The `dm-including` and `group-pm-with` operators return slightly
|
||||
different results. For example, `dm-including:1234` returns all
|
||||
direct messages (1-on-1 and group) that include the current user
|
||||
and the user with the unique user ID of `1234`. On the other hand,
|
||||
`group-pm-with:1234` returned only group direct messages that
|
||||
included the current user and the user with the unique user ID of
|
||||
`1234`.
|
||||
|
||||
* Both `dm` and `is:dm` are aliases of `pm-with` and `is:private`
|
||||
respectively, and return the same exact results that the
|
||||
deprecated filters did.
|
||||
|
||||
## Narrows that use IDs
|
||||
|
||||
### Message IDs
|
||||
|
||||
The `id` and `with` operators use message IDs for their operands. The
|
||||
message ID operand for these two operators may be encoded as either a
|
||||
number or a string.
|
||||
|
||||
* `id:12345`: Search for only the message with ID `12345`.
|
||||
* `with:12345`: Search for the conversation that contains the message
|
||||
with ID `12345`.
|
||||
|
||||
The `id` operator returns the message with the specified ID if it exists,
|
||||
and if it can be accessed by the user.
|
||||
|
||||
The `with` operator is designed to be used for permanent links to
|
||||
topics, which means they should continue to work when the topic is
|
||||
[moved](/help/move-content-to-another-topic) or
|
||||
[resolved](/help/resolve-a-topic). If the message with the specified
|
||||
ID exists, and can be accessed by the user, then it will return
|
||||
messages with the `channel`/`topic`/`dm` operators corresponding to
|
||||
the current conversation containing that message, replacing any such
|
||||
operators included in the original narrow query.
|
||||
|
||||
If no such message exists, or the message ID represents a message that
|
||||
is inaccessible to the user, this operator will be ignored (rather
|
||||
than throwing an error) if the remaining operators uniquely identify a
|
||||
conversation (i.e., they contain `channel` and `topic` terms or `dm`
|
||||
term). This behavior is intended to provide the best possible
|
||||
experience for links to private channels with protected history.
|
||||
|
||||
The [help center](/help/search-for-messages#search-by-message-id) also
|
||||
documents the `near` operator for searching for messages by ID, but
|
||||
this narrow operator has no effect on filtering messages when sent to
|
||||
the server. In practice, when the `near` operator is used to search for
|
||||
messages, or is part of a URL fragment, the value of its operand should
|
||||
instead be used for the value of the `anchor` parameter in endpoints
|
||||
that also accept a `narrow` parameter; see
|
||||
[GET /messages][anchor-get-messages] and
|
||||
[POST /messages/flags/narrow][anchor-post-flags].
|
||||
|
||||
**Changes**: Prior to Zulip 8.0 (feature level 194), the message ID
|
||||
operand for the `id` operator needed to be encoded as a string.
|
||||
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"operator": "id",
|
||||
"operand": 12345
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### Channel and user IDs
|
||||
|
||||
There are a few additional narrow/search options (new in Zulip 2.1)
|
||||
that use either channel IDs or user IDs that are not documented in the
|
||||
help center because they are primarily useful to API clients:
|
||||
|
||||
* `channel:1234`: Search messages sent to the channel with ID `1234`.
|
||||
* `sender:1234`: Search messages sent by user ID `1234`.
|
||||
* `dm:1234`: Search the direct message conversation between
|
||||
you and user ID `1234`.
|
||||
* `dm:1234,5678`: Search the direct message conversation between
|
||||
you, user ID `1234`, and user ID `5678`.
|
||||
* `dm-including:1234`: Search all direct messages (1-on-1 and group)
|
||||
that include you and user ID `1234`.
|
||||
|
||||
!!! tip ""
|
||||
|
||||
A user ID can be found by [viewing a user's profile][view-profile]
|
||||
in the web or desktop apps. A channel ID can be found when [browsing
|
||||
channels][browse-channels] in the web or desktop apps.
|
||||
|
||||
The operands for these search options must be encoded either as an
|
||||
integer ID or a JSON list of integer IDs. For example, to query
|
||||
messages sent by a user 1234 to a direct message thread with yourself,
|
||||
user 1234, and user 5678, the correct JSON-encoded query is:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"operator": "dm",
|
||||
"operand": [1234, 5678]
|
||||
},
|
||||
{
|
||||
"operator": "sender",
|
||||
"operand": 1234
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
[view-profile]: /help/view-someones-profile
|
||||
[browse-channels]: /help/introduction-to-channels#browse-and-subscribe-to-channels
|
||||
[anchor-get-messages]: /api/get-messages#parameter-anchor
|
||||
[anchor-post-flags]: /api/update-message-flags-for-narrow#parameter-anchor
|
||||
51
api_docs/create-scheduled-message.md
Normal file
51
api_docs/create-scheduled-message.md
Normal file
@@ -0,0 +1,51 @@
|
||||
{generate_api_header(/scheduled_messages:post)}
|
||||
|
||||
## Usage examples
|
||||
|
||||
{start_tabs}
|
||||
|
||||
{generate_code_example(python)|/scheduled_messages:post|example}
|
||||
|
||||
{generate_code_example(javascript)|/scheduled_messages:post|example}
|
||||
|
||||
{tab|curl}
|
||||
|
||||
{!curl-auth-credentials.md!}
|
||||
|
||||
``` curl
|
||||
# Create a scheduled channel message
|
||||
curl -X POST {{ api_url }}/v1/scheduled_messages \
|
||||
-u EMAIL_ADDRESS:API_KEY \
|
||||
--data-urlencode type=stream \
|
||||
--data-urlencode to=9 \
|
||||
--data-urlencode topic=Hello \
|
||||
--data-urlencode 'content=Nice to meet everyone!' \
|
||||
--data-urlencode scheduled_delivery_timestamp=3165826990
|
||||
|
||||
# Create a scheduled direct message
|
||||
curl -X POST {{ api_url }}/v1/messages \
|
||||
-u EMAIL_ADDRESS:API_KEY \
|
||||
--data-urlencode type=direct \
|
||||
--data-urlencode 'to=[9, 10]' \
|
||||
--data-urlencode 'content=Can we meet on Monday?' \
|
||||
--data-urlencode scheduled_delivery_timestamp=3165826990
|
||||
|
||||
```
|
||||
|
||||
{end_tabs}
|
||||
|
||||
## Parameters
|
||||
|
||||
{generate_api_arguments_table|zulip.yaml|/scheduled_messages:post}
|
||||
|
||||
{generate_parameter_description(/scheduled_messages:post)}
|
||||
|
||||
## Response
|
||||
|
||||
{generate_return_values_table|zulip.yaml|/scheduled_messages:post}
|
||||
|
||||
{generate_response_description(/scheduled_messages:post)}
|
||||
|
||||
#### Example response(s)
|
||||
|
||||
{generate_code_example|/scheduled_messages:post|fixture}
|
||||
6
api_docs/create-stream.md
Normal file
6
api_docs/create-stream.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Create a channel
|
||||
|
||||
You can create a channel using Zulip's REST API by submitting a
|
||||
[subscribe](/api/subscribe) request with a channel name that
|
||||
doesn't yet exist and passing appropriate parameters to define
|
||||
the initial configuration of the new channel.
|
||||
122
api_docs/group-setting-values.md
Normal file
122
api_docs/group-setting-values.md
Normal file
@@ -0,0 +1,122 @@
|
||||
# Group-setting values
|
||||
|
||||
Settings defining permissions in Zulip are increasingly represented
|
||||
using [user groups](/help/user-groups), which offer much more flexible
|
||||
configuration than the older [roles](/api/roles-and-permissions) system.
|
||||
|
||||
!!! warn ""
|
||||
|
||||
**Note**: Many group-valued settings are configured to require
|
||||
a single system group for their value via
|
||||
`server_supported_permission_settings`, pending web app UI
|
||||
changes to fully support group-setting values.
|
||||
|
||||
**Changes**: Before Zulip 10.0 (feature level 309), only system
|
||||
groups were permitted values for group-setting values in
|
||||
production environments, regardless of the values in
|
||||
`server_supported_permission_settings`.
|
||||
|
||||
In the API, these settings are represented using a **group-setting
|
||||
value**, which can take two forms:
|
||||
|
||||
- An integer user group ID, which can be either a named user group
|
||||
visible in the UI or a [role-based system group](#system-groups).
|
||||
- An object with fields `direct_members`, containing a list of
|
||||
integer user IDs, and `direct_subgroups`, containing a list of
|
||||
integer group IDs. The setting's value is the union of the
|
||||
identified collection of users and groups.
|
||||
|
||||
Group-setting values in the object form can be thought of as an
|
||||
anonymous group. They function very much like a named user group
|
||||
object, and remove the naming and UI overhead involved in creating
|
||||
a visible user group just to store the value of a single setting.
|
||||
|
||||
The server will canonicalize an object with an empty `direct_members`
|
||||
list and a `direct_subgroups` list that contains just a single group
|
||||
ID to the integer format.
|
||||
|
||||
## System groups
|
||||
|
||||
The Zulip server maintains a collection of system groups that
|
||||
correspond to the users with a given role; this makes it convenient to
|
||||
store concepts like "all administrators" in a group-setting
|
||||
value. These use a special naming convention and can be recognized by
|
||||
the `is_system_group` property on their group object.
|
||||
|
||||
The following system groups are maintained by the Zulip server:
|
||||
|
||||
- `role:internet`: Everyone on the Internet has this permission; this
|
||||
is used to configure the [public access
|
||||
option](/help/public-access-option).
|
||||
- `role:everyone`: All users, including guests.
|
||||
- `role:members`: All users, excluding guests.
|
||||
- `role:fullmembers`: All [full
|
||||
members](https://zulip.com/api/roles-and-permissions#determining-if-a-user-is-a-full-member)
|
||||
of the organization.
|
||||
- `role:moderators`: All users with at least the moderator role.
|
||||
- `role:administrators`: All users with at least the administrator
|
||||
role.
|
||||
- `role:owners`: All users with the owner role.
|
||||
- `role:nobody`: The formal empty group. Used in the API to represent
|
||||
disabling a feature.
|
||||
|
||||
Client UI for setting a permission or displaying a group (when
|
||||
silently mentioned, for example) is encouraged to display system
|
||||
groups using their description, rather than using their `role:}`
|
||||
names, which are chosen to be unique and clear in the API.
|
||||
|
||||
System groups should generally not be displayed in UI for
|
||||
administering an organization's user groups, since they are not
|
||||
directly mutable.
|
||||
|
||||
## Updating group-setting values
|
||||
|
||||
The Zulip API uses a special format for modifying an existing setting
|
||||
using a group-setting value.
|
||||
|
||||
A **group-setting update** is an object with a `new` field and an
|
||||
optional `old` field, each containing a group-setting value. The
|
||||
setting's value will be set to the membership expressed by the `new`
|
||||
field.
|
||||
|
||||
The `old` field expresses the client's understanding of the current
|
||||
value of the setting. If the `old` field is present and does not match
|
||||
the actual current value of the setting, then the request will fail
|
||||
with error code `EXPECTATION_MISMATCH` and no changes will be applied.
|
||||
|
||||
When a user edits the setting in a UI, the resulting API request
|
||||
should generally always include the `old` field, giving the value
|
||||
the list had when the user started editing. This accurately expresses
|
||||
the user's intent, and if two users edit the same list around the
|
||||
same time, it prevents a situation where the second change
|
||||
accidentally reverts the first one without either user noticing.
|
||||
|
||||
Omitting `old` is appropriate where the intent really is a new complete
|
||||
list rather than an edit, for example in an integration that syncs the
|
||||
list from an external source of truth.
|
||||
|
||||
## Permitted values
|
||||
|
||||
Not every possible group-setting value is a valid configuration for a
|
||||
given group-based setting. For example, as a security hardening
|
||||
measure, some administrative permissions should never be exercised by
|
||||
guest users, and the system group for all users, including guests,
|
||||
should not be offered to users as an option for those settings.
|
||||
|
||||
Others have restrictions to only permit system groups due to UI
|
||||
components not yet having been migrated to support a broader set of
|
||||
values. In order to avoid this configuration ending up hardcoded in
|
||||
clients, every permission setting using this framework has an entry in
|
||||
the `server_supported_permission_settings` section of the [`POST
|
||||
/register`](/api/register-queue) response.
|
||||
|
||||
Clients that support mutating group-settings values must parse that
|
||||
part of the `register` payload in order to compute the set of
|
||||
permitted values to offer to the user and avoid server-side errors
|
||||
when trying to save a value.
|
||||
|
||||
Note specifically that the `allow_everyone_group` field, which
|
||||
determines whether the setting can have the value of "all user
|
||||
accounts, including guests" also controls whether guests users can
|
||||
exercise the permission regardless of their membership in the
|
||||
group-setting value.
|
||||
103
api_docs/http-headers.md
Normal file
103
api_docs/http-headers.md
Normal file
@@ -0,0 +1,103 @@
|
||||
# HTTP headers
|
||||
|
||||
This page documents the HTTP headers used by the Zulip API.
|
||||
|
||||
!!! tip ""
|
||||
|
||||
Full details of the HTTP requests are given in the `curl` example
|
||||
on each endpoint's documentation page. You can access curl's
|
||||
documentation at [`man curl`](https://curl.se/docs/manpage.html).
|
||||
|
||||
## The `Authorization` header
|
||||
|
||||
Most important is that API clients authenticate to the server using
|
||||
HTTP Basic authentication. If you're using the official [Python or
|
||||
JavaScript bindings](/api/installation-instructions), this is taken
|
||||
care of when you configure said bindings.
|
||||
|
||||
Otherwise, to authenticate an API request:
|
||||
|
||||
- Use HTTP `Basic` authentication, which is described [here][mdn-auth-headers].
|
||||
This means sending an HTTP header named `Authorization`, with your
|
||||
credentials [in a certain format][mdn-basic-auth].
|
||||
|
||||
- For `Basic` authentication credentials in the Zulip API, a "username"
|
||||
takes the form of an email address, and a "password" takes the form of
|
||||
an API key. In the `curl` example for each endpoint, this is shown as:
|
||||
`-u EMAIL_ADDRESS:API_KEY`.
|
||||
|
||||
- A bot's credentials can be obtained through the web and desktop apps'
|
||||
[bot management UI](/help/manage-a-bot) or by [downloading the bot's
|
||||
`zuliprc` file](/api/api-keys#download-a-zuliprc-file).
|
||||
|
||||
- See [fetch an API key (production)](/api/fetch-api-key) for the
|
||||
password-based authentication flow for getting a user's credentials.
|
||||
|
||||
## The `User-Agent` header
|
||||
|
||||
Clients are not required to pass a `User-Agent` HTTP header, but we
|
||||
highly recommend doing so when writing an integration. It's easy to do
|
||||
and it can help save time when debugging issues related to an API
|
||||
client.
|
||||
|
||||
If provided, the Zulip server will parse the `User-Agent` HTTP header
|
||||
in order to identify specific clients and integrations. This
|
||||
information is used by the server for logging, [usage
|
||||
statistics](/help/analytics), and on rare occasions, for
|
||||
backwards-compatibility logic to preserve support for older versions
|
||||
of official clients.
|
||||
|
||||
Official Zulip clients and integrations use a `User-Agent` that starts
|
||||
with something like `ZulipMobile/20.0.103 `, encoding the name of the
|
||||
application and it's version.
|
||||
|
||||
Zulip's official API bindings have reasonable defaults for
|
||||
`User-Agent`. For example, the official Zulip Python bindings have a
|
||||
default `User-Agent` starting with `ZulipPython/{version}`, where
|
||||
`version` is the version of the library.
|
||||
|
||||
You can give your bot/integration its own name by passing the `client`
|
||||
parameter when initializing the Python bindings. For example, the
|
||||
official Zulip Nagios integration is initialized like this:
|
||||
|
||||
``` python
|
||||
client = zulip.Client(
|
||||
config_file=opts.config, client=f"ZulipNagios/{VERSION}"
|
||||
)
|
||||
```
|
||||
|
||||
If you are working on an integration that you plan to share outside
|
||||
your organization, you can get help picking a good name in
|
||||
[#integrations][integrations-channel] in the [Zulip development
|
||||
community](https://zulip.com/development-community/).
|
||||
|
||||
## Rate-limiting response headers
|
||||
|
||||
To help clients avoid exceeding rate limits, Zulip sets the following
|
||||
HTTP headers in all API responses:
|
||||
|
||||
* `X-RateLimit-Remaining`: The number of additional requests of this
|
||||
type that the client can send before exceeding its limit.
|
||||
* `X-RateLimit-Limit`: The limit that would be applicable to a client
|
||||
that had not made any recent requests of this type. This is useful
|
||||
for designing a client's burst behavior so as to avoid ever reaching
|
||||
a rate limit.
|
||||
* `X-RateLimit-Reset`: The time at which the client will no longer
|
||||
have any rate limits applied to it (and thus could do a burst of
|
||||
`X-RateLimit-Limit` requests).
|
||||
|
||||
[Zulip's rate limiting rules are configurable][rate-limiting-rules],
|
||||
and can vary by server and over time. The default configuration
|
||||
currently limits:
|
||||
|
||||
* Every user is limited to 200 total API requests per minute.
|
||||
* Separate, much lower limits for authentication/login attempts.
|
||||
|
||||
When the Zulip server has configured multiple rate limits that apply
|
||||
to a given request, the values returned will be for the strictest
|
||||
limit.
|
||||
|
||||
[rate-limiting-rules]: https://zulip.readthedocs.io/en/latest/production/securing-your-zulip-server.html#rate-limiting
|
||||
[integrations-channel]: https://chat.zulip.org/#narrow/channel/127-integrations/
|
||||
[mdn-auth-headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Authorization
|
||||
[mdn-basic-auth]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Authorization#basic_authentication_2
|
||||
3
api_docs/include/api-admin-only.md
Normal file
3
api_docs/include/api-admin-only.md
Normal file
@@ -0,0 +1,3 @@
|
||||
!!! warn ""
|
||||
|
||||
This endpoint is only available to organization administrators.
|
||||
2
api_docs/include/api-owner-only.md
Normal file
2
api_docs/include/api-owner-only.md
Normal file
@@ -0,0 +1,2 @@
|
||||
!!! warn ""
|
||||
This endpoint is only available to organization owners.
|
||||
6
api_docs/include/api-pending-web.md
Normal file
6
api_docs/include/api-pending-web.md
Normal file
@@ -0,0 +1,6 @@
|
||||
!!! warn ""
|
||||
|
||||
**Note**: The Zulip web application implementation of this feature is
|
||||
pending. For information about the current state of this API and the
|
||||
feature's development, reach out in [our development
|
||||
community](https://chat.zulip.org).
|
||||
6
api_docs/include/curl-auth-credentials.md
Normal file
6
api_docs/include/curl-auth-credentials.md
Normal file
@@ -0,0 +1,6 @@
|
||||
The [`-u` line][curl-man-user] implements HTTP `Basic` authentication.
|
||||
See the [`Authorization` header][auth-header] documentation for how
|
||||
to get those credentials for Zulip users and bots.
|
||||
|
||||
[curl-man-user]: https://curl.se/docs/manpage.html#--user
|
||||
[auth-header]: /api/http-headers#the-authorization-header
|
||||
0
api_docs/include/empty.md
Normal file
0
api_docs/include/empty.md
Normal file
208
api_docs/include/rest-endpoints.md
Normal file
208
api_docs/include/rest-endpoints.md
Normal file
@@ -0,0 +1,208 @@
|
||||
## Messages
|
||||
|
||||
* [Send a message](/api/send-message)
|
||||
* [Upload a file](/api/upload-file)
|
||||
* [Edit a message](/api/update-message)
|
||||
* [Delete a message](/api/delete-message)
|
||||
* [Get messages](/api/get-messages)
|
||||
* [Construct a narrow](/api/construct-narrow)
|
||||
* [Add an emoji reaction](/api/add-reaction)
|
||||
* [Remove an emoji reaction](/api/remove-reaction)
|
||||
* [Render a message](/api/render-message)
|
||||
* [Fetch a single message](/api/get-message)
|
||||
* [Check if messages match a narrow](/api/check-messages-match-narrow)
|
||||
* [Get a message's edit history](/api/get-message-history)
|
||||
* [Update personal message flags](/api/update-message-flags)
|
||||
* [Update personal message flags for narrow](/api/update-message-flags-for-narrow)
|
||||
* [Mark all messages as read](/api/mark-all-as-read)
|
||||
* [Mark messages in a channel as read](/api/mark-stream-as-read)
|
||||
* [Mark messages in a topic as read](/api/mark-topic-as-read)
|
||||
* [Get a message's read receipts](/api/get-read-receipts)
|
||||
* [Get temporary URL for an uploaded file](/api/get-file-temporary-url)
|
||||
* [Check thumbnail status](/api/check-thumbnail-status)
|
||||
* [Report a message](/api/report-message)
|
||||
|
||||
## Scheduled messages
|
||||
|
||||
* [Get scheduled messages](/api/get-scheduled-messages)
|
||||
* [Create a scheduled message](/api/create-scheduled-message)
|
||||
* [Edit a scheduled message](/api/update-scheduled-message)
|
||||
* [Delete a scheduled message](/api/delete-scheduled-message)
|
||||
|
||||
## Message reminders
|
||||
|
||||
* [Create a message reminder](/api/create-message-reminder)
|
||||
* [Get reminders](/api/get-reminders)
|
||||
* [Delete a reminder](/api/delete-reminder)
|
||||
|
||||
## Drafts
|
||||
|
||||
* [Get drafts](/api/get-drafts)
|
||||
* [Create drafts](/api/create-drafts)
|
||||
* [Edit a draft](/api/edit-draft)
|
||||
* [Delete a draft](/api/delete-draft)
|
||||
* [Get all saved snippets](/api/get-saved-snippets)
|
||||
* [Create a saved snippet](/api/create-saved-snippet)
|
||||
* [Edit a saved snippet](/api/edit-saved-snippet)
|
||||
* [Delete a saved snippet](/api/delete-saved-snippet)
|
||||
|
||||
## Navigation views
|
||||
|
||||
* [Get all navigation views](/api/get-navigation-views)
|
||||
* [Add a navigation view](/api/add-navigation-view)
|
||||
* [Update the navigation view](/api/edit-navigation-view)
|
||||
* [Remove a navigation view](/api/remove-navigation-view)
|
||||
|
||||
## Channels
|
||||
|
||||
* [Get subscribed channels](/api/get-subscriptions)
|
||||
* [Subscribe to a channel](/api/subscribe)
|
||||
* [Unsubscribe from a channel](/api/unsubscribe)
|
||||
* [Get subscription status](/api/get-subscription-status)
|
||||
* [Get channel subscribers](/api/get-subscribers)
|
||||
* [Get a user's subscribed channels](/api/get-user-channels)
|
||||
* [Update a subscription setting](/api/update-subscription-property)
|
||||
* [Bulk update subscription settings](/api/update-subscription-settings)
|
||||
* [Get all channels](/api/get-streams)
|
||||
* [Get a channel by ID](/api/get-stream-by-id)
|
||||
* [Get channel ID](/api/get-stream-id)
|
||||
* [Create a channel](/api/create-channel)
|
||||
* [Update a channel](/api/update-stream)
|
||||
* [Archive a channel](/api/archive-stream)
|
||||
* [Get channel's email address](/api/get-stream-email-address)
|
||||
* [Get topics in a channel](/api/get-stream-topics)
|
||||
* [Topic muting](/api/mute-topic)
|
||||
* [Update personal preferences for a topic](/api/update-user-topic)
|
||||
* [Delete a topic](/api/delete-topic)
|
||||
* [Add a default channel](/api/add-default-stream)
|
||||
* [Remove a default channel](/api/remove-default-stream)
|
||||
* [Create a channel folder](/api/create-channel-folder)
|
||||
* [Get channel folders](/api/get-channel-folders)
|
||||
* [Reorder channel folders](/api/patch-channel-folders)
|
||||
* [Update a channel folder](/api/update-channel-folder)
|
||||
|
||||
## Users
|
||||
|
||||
* [Get a user](/api/get-user)
|
||||
* [Get a user by email](/api/get-user-by-email)
|
||||
* [Get own user](/api/get-own-user)
|
||||
* [Get users](/api/get-users)
|
||||
* [Create a user](/api/create-user)
|
||||
* [Update a user](/api/update-user)
|
||||
* [Update a user by email](/api/update-user-by-email)
|
||||
* [Deactivate a user](/api/deactivate-user)
|
||||
* [Deactivate own user](/api/deactivate-own-user)
|
||||
* [Reactivate a user](/api/reactivate-user)
|
||||
* [Get a user's status](/api/get-user-status)
|
||||
* [Update your status](/api/update-status)
|
||||
* [Update user status](/api/update-status-for-user)
|
||||
* [Update your profile data](/api/update-profile-data)
|
||||
* [Remove your profile data](/api/remove-profile-data)
|
||||
* [Upload your profile picture](/api/upload-avatar)
|
||||
* [Delete your profile picture](/api/delete-avatar)
|
||||
* [Set "typing" status](/api/set-typing-status)
|
||||
* [Set "typing" status for message editing](/api/set-typing-status-for-message-edit)
|
||||
* [Get a user's presence](/api/get-user-presence)
|
||||
* [Get presence of all users](/api/get-presence)
|
||||
* [Update your presence](/api/update-presence)
|
||||
* [Get attachments](/api/get-attachments)
|
||||
* [Delete an attachment](/api/remove-attachment)
|
||||
* [Update settings](/api/update-settings)
|
||||
* [Get user groups](/api/get-user-groups)
|
||||
* [Create a user group](/api/create-user-group)
|
||||
* [Update a user group](/api/update-user-group)
|
||||
* [Deactivate a user group](/api/deactivate-user-group)
|
||||
* [Update user group members](/api/update-user-group-members)
|
||||
* [Update subgroups of a user group](/api/update-user-group-subgroups)
|
||||
* [Get user group membership status](/api/get-is-user-group-member)
|
||||
* [Get user group members](/api/get-user-group-members)
|
||||
* [Get subgroups of a user group](/api/get-user-group-subgroups)
|
||||
* [Mute a user](/api/mute-user)
|
||||
* [Unmute a user](/api/unmute-user)
|
||||
* [Get all alert words](/api/get-alert-words)
|
||||
* [Add alert words](/api/add-alert-words)
|
||||
* [Remove alert words](/api/remove-alert-words)
|
||||
* [Regenerate your API key](/api/regenerate-api-key)
|
||||
* [Get a bot's API key](/api/get-bot-api-key)
|
||||
* [Regenerate a bot's API key](/api/regenerate-bot-api-key)
|
||||
|
||||
## Invitations
|
||||
|
||||
* [Get all invitations](/api/get-invites)
|
||||
* [Send invitations](/api/send-invites)
|
||||
* [Create a reusable invitation link](/api/create-invite-link)
|
||||
* [Resend an email invitation](/api/resend-email-invite)
|
||||
* [Revoke an email invitation](/api/revoke-email-invite)
|
||||
* [Revoke a reusable invitation link](/api/revoke-invite-link)
|
||||
|
||||
## Server & organizations
|
||||
|
||||
* [Get server settings](/api/get-server-settings)
|
||||
* [Get linkifiers](/api/get-linkifiers)
|
||||
* [Add a linkifier](/api/add-linkifier)
|
||||
* [Update a linkifier](/api/update-linkifier)
|
||||
* [Remove a linkifier](/api/remove-linkifier)
|
||||
* [Reorder linkifiers](/api/reorder-linkifiers)
|
||||
* [Add a code playground](/api/add-code-playground)
|
||||
* [Remove a code playground](/api/remove-code-playground)
|
||||
* [Get all custom emoji](/api/get-custom-emoji)
|
||||
* [Upload custom emoji](/api/upload-custom-emoji)
|
||||
* [Deactivate custom emoji](/api/deactivate-custom-emoji)
|
||||
* [Get all custom profile fields](/api/get-custom-profile-fields)
|
||||
* [Reorder custom profile fields](/api/reorder-custom-profile-fields)
|
||||
* [Create a custom profile field](/api/create-custom-profile-field)
|
||||
* [Update a custom profile field](/api/update-custom-profile-field)
|
||||
* [Delete a custom profile field](/api/delete-custom-profile-field)
|
||||
* [Update realm-level defaults of user settings](/api/update-realm-user-settings-defaults)
|
||||
* [Get allowed domains](/api/get-realm-domains)
|
||||
* [Add an allowed domain](/api/add-realm-domain)
|
||||
* [Update an allowed domain](/api/patch-realm-domain)
|
||||
* [Remove an allowed domain](/api/delete-realm-domain)
|
||||
* [Get all data exports](/api/get-realm-exports)
|
||||
* [Create a data export](/api/export-realm)
|
||||
* [Get data export consent state](/api/get-realm-export-consents)
|
||||
* [Delete a data export](/api/delete-realm-export)
|
||||
* [Test welcome bot custom message](/api/test-welcome-bot-custom-message)
|
||||
* [Deactivate an organization](/api/deactivate-realm)
|
||||
|
||||
## Real-time events
|
||||
|
||||
* [Real time events API](/api/real-time-events)
|
||||
* [Register an event queue](/api/register-queue)
|
||||
* [Get events from an event queue](/api/get-events)
|
||||
* [Delete an event queue](/api/delete-queue)
|
||||
|
||||
## Interactive bots
|
||||
|
||||
* [Get a bot's stored data](/api/get-bot-storage)
|
||||
* [Update a bot's stored data](/api/update-bot-storage)
|
||||
* [Remove a bot's stored data](/api/remove-bot-storage)
|
||||
|
||||
## Video call integrations
|
||||
|
||||
* [Create BigBlueButton video call](/api/create-big-blue-button-video-call)
|
||||
* [Create Constructor Groups video call](/api/create-constructor-groups-video-call)
|
||||
* [Create Nextcloud Talk video call](/api/create-nextcloud-talk-video-call)
|
||||
* [Create Webex video call](/api/create-webex-video-call)
|
||||
|
||||
## Mobile push notifications
|
||||
|
||||
* [Register a logged-in device](/api/register-client-device)
|
||||
* [Remove a registered device](/api/remove-client-device)
|
||||
* [Send an E2EE test notification to mobile device(s)](/api/e2ee-test-notify)
|
||||
* [Register E2EE push device](/api/register-push-device)
|
||||
* [Register E2EE push device to bouncer](/api/register-remote-push-device)
|
||||
* [Mobile notifications](/api/mobile-notifications)
|
||||
* [Send a test notification to mobile device(s)](/api/test-notify)
|
||||
* [Add an APNs device token](/api/add-apns-token)
|
||||
* [Remove an APNs device token](/api/remove-apns-token)
|
||||
* [Add an FCM registration token](/api/add-fcm-token)
|
||||
* [Remove an FCM registration token](/api/remove-fcm-token)
|
||||
|
||||
## Specialty endpoints
|
||||
|
||||
* [Fetch an API key (production)](/api/fetch-api-key)
|
||||
* [Fetch an API key (development only)](/api/dev-fetch-api-key)
|
||||
* [Fetch an API key (JWT)](/api/jwt-fetch-api-key)
|
||||
* [List users (development only)](/api/dev-list-users)
|
||||
* [Outgoing webhook payloads](/api/outgoing-webhook-payload)
|
||||
28
api_docs/index.md
Normal file
28
api_docs/index.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# The Zulip API
|
||||
|
||||
Zulip's APIs allow you to integrate other services with Zulip. This
|
||||
guide should help you find the API you need:
|
||||
|
||||
* First, check if the tool you'd like to integrate with Zulip
|
||||
[already has a native integration](/integrations/).
|
||||
* Next, check if [Zapier](https://zapier.com/apps) or
|
||||
[IFTTT](https://ifttt.com/search) has an integration.
|
||||
[Zulip's Zapier integration](/integrations/zapier) and
|
||||
[Zulip's IFTTT integration](/integrations/ifttt) often allow
|
||||
integrating a new service with Zulip without writing any code.
|
||||
* If you'd like to send content into Zulip, you can
|
||||
[write a native incoming webhook integration][incoming-webhooks-overview]
|
||||
or use [Zulip's API for sending messages](/api/send-message).
|
||||
* If you're building an interactive bot that reacts to activity inside
|
||||
Zulip, you'll want to look at Zulip's
|
||||
[Python framework for interactive bots](/help/running-bots) or
|
||||
[Zulip's real-time events API](/api/get-events).
|
||||
|
||||
And if you still need to build your own integration with Zulip, check out
|
||||
the full [REST API](/api/rest), generally starting with
|
||||
[installing the API client bindings](/api/installation-instructions).
|
||||
|
||||
In case you already know how you want to build your integration and you're
|
||||
just looking for an API key, we've got you covered [here](/api/api-keys).
|
||||
|
||||
[incoming-webhooks-overview]: https://zulip.readthedocs.io/en/latest/webhooks/incoming-webhooks-overview.html
|
||||
46
api_docs/installation-instructions.md
Normal file
46
api_docs/installation-instructions.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# Installation instructions
|
||||
|
||||
Zulip's REST API is easy to work with directly, but there are API
|
||||
libraries available for a few popular languages.
|
||||
|
||||
The Python library is the most advanced (and has tools for easily
|
||||
writing interactive bots that react to messages), so we recommend it
|
||||
if you're trying to decide.
|
||||
|
||||
{start_tabs}
|
||||
{tab|python}
|
||||
|
||||
Install the Python API with [pip](https://pypi.python.org/pypi/zulip/):
|
||||
|
||||
```
|
||||
pip install zulip
|
||||
```
|
||||
|
||||
{tab|zulip-send}
|
||||
|
||||
Included with the Python bindings:
|
||||
|
||||
```
|
||||
pip install zulip
|
||||
```
|
||||
|
||||
{tab|js}
|
||||
|
||||
Install the JavaScript API with [npm](https://www.npmjs.com/package/zulip-js):
|
||||
|
||||
```
|
||||
npm install zulip-js
|
||||
```
|
||||
|
||||
{tab|curl}
|
||||
|
||||
No download required!
|
||||
|
||||
{end_tabs}
|
||||
|
||||
See also [user-contributed client libraries](/api/client-libraries)
|
||||
for many other languages.
|
||||
|
||||
## Related articles
|
||||
|
||||
* [Configuring the Python bindings](/api/configuring-python-bindings)
|
||||
630
api_docs/message-formatting.md
Normal file
630
api_docs/message-formatting.md
Normal file
@@ -0,0 +1,630 @@
|
||||
# Message formatting
|
||||
|
||||
Zulip supports an extended version of Markdown for messages, as well as
|
||||
some HTML level special behavior. The Zulip help center article on [message
|
||||
formatting](/help/format-your-message-using-markdown) is the primary
|
||||
documentation for Zulip's markup features. This article is currently a
|
||||
changelog for updates to these features.
|
||||
|
||||
The [render a message](/api/render-message) endpoint can be used to get
|
||||
the current HTML version of any Markdown syntax for message content.
|
||||
|
||||
## Code blocks
|
||||
|
||||
**Changes**: As of Zulip 4.0 (feature level 33), [code blocks][help-code]
|
||||
can have a `data-code-language` attribute attached to the outer HTML
|
||||
`div` element, which records the programming language that was selected
|
||||
for syntax highlighting. This field is used in the
|
||||
[playgrounds][help-playgrounds] feature for code blocks.
|
||||
|
||||
## Global times
|
||||
|
||||
**Changes**: In Zulip 13.0 (feature level 503), the global time
|
||||
syntax only recognizes ISO 8601 formatted timestamps.
|
||||
|
||||
**Changes**: In Zulip 12.0 (feature level 451), invalid timestamp formats
|
||||
are now rendered as escaped literal text instead of a `<span>` element with
|
||||
`timestamp-error` class and an error message.
|
||||
|
||||
Previously, an invalid timestamp string would be rendered as:
|
||||
``` html
|
||||
<span class="timestamp-error">Invalid time format: invalid</span>
|
||||
```
|
||||
Now, it is rendered as:
|
||||
``` html
|
||||
<time:invalid>
|
||||
```
|
||||
|
||||
**Changes**: In Zulip 3.0 (feature level 8), added [global time
|
||||
mentions][help-global-time] to supported Markdown message formatting
|
||||
features.
|
||||
|
||||
## Links to channels, topics, and messages
|
||||
|
||||
Zulip's markup supports special readable Markdown syntax for [linking
|
||||
to channels, topics, and
|
||||
messages](/help/link-to-a-message-or-conversation). See also [Zulip
|
||||
URLs](/api/zulip-urls)
|
||||
|
||||
Sample HTML formats are as follows:
|
||||
``` html
|
||||
<!-- Syntax: #**announce** -->
|
||||
<a class="stream" data-stream-id="9"
|
||||
href="/#narrow/channel/9-announce">
|
||||
#announce
|
||||
</a>
|
||||
|
||||
<!-- Syntax: #**announce>Zulip updates** -->
|
||||
<a class="stream-topic" data-stream-id="9"
|
||||
href="/#narrow/channel/9-announce/topic/Zulip.20updates/with/214">
|
||||
#announce > Zulip updates
|
||||
</a>
|
||||
|
||||
<!-- Syntax: #**announce>Zulip updates**
|
||||
Generated only if topic had no messages or the link was rendered
|
||||
before Zulip 10.0 (feature level 347) -->
|
||||
<a class="stream-topic" data-stream-id="9"
|
||||
href="/#narrow/channel/9-announce/topic/Zulip.20updates">
|
||||
#announce > Zulip updates
|
||||
</a>
|
||||
|
||||
<!-- Syntax: #**announce>Zulip updates@214** -->
|
||||
<a class="message-link"
|
||||
href="/#narrow/channel/9-announce/topic/Zulip.20updates/near/214">
|
||||
#announce > Zulip updates @ 💬
|
||||
</a>
|
||||
```
|
||||
|
||||
The `near` and `with` operators are documented in more detail in the
|
||||
[search and URL documentation](/api/construct-narrow). When rendering
|
||||
topic links with the `with` operator, the code doing the rendering may
|
||||
pick the ID arbitrarily among messages accessible to the client and/or
|
||||
acting user at the time of rendering. Currently, the server chooses
|
||||
the message ID to use for `with` operators as the latest message ID in
|
||||
the topic accessible to the user who wrote the message.
|
||||
|
||||
The older stream/topic link elements include a `data-stream-id`, which
|
||||
historically was used in order to display the current channel name if
|
||||
the channel had been renamed. That field is **deprecated**, because
|
||||
displaying an updated value for the most common forms of this syntax
|
||||
requires parsing the URL to get the topic to use anyway.
|
||||
|
||||
When a topic is an empty string, it is replaced with
|
||||
`realm_empty_topic_display_name` found in the [`POST /register`](/api/register-queue)
|
||||
response and wrapped with the `<em>` tag.
|
||||
|
||||
Sample HTML formats with `"realm_empty_topic_display_name": "general chat"`
|
||||
are as follows:
|
||||
```html
|
||||
<!-- Syntax: #**announce>** -->
|
||||
<a class="stream-topic" data-stream-id="9"
|
||||
href="/#narrow/channel/9-announce/topic/with/214">
|
||||
#announce > <em>general chat</em>
|
||||
</a>
|
||||
|
||||
<!-- Syntax: #**announce>**
|
||||
Generated only if topic had no messages or the link was rendered
|
||||
before Zulip 10.0 (feature level 347) -->
|
||||
<a class="stream-topic" data-stream-id="9"
|
||||
href="/#narrow/channel/9-announce/topic/">
|
||||
#announce > <em>general chat</em>
|
||||
</a>
|
||||
|
||||
<!-- Syntax: #**announce>@214** -->
|
||||
<a class="message-link"
|
||||
href="/#narrow/channel/9-announce/topic//near/214">
|
||||
#announce > <em>general chat</em> @ 💬
|
||||
</a>
|
||||
```
|
||||
|
||||
**Changes**: In Zulip 11.0 (feature level 400), the server switched
|
||||
its strategy for `with` URL construction to choose the latest
|
||||
accessible message ID in a topic. Previously, it used the oldest.
|
||||
|
||||
Before Zulip 10.0 (feature level 347), the `with` field
|
||||
was never used in topic link URLs generated by the server; the markup
|
||||
currently used only for empty topics was used for all topic links.
|
||||
|
||||
Before Zulip 10.0 (feature level 346), empty string
|
||||
was not a valid topic name in syntaxes for linking to topics and
|
||||
messages.
|
||||
|
||||
In Zulip 10.0 (feature level 319), added Markdown syntax
|
||||
for linking to a specific message in a conversation. Declared the
|
||||
`data-stream-id` field to be deprecated as detailed above.
|
||||
|
||||
In Zulip 11.0 (feature level 383), clients can decide what
|
||||
channel view a.stream channel link elements take you to -- i.e.,
|
||||
the href for those is the default behavior of the link that also
|
||||
encodes the channel alongside the data-stream-id field, but clients
|
||||
can override that default based on `web_channel_default_view` setting.
|
||||
|
||||
## Emoji
|
||||
|
||||
Zulip's [emoji][help-emoji] support includes standard Unicode emoji, a
|
||||
built-in Zulip custom emoji like `:zulip:` and [custom realm
|
||||
emoji][help-custom-emoji]. To maximize legibility, emoji should be
|
||||
displayed inline with text, at the maximum size that does not
|
||||
interfere with line spacing.
|
||||
|
||||
**Large emoji**. Clients are recommended to display single-paragraph
|
||||
messages that contain only emoji elements with a greatly increased
|
||||
size. For example, Zulip the web app scales large emoji to be 2x the
|
||||
size of other message emoji.
|
||||
|
||||
Unicode emoji, such as `:smiling_face:` (☺️ / `263a`), are represented
|
||||
in the HTML by spans with the following format:
|
||||
|
||||
```html
|
||||
<span aria-label="smiling face" class="emoji emoji-263a" role="img"
|
||||
title="smiling face">:smiling_face:</span>
|
||||
```
|
||||
|
||||
Note that Unicode emoji in messages that were originally sent on Zulip
|
||||
versions older than Zulip 1.9.2 will not have the `role` or
|
||||
`aria-label` attributes. Thus, clients should not rely on those fields
|
||||
existing.
|
||||
|
||||
The `server_emoji_data_url` key in the [`POST
|
||||
/register`](/api/register-queue) response contains the server's
|
||||
mapping between Unicode codepoints and emoji names.
|
||||
|
||||
Custom emoji are represented in the HTML by image tags that also use
|
||||
the `.emoji` class. The `src` URL should be resolved with respect to
|
||||
the Zulip server's hostname:
|
||||
|
||||
```html
|
||||
<-- Configured realm-specific custom emoji -->
|
||||
<img alt=":example_custom_emoji:" class="emoji" title="example_custom_emoji"
|
||||
src="/user_avatars/2/emoji/images/dbe43627.png">
|
||||
|
||||
<-- Built-in custom emoji like :zulip: -->
|
||||
<img alt=":zulip:" class="emoji" title="zulip"
|
||||
src="/static/generated/emoji/images/emoji/unicode/zulip.png">
|
||||
```
|
||||
|
||||
**Changes**: Large emoji are new in Zulip 12.0 (feature level 436).
|
||||
|
||||
## Images
|
||||
|
||||
When a Zulip message is sent with a link to an uploaded image, Zulip will
|
||||
also insert an image preview element with the following format:
|
||||
|
||||
``` html
|
||||
<div class="message_inline_image">
|
||||
<a href="/user_uploads/path/to/example.png" title="example.png">
|
||||
<img data-original-dimensions="1920x1080"
|
||||
data-original-content-type="image/png"
|
||||
src="/user_uploads/thumbnail/path/to/example.png/840x560.webp">
|
||||
</a>
|
||||
</div>
|
||||
```
|
||||
|
||||
Clients can recognize if an image was thumbnailed by its `src`
|
||||
attribute starting with `/user_uploads/thumbnail/`. The `href` will
|
||||
always link to the originally-uploaded file, at its original
|
||||
resolution.
|
||||
|
||||
When a Zulip message is sent referencing an **uploaded image** in Markdown
|
||||
image syntax, (e.g.,``),
|
||||
Zulip will generate an image element with the following format:
|
||||
|
||||
```html
|
||||
<img alt="example image" class="inline-image"
|
||||
data-original-dimensions="1050x700"
|
||||
data-original-content-type="image/png"
|
||||
data-original-src="/user_uploads/path/to/example.png"
|
||||
src="/user_uploads/thumbnail/path/to/example.png/840x560.webp">
|
||||
```
|
||||
|
||||
Note that the Markdown image syntax is only supported/permitted for
|
||||
uploaded images, not third-party image URLs.
|
||||
|
||||
As with link-derived image previews, clients can recognize if an image
|
||||
was thumbnailed by its `src` attribute starting with
|
||||
`/user_uploads/thumbnail/`. If an image is a thumbnail, the
|
||||
`data-original-src` attribute will always reference the
|
||||
originally-uploaded file, at its original resolution.
|
||||
|
||||
Note that images generated using Markdown image syntax may appear
|
||||
inside arbitrary block-level elements, unlike the image previews from
|
||||
links, which will always be top-level elements.
|
||||
|
||||
Regardless of which form (link-derived preview, or Markdown image
|
||||
syntax), the `data-original-dimensions` and
|
||||
`data-original-content-type` attributes will only be present if the
|
||||
image was thumbnailed and the message was sent (or last edited)
|
||||
after those attributes were added (see [Changes to image
|
||||
formatting](#changes-to-image-formatting)). If the image is *not* a
|
||||
thumbnail, clients should make a best-effort attempt to render the
|
||||
given `src`, in a manner which minimizes layout shift when the
|
||||
resource is loaded -- see the next section for a special case of this.
|
||||
|
||||
**Changes**: See [Changes to image formatting](#changes-to-image-formatting).
|
||||
|
||||
### Image-loading placeholders
|
||||
|
||||
If the server has yet to generate thumbnails for the image by the time
|
||||
the message is sent, the `img` element will temporarily reference a
|
||||
loading indicator image and have the `image-loading-placeholder`
|
||||
class, which clients can use to identify loading indicators and
|
||||
replace them with a more native loading indicator element if desired.
|
||||
This spinner placeholder will have `data-original-dimensions`
|
||||
and `data-original-content-type` attributes
|
||||
if the message was sent (or last edited) after those attributes were added
|
||||
(see [Changes to image formatting](#changes-to-image-formatting)).
|
||||
|
||||
In link-derived image previews, the placeholder is structured like this:
|
||||
|
||||
``` html
|
||||
<div class="message_inline_image">
|
||||
<a href="/user_uploads/path/to/example.png" title="example.png">
|
||||
<img class="image-loading-placeholder"
|
||||
data-original-dimensions="1920x1080"
|
||||
data-original-content-type="image/png"
|
||||
src="/path/to/spinner.png">
|
||||
</a>
|
||||
</div>
|
||||
```
|
||||
|
||||
For image elements presented in Markdown image syntax, this placeholder
|
||||
structure is used:
|
||||
|
||||
```html
|
||||
<img alt="example image"
|
||||
class="inline-image image-loading-placeholder"
|
||||
data-original-content-type="image/png"
|
||||
data-original-dimensions="1050x700"
|
||||
data-original-src="/user_uploads/path/to/example.png"
|
||||
src="/path/to/spinner.png">
|
||||
```
|
||||
|
||||
Once the server has a working thumbnail, such messages will be updated
|
||||
via an `update_message` event, with the `rendering_only: true` flag
|
||||
(telling clients not to adjust message edit history), with appropriate
|
||||
adjusted `rendered_content`. A client should process those events by
|
||||
just using the updated rendering. If thumbnailing failed, the same
|
||||
type of event will edit the message's rendered form to remove the
|
||||
image preview element, so no special client-side logic should be
|
||||
required to process such errors.
|
||||
|
||||
Note that in the uncommon situation that the thumbnailing system is
|
||||
backlogged, an individual message containing multiple image previews
|
||||
may be re-rendered multiple times as each image finishes thumbnailing
|
||||
and triggers a message update.
|
||||
|
||||
Clients displaying message-edit history should rewrite image-loading
|
||||
placeholder images in edit history to the generic deleted-file image
|
||||
(`/static/images/errors/image-not-exist.png`).
|
||||
|
||||
### Transcoded images
|
||||
|
||||
Image elements whose formats are not widely supported by web browsers
|
||||
(e.g., HEIC and TIFF) may contain a `data-transcoded-image` attribute,
|
||||
which specifies a high-resolution thumbnail format that clients may
|
||||
opt to present instead of the original image. If the
|
||||
`data-transcoded-image` attribute is present, clients should use the
|
||||
`data-original-content-type` attribute to decide whether to display the
|
||||
original image or use the transcoded version.
|
||||
|
||||
Transcoded images are presented with this structure in image previews:
|
||||
|
||||
``` html
|
||||
<div class="message_inline_image">
|
||||
<a href="/user_uploads/path/to/example.heic" title="example.heic">
|
||||
<img data-original-dimensions="1920x1080"
|
||||
data-original-content-type="image/heic"
|
||||
data-transcoded-image="1920x1080.webp"
|
||||
src="/user_uploads/thumbnail/path/to/example.heic/840x560.webp">
|
||||
</a>
|
||||
</div>
|
||||
```
|
||||
|
||||
Transcoded images presented in Markdown image syntax are structured like this:
|
||||
|
||||
```html
|
||||
<img alt="example HEIC image" class="inline-image"
|
||||
data-original-dimensions="1920x1080"
|
||||
data-original-content-type="image/heic"
|
||||
data-original-src="/user_uploads/path/to/example.heic"
|
||||
data-transcoded-image="1920x1080.webp"
|
||||
src="/user_uploads/thumbnail/path/to/example.heic/840x560.webp">
|
||||
```
|
||||
|
||||
### Recommended client processing of image previews
|
||||
|
||||
Clients are recommended to do the following when processing image
|
||||
previews:
|
||||
|
||||
- Clients that would like to use the image's aspect ratio to lay out
|
||||
one or more images in the message feed may use the
|
||||
`data-original-dimensions` attribute, which is present even if the
|
||||
image is a placeholder spinner. This attribute encodes the
|
||||
dimensions of the original image as `{width}x{height}`. These
|
||||
dimensions are for the image as rendered, _after_ any EXIF rotation
|
||||
and mirroring has been applied.
|
||||
- If the client would like to control the thumbnail resolution used,
|
||||
it can replace the final section of the URL (`840x560.webp` in the
|
||||
example above) with the `name` of its preferred format from the set
|
||||
of supported formats provided by the server in the
|
||||
`server_thumbnail_formats` portion of the `register`
|
||||
response. Clients should not make any assumptions about what format
|
||||
the server will use as the "default" thumbnail resolution, as it may
|
||||
change over time.
|
||||
- Download button type elements should provide the original image
|
||||
(encoded via the `href` of the containing `a` tag).
|
||||
- The content-type of the original image is provided on a
|
||||
`data-original-content-type` attribute, so clients can decide if
|
||||
they are capable of rendering the original image.
|
||||
- For images whose formats which are not widely-accepted by browsers
|
||||
(e.g., HEIC and TIFF), the image may contain a
|
||||
`data-transcoded-image` attribute, which specifies a high-resolution
|
||||
thumbnail format which clients may use instead of the original
|
||||
image.
|
||||
- Lightbox elements for viewing an image should be designed to
|
||||
immediately display any already-downloaded thumbnail while fetching
|
||||
the original-quality image or an appropriate higher-quality
|
||||
thumbnail from the server, to be transparently swapped in once it is
|
||||
available. Clients that would like to size the lightbox based on the
|
||||
size of the original image can use the `data-original-dimensions`
|
||||
attribute, as described above.
|
||||
- Animated images will have a `data-animated` attribute on the `img`
|
||||
tag. As detailed in `server_thumbnail_formats`, both animated and
|
||||
still images are available for clients to use, depending on their
|
||||
preference. See, for example, the [web setting][help-previews]
|
||||
to control whether animated images are autoplayed in the message
|
||||
feed.
|
||||
- Clients should not assume that the requested format is the format
|
||||
that they will receive; in rare cases where the client has an
|
||||
out-of-date list of `server_thumbnail_formats`, the server will
|
||||
provide an approximation of the client's requested format. Because
|
||||
of this, clients should not assume that the pixel dimensions or file
|
||||
format match what they requested.
|
||||
- No other processing of the URLs is recommended.
|
||||
|
||||
### Changes to image formatting
|
||||
|
||||
**In Zulip 12.0** (feature level 467), limited the Markdown
|
||||
image syntax to only support uploaded images, not linking to
|
||||
third-party image URLs.
|
||||
|
||||
**In Zulip 12.0** (feature level 437), added support for Markdown
|
||||
image syntax, in addition to the previous link-derived image previews;
|
||||
these can be inserted into any block-level element.
|
||||
|
||||
**In Zulip 10.0** (feature level 336), added
|
||||
`data-original-content-type` attribute to convey the type of the
|
||||
original image, and optional `data-transcoded-image` attribute for
|
||||
images with formats which are not widely supported by browsers.
|
||||
|
||||
**In Zulip 9.2** (feature levels 278-279, and 287+), added
|
||||
`data-original-dimensions` to the `image-loading-placeholder` spinner
|
||||
images, containing the dimensions of the original image.
|
||||
|
||||
**In Zulip 9.0** (feature level 276), added `data-original-dimensions`
|
||||
attribute to images that have been thumbnailed, containing the
|
||||
dimensions of the full-size version of the image. Thumbnailing itself
|
||||
was reintroduced at feature level 275.
|
||||
|
||||
Previously, with the exception of Zulip servers that used the beta
|
||||
Thumbor-based implementation years ago, all image previews in Zulip
|
||||
messages were not thumbnailed; the `a` tag and the `img` tag would both
|
||||
point to the original image.
|
||||
|
||||
Clients that correctly implement the current API should handle
|
||||
Thumbor-based older thumbnails correctly, as long as they do not
|
||||
assume that `data-original-dimensions` is present. Clients should not
|
||||
assume that messages sent prior to the introduction of thumbnailing
|
||||
have been re-rendered to use the new format or have thumbnails
|
||||
available.
|
||||
|
||||
## Video embeddings and previews
|
||||
|
||||
When a Zulip message is sent linking to an uploaded video, Zulip may
|
||||
generate a video preview element with the following format. Supported
|
||||
MIME types are `video/mp4`, `video/quicktime` (i.e., `.mov` files), and
|
||||
`video/webm`. Because `video/quicktime` is not supported in every
|
||||
browser, the preview element is hidden at render time when the browser
|
||||
reports that it cannot play the video; the download link in the
|
||||
surrounding `a` tag remains available.
|
||||
|
||||
|
||||
``` html
|
||||
<div class="message_inline_image message_inline_video">
|
||||
<a href="/user_uploads/path/to/video.mp4">
|
||||
<video preload="metadata" src="/user_uploads/path/to/video.mp4">
|
||||
</video>
|
||||
</a>
|
||||
</div>
|
||||
```
|
||||
|
||||
## Audio Players
|
||||
|
||||
When the Markdown media syntax is used with an uploaded file with an
|
||||
audio `Content-Type`, Zulip will generate an HTML5 `<audio>` player
|
||||
element. Supported MIME types are currently `audio/aac`, `audio/flac`,
|
||||
`audio/mpeg`, and `audio/wav` (and its `audio/x-wav` and
|
||||
`audio/vnd.wave` variants).
|
||||
|
||||
For example, `` renders as:
|
||||
|
||||
``` html
|
||||
<audio controls preload="metadata"
|
||||
src="/user_uploads/path/to/file.mp3" title="file.mp3">
|
||||
</audio>
|
||||
```
|
||||
|
||||
If the Zulip server has rewritten the URL of the audio file, it will
|
||||
provide the URL in a `data-original-url` parameter. The Zulip server
|
||||
does this for all non-uploaded file audio URLs.
|
||||
|
||||
``` html
|
||||
<audio controls preload="metadata"
|
||||
data-original-url="https://example.com/path/to/original/file.mp3"
|
||||
src="https://zulipcdn.example.com/path/to/playable/file.mp3" title="file.mp3">
|
||||
</audio>
|
||||
```
|
||||
|
||||
Clients that cannot render an audio player are recommended to convert
|
||||
audio elements into a link to the original URL.
|
||||
|
||||
The Zulip server does not validate whether uploaded files with an
|
||||
audio `Content-Type` are actually playable.
|
||||
|
||||
**Changes**: New in Zulip 11.0 (feature level 405).
|
||||
|
||||
## Mentions and silent mentions
|
||||
|
||||
Zulip markup supports [mentioning](/help/mention-a-user-or-group)
|
||||
users, user groups, and a few special "wildcard" mentions (the three
|
||||
spellings of a channel wildcard mention: `@**all**`, `@**everyone**`,
|
||||
`@**channel**` and the topic wildcard mention `@**topic**`).
|
||||
|
||||
Mentions result in a message being highlighted for the target user(s),
|
||||
both in the UI and in notifications, and may also result in the target
|
||||
user(s) following the conversation, [depending on their
|
||||
settings](/help/follow-a-topic#follow-topics-where-you-are-mentioned).
|
||||
|
||||
Silent mentions of users or groups have none of those side effects,
|
||||
but nonetheless uniquely identify the user or group
|
||||
identified. (There's no such thing as a silent wildcard mention).
|
||||
|
||||
Permissions for mentioning users work as follows:
|
||||
|
||||
- Any user can mention any other user, though mentions by [muted
|
||||
users](/help/mute-a-user) are automatically marked as read and thus do
|
||||
not trigger notifications or otherwise get highlighted like unread
|
||||
mentions.
|
||||
|
||||
- Wildcard mentions are permitted except where [organization-level
|
||||
restrictions](/help/restrict-wildcard-mentions) apply.
|
||||
|
||||
- User groups can be mentioned if and only if the acting user is in
|
||||
the `can_mention_group` group for that group. All user groups can be
|
||||
silently mentioned by any user.
|
||||
|
||||
- System groups, when (silently) mentioned, should be displayed using
|
||||
their description, not their `role:nobody` style API names; see the
|
||||
main [system group
|
||||
documentation](/api/group-setting-values#system-groups) for
|
||||
details. System groups can only be silently mentioned right now,
|
||||
because they happen to all use the empty `Nobody` group for
|
||||
`can_mention_group`; clients should just use `can_mention_group` to
|
||||
determine which groups to offer in typeahead in similar contexts.
|
||||
|
||||
- Requests to send or edit a message that are impermissible due to
|
||||
including a mention where the acting user does not have permission to
|
||||
mention the target will return an error. Mention syntax that does not
|
||||
correspond to a real user or group is ignored.
|
||||
|
||||
Sample markup for `@**Example User**`:
|
||||
|
||||
``` html
|
||||
<span class="user-mention" data-user-id="31">@Example User</span>
|
||||
```
|
||||
|
||||
Sample markup for `@_**Example User**`:
|
||||
|
||||
``` html
|
||||
<span class="user-mention silent" data-user-id="31">Example User</span>
|
||||
```
|
||||
|
||||
Sample markup for `@**topic**`:
|
||||
|
||||
``` html
|
||||
<span class="topic-mention">@topic</span>
|
||||
```
|
||||
|
||||
Sample markup for `@**channel**`:
|
||||
|
||||
``` html
|
||||
<span class="user-mention channel-wildcard-mention"
|
||||
data-user-id="*">@channel</span>
|
||||
```
|
||||
|
||||
Sample markup for `@*support*`, assuming "support" is a valid group:
|
||||
``` html
|
||||
<span class="user-group-mention"
|
||||
data-user-group-id="17">@support</span>
|
||||
```
|
||||
|
||||
Sample markup for `@_*support*`, assuming "support" is a valid group:
|
||||
``` html
|
||||
<span class="user-group-mention silent"
|
||||
data-user-group-id="17">support</span>
|
||||
```
|
||||
|
||||
Sample markup for `@_*role:administrators*`:
|
||||
``` html
|
||||
<span class="user-group-mention silent"
|
||||
data-user-group-id="5">Administrators</span>
|
||||
```
|
||||
|
||||
When processing mentions, clients should look up the user or group
|
||||
referenced by ID, and update the textual name for the mention to the
|
||||
current name for the user or group with that ID. Note that for system
|
||||
groups, this requires special logic to look up the user-facing name
|
||||
for that group; see [system
|
||||
groups](/api/group-setting-values#system-groups) for details.
|
||||
|
||||
**Changes**: Prior to Zulip 10.0 (feature level 333), it was not
|
||||
possible to silently mention [system
|
||||
groups](/api/group-setting-values#system-groups).
|
||||
|
||||
In Zulip 9.0 (feature level 247), `channel` was added to the supported
|
||||
[wildcard][help-mention-all] options used in the
|
||||
[mentions][help-mentions] Markdown message formatting feature.
|
||||
|
||||
## Spoilers
|
||||
|
||||
**Changes**: In Zulip 3.0 (feature level 15), added
|
||||
[spoilers][help-spoilers] to supported Markdown message formatting
|
||||
features.
|
||||
|
||||
## Removed features
|
||||
|
||||
### Removed legacy Dropbox link preview markup
|
||||
|
||||
In Zulip 11.0 (feature level 395), the Zulip server stopped generating
|
||||
legacy Dropbox link previews. Dropbox links are now previewed just
|
||||
like standard Zulip image/link previews. However, some legacy Dropbox
|
||||
previews may exist in existing messages.
|
||||
|
||||
Clients are recommended to prune these previews from message HTML;
|
||||
since they always appear after the actual link, there is no loss of
|
||||
information/functionality. They can be recognized via the classes
|
||||
`message_inline_ref`, `message_inline_image_desc`, and
|
||||
`message_inline_image_title`:
|
||||
|
||||
``` html
|
||||
<div class="message_inline_ref">
|
||||
<a href="https://www.dropbox.com/sh/cm39k9e04z7fhim/AAAII5NK-9daee3FcF41anEua?dl=" title="Saves">
|
||||
<img src="/path/to/folder_dropbox.png">
|
||||
</a>
|
||||
<div><div class="message_inline_image_title">Saves</div>
|
||||
<desc class="message_inline_image_desc"></desc>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
### Removed legacy avatar markup
|
||||
|
||||
In Zulip 4.0 (feature level 24), the rarely used `!avatar()`
|
||||
and `!gravatar()` markup syntax, which was never documented and had an
|
||||
inconsistent syntax, were removed.
|
||||
|
||||
## Related articles
|
||||
|
||||
* [Markdown formatting](/help/format-your-message-using-markdown)
|
||||
* [Send a message](/api/send-message)
|
||||
* [Render a message](/api/render-message)
|
||||
|
||||
[help-code]: /help/code-blocks
|
||||
[help-emoji]: /help/emoji-and-emoticons
|
||||
[help-custom-emoji]: /help/custom-emoji
|
||||
[help-playgrounds]: /help/code-blocks#code-playgrounds
|
||||
[help-spoilers]: /help/spoilers
|
||||
[help-global-time]: /help/global-times
|
||||
[help-mentions]: /help/mention-a-user-or-group
|
||||
[help-mention-all]: /help/mention-a-user-or-group#mention-everyone-on-a-channel
|
||||
[help-previews]: /help/image-video-and-website-previews#configure-how-animated-images-are-played
|
||||
1
api_docs/missing.md
Normal file
1
api_docs/missing.md
Normal file
@@ -0,0 +1 @@
|
||||
No such article.
|
||||
225
api_docs/mobile-notifications.md
Normal file
225
api_docs/mobile-notifications.md
Normal file
@@ -0,0 +1,225 @@
|
||||
# Mobile notifications
|
||||
|
||||
Zulip Server 11.0+ supports end-to-end encryption (E2EE) for mobile
|
||||
push notifications. Mobile push notifications sent by all Zulip
|
||||
servers go through Zulip's mobile push notifications service, which
|
||||
then delivers the notifications through the appropriate
|
||||
platform-specific push notification service (Google's FCM or Apple's
|
||||
APNs). E2EE push notifications ensure that mobile notification message
|
||||
content and metadata is not visible to intermediaries.
|
||||
|
||||
Mobile clients that have [registered an E2EE push
|
||||
device](/api/register-push-device) will receive mobile notifications
|
||||
end-to-end encrypted by their Zulip server.
|
||||
|
||||
This page documents the format of the encrypted JSON-format payloads
|
||||
that the client will receive through this protocol. The same encrypted
|
||||
payload formats are used for both Firebase Cloud Messaging (FCM) and
|
||||
Apple Push Notification service (APNs).
|
||||
|
||||
## Payload examples
|
||||
|
||||
### New channel message
|
||||
|
||||
Sample JSON data that gets encrypted:
|
||||
```json
|
||||
{
|
||||
"channel_id": 10,
|
||||
"channel_name": "Denmark",
|
||||
"content": "@test_user_group",
|
||||
"mentioned_user_group_id": 41,
|
||||
"mentioned_user_group_name": "test_user_group",
|
||||
"message_id": 45,
|
||||
"realm_name": "Zulip Dev",
|
||||
"realm_url": "http://zulip.testserver",
|
||||
"recipient_type": "channel",
|
||||
"sender_avatar_url": "https://secure.gravatar.com/avatar/818c212b9f8830dfef491b3f7da99a14?d=identicon&version=1",
|
||||
"sender_full_name": "aaron",
|
||||
"sender_id": 6,
|
||||
"time": 1754385395,
|
||||
"topic": "test",
|
||||
"type": "message",
|
||||
"user_id": 10
|
||||
}
|
||||
```
|
||||
|
||||
- The `mentioned_user_group_id` and `mentioned_user_group_name` fields
|
||||
are only present for messages that mention a group containing the
|
||||
current user, and triggered a mobile notification because of that
|
||||
group mention. For example, messages that mention both the user
|
||||
directly and a group containing the user, these fields will not be
|
||||
present in the payload, because the direct mention has precedence.
|
||||
|
||||
**Changes**: New in Zulip 11.0 (feature level 413).
|
||||
|
||||
### New direct message
|
||||
|
||||
Sample JSON data that gets encrypted:
|
||||
```json
|
||||
{
|
||||
"content": "test content",
|
||||
"message_id": 46,
|
||||
"realm_name": "Zulip Dev",
|
||||
"realm_url": "http://zulip.testserver",
|
||||
"recipient_type": "direct",
|
||||
"recipient_user_ids": [6,10,12,15],
|
||||
"sender_avatar_url": "https://secure.gravatar.com/avatar/818c212b9f8830dfef491b3f7da99a14?d=identicon&version=1",
|
||||
"sender_full_name": "aaron",
|
||||
"sender_id": 6,
|
||||
"time": 1754385290,
|
||||
"type": "message",
|
||||
"user_id": 10
|
||||
}
|
||||
```
|
||||
|
||||
- The `recipient_user_ids` field is a sorted array of all user IDs in
|
||||
the direct message conversation, including both `user_id` and
|
||||
`sender_id`.
|
||||
|
||||
**Changes**: In Zulip 12.0 (feature level 429), replaced the
|
||||
`pm_users` field with `recipient_user_ids`. The old `pm_users` field
|
||||
was only present for group DMs, and was a string containing a
|
||||
comma-separated list of sorted user IDs.
|
||||
|
||||
New in Zulip 11.0 (feature level 413).
|
||||
|
||||
### Remove notifications
|
||||
|
||||
When a batch of messages that had previously been included in mobile
|
||||
notifications are marked as read, are deleted, become inaccessible, or
|
||||
otherwise should no longer be displayed to the user, a removal
|
||||
notification is sent.
|
||||
|
||||
Sample JSON data that gets encrypted:
|
||||
```json
|
||||
{
|
||||
"message_ids": [
|
||||
31,
|
||||
32
|
||||
],
|
||||
"realm_name": "Zulip Dev",
|
||||
"realm_url": "http://zulip.testserver",
|
||||
"type": "remove",
|
||||
"user_id": 10
|
||||
}
|
||||
```
|
||||
|
||||
[zulip-bouncer]: https://zulip.readthedocs.io/en/latest/production/mobile-push-notifications.html#mobile-push-notification-service
|
||||
|
||||
**Changes**: New in Zulip 11.0 (feature level 413).
|
||||
|
||||
### Test push notification
|
||||
|
||||
A user can trigger [sending an E2EE test push notification](/api/e2ee-test-notify)
|
||||
to the user's selected mobile device or all of their mobile devices.
|
||||
|
||||
Sample JSON data that gets encrypted:
|
||||
```json
|
||||
{
|
||||
"realm_name": "Zulip Dev",
|
||||
"realm_url": "http://zulip.testserver",
|
||||
"time": 1754577820,
|
||||
"type": "test",
|
||||
"user_id": 10
|
||||
}
|
||||
```
|
||||
|
||||
**Changes**: New in Zulip 11.0 (feature level 420).
|
||||
|
||||
### Data sent to Zulip's push notifications service
|
||||
|
||||
Sample JSON data sent by a self-hosted server to the Zulip's push notifications service:
|
||||
```json
|
||||
{
|
||||
"realm_uuid": "e502dde1-74fc-44b3-9e3a-114c41ed3ea4",
|
||||
"push_requests": [
|
||||
{
|
||||
"token_id": "AAAAAAAAAAE=",
|
||||
"http_headers": {
|
||||
"apns_priority": 10,
|
||||
"apns_push_type": "alert"
|
||||
},
|
||||
"payload": {
|
||||
"push_key_id": 10,
|
||||
"encrypted_data": "uOGQ9m8bdnLab/2Qq6WLdJnFUsU/NlX0955rF6GgpiZylQB/HSD+lrHct0KUXdCneu+fnGOuBMAGkYol+SLlbvdsnePn/f6wSvMDbm3iffcgiz2u8TywUlmQL/Q7Ruj5RSpLgEhpFitL/WjwQBtrA31vsqMHycmROju+tOhFlVjmzJmYy3o7ZQDi/YeB2Y+CnA5EuuXjckBYSjL4vi/YaEJXmeHvJ8Pk3T/WwXvo8CFZYlafiqSw0vC/2bkjPTFFAFVo/49nAUI+5Rpa90wJUVChsrkKTclOs4Ih1dNIDYr6+WoIKJTtIR9zgDg3YOkVHBZhlt7Se3i40WAs5JAb1PViMpAp2hbU36z1Qq0g90nmfRjXN9FRdAPaKlbFTT2PkEtS9wVBv9T14ufkhbOwaMLfx5iaHKw3XHoWo7Fe+0IF9ZJ77uhCZoA1kyFKDhl7AZ8K4DOvib8gsfkeAR4XXXnXVmLtAyjBhMrWYNsECo9j4UeE6M90z3xIVR8=",
|
||||
"aps": {
|
||||
"mutable-content": 1,
|
||||
"alert": {
|
||||
"title": "New notification"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"token_id": "AAAAAAAAAAI=",
|
||||
"fcm_priority": "high",
|
||||
"payload": {
|
||||
"push_key_id": 20,
|
||||
"encrypted_data": "OzPhtLiyU1U+3ynqyTxkFt83N5GN7t3Uw8/OkCoFKFo/cu3GAzCMMbAAhPghflkrFK37SNOuxpPiL1TzPy5tQJqdSKpQrgu6cp0Y6VVA1aV/zsCDAcSABaWeaOeC5mVL+xFpmFeEbhzUaOLchbRn4kBO4m8gqDU/rAn0cKFY1F7tyCgC+fvvcczP05itDLpkwZMnrADGp3tSHFldr4iGO1pWJxFTXFFhg63UyH1FcMXKFzBPek7hLbpLsqu5OFEQv2TtDbAYdWZr1LXRqnkHTDmMd6NAdkOsVcnk31jHThFPDqaM5zDXb24hGHW79OpBnGAQWydfeChS4pC4yHWCO6ZRDqwvJX9IydS+V7S91KCl0QSToaXvgW7Q3zvHunzu7L/rw0dQQRgPM3qIOHr7gGtptkZpmKuT6icdDGgjRtgP/L0TfxdRKa37fn6nF64+HH60wLPYWOz7vZjgTrA20MrbA3ogMfhFYpwjppidFGVWjrLpk+peQjHB1sY="
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Changes**: In Zulip 12.0 (feature level 468), the `device_id` and
|
||||
`push_account_id` fields were replaced with `token_id` and `push_key_id`
|
||||
to support the rotation of tokens provided by FCM/APNs and keys used
|
||||
to encrypt push notifications.
|
||||
|
||||
New in Zulip 11.0 (feature level 413).
|
||||
|
||||
### Data sent to FCM
|
||||
|
||||
Zulip's push notifications service uses [Firebase Admin Python SDK](https://github.com/firebase/firebase-admin-python)
|
||||
to access FCM.
|
||||
|
||||
A sample `messages` argument, which is internally used by the SDK to prepare payload for FCM,
|
||||
passed to [`firebase_admin.messaging.send_each`](https://firebase.google.com/docs/reference/admin/python/firebase_admin.messaging#send_each):
|
||||
```py
|
||||
[
|
||||
firebase_admin.messaging.Message(
|
||||
data={
|
||||
'push_key_id': '20',
|
||||
'encrypted_data': 'OzPhtLiyU1U+3ynqyTxkFt83N5GN7t3Uw8/OkCoFKFo/cu3GAzCMMbAAhPghflkrFK37SNOuxpPiL1TzPy5tQJqdSKpQrgu6cp0Y6VVA1aV/zsCDAcSABaWeaOeC5mVL+xFpmFeEbhzUaOLchbRn4kBO4m8gqDU/rAn0cKFY1F7tyCgC+fvvcczP05itDLpkwZMnrADGp3tSHFldr4iGO1pWJxFTXFFhg63UyH1FcMXKFzBPek7hLbpLsqu5OFEQv2TtDbAYdWZr1LXRqnkHTDmMd6NAdkOsVcnk31jHThFPDqaM5zDXb24hGHW79OpBnGAQWydfeChS4pC4yHWCO6ZRDqwvJX9IydS+V7S91KCl0QSToaXvgW7Q3zvHunzu7L/rw0dQQRgPM3qIOHr7gGtptkZpmKuT6icdDGgjRtgP/L0TfxdRKa37fn6nF64+HH60wLPYWOz7vZjgTrA20MrbA3ogMfhFYpwjppidFGVWjrLpk+peQjHB1sY=',
|
||||
},
|
||||
token='push-device-token-3',
|
||||
android=firebase_admin.messaging.AndroidConfig(priority='high'),
|
||||
),
|
||||
]
|
||||
```
|
||||
|
||||
**Changes**: In Zulip 12.0 (feature level 468), the `push_account_id`
|
||||
field was replaced with `push_key_id` to support the rotation of
|
||||
keys used to encrypt push notifications.
|
||||
|
||||
New in Zulip 11.0 (feature level 413).
|
||||
|
||||
### Data sent to APNs
|
||||
|
||||
Zulip's push notifications service uses [aioapns](https://github.com/Fatal1ty/aioapns) to access APNs.
|
||||
|
||||
A sample `request` argument, which is internally used by the library to prepare payload for APNs,
|
||||
passed to [`aioapns.APNs.send_notification`](https://github.com/Fatal1ty/aioapns/blob/96831003ec5a8986206cde77e59fdb4b5a3c4b24/aioapns/client.py):
|
||||
```py
|
||||
aioapns.NotificationRequest(
|
||||
apns_topic='remote_push_device_ios_app_id',
|
||||
device_token='push-device-token-1',
|
||||
message={
|
||||
'push_key_id': 10,
|
||||
'encrypted_data': 'rUNqoWOB+EQmjThJyXhDptmUrHyzSx4DPlvShzrM7XGdRVMG5qNuH0dnGQDVza9frnWNVOF3vFcuYvDnUnYRBf1j+/n1ML1K2CBnsThCGl3KJNWrKcf5fME7Q1dU2xtJ3+RAKuLtZ9y2gq6DWamui7WfQ75m1eJpYRDbbHIQEiSIZpo7X2Lie3aHkQBgE8SN5MJ6N3VM33DM6i1xGpIeWiFy+hqNloGyEI2qf6xV0SjvvkN+HbGticben4atBkAuAIKi0gIYMPyMihH26T1sEhOH3IDyO3KvaHe1NIdj0naT9RoFkN5UgdxIchXQ7qkVEjivA2E/HefpvZYlhems6TAosfJwgCMB8HuydqdImjixkugRQfugroTTG97p6xQIJSFWCOyrpuBDElI0Ale8XjmzaVo4Dbgqz5kIAhmJWtlwgJw8nt7Orr3EWUVjnIAi0nHCFObAXNShedAbyuLeC1qezqC4FZe/GOLLi4DPWgWSdk8PV5vGw9YC+XcZ38dqQogtpG7dpzMwwsqzLBmlzQ==',
|
||||
'aps': {
|
||||
'mutable-content': 1,
|
||||
'alert': {'title': 'New notification'}
|
||||
}
|
||||
},
|
||||
priority=10,
|
||||
push_type="alert",
|
||||
)
|
||||
```
|
||||
|
||||
**Changes**: In Zulip 12.0 (feature level 468), the `push_account_id`
|
||||
field was replaced with `push_key_id` to support the rotation of
|
||||
keys used to encrypt push notifications.
|
||||
|
||||
New in Zulip 11.0 (feature level 413).
|
||||
106
api_docs/outgoing-webhook-payload.md
Normal file
106
api_docs/outgoing-webhook-payload.md
Normal file
@@ -0,0 +1,106 @@
|
||||
# Outgoing webhook payloads
|
||||
|
||||
Zulip supports [outgoing webhooks](/help/outgoing-webhooks) in a clean,
|
||||
native [Zulip format](#zulip-format), as well as in a [Slack-compatible
|
||||
format](#slack-compatible-format).
|
||||
|
||||
## Zulip format
|
||||
|
||||
{generate_code_example|/zulip-outgoing-webhook:post|fixture}
|
||||
|
||||
### Fields documentation
|
||||
|
||||
{generate_return_values_table|zulip.yaml|/zulip-outgoing-webhook:post}
|
||||
|
||||
## Slack-compatible format
|
||||
|
||||
This webhook format is compatible with [Slack's outgoing webhook
|
||||
API](https://api.slack.com/custom-integrations/outgoing-webhooks),
|
||||
which can help with porting an existing Slack integration to work with
|
||||
Zulip, and allows immediate integration with many third-party systems
|
||||
that already support Slack outgoing webhooks.
|
||||
|
||||
The following table details how the Zulip server translates a Zulip
|
||||
message into the Slack-compatible webhook format.
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>token</code></td>
|
||||
<td>A string of alphanumeric characters you can use to
|
||||
authenticate the webhook request (each bot user uses a fixed token)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>team_id</code></td>
|
||||
<td>ID of the Zulip organization prefixed by "T".</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>team_domain</code></td>
|
||||
<td>Hostname of the Zulip organization</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>channel_id</code></td>
|
||||
<td>Channel ID prefixed by "C"</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>channel_name</code></td>
|
||||
<td>Channel name</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>thread_ts</code></td>
|
||||
<td>Timestamp for when message was sent</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>timestamp</code></td>
|
||||
<td>Timestamp for when message was sent</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>user_id</code></td>
|
||||
<td>ID of the user who sent the message prefixed by "U"</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>user_name</code></td>
|
||||
<td>Full name of sender</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>text</code></td>
|
||||
<td>The content of the message (in Markdown)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>trigger_word</code></td>
|
||||
<td>Trigger method</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>service_id</code></td>
|
||||
<td>ID of the bot user</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
The above data is posted as list of tuples (not JSON), here's an example:
|
||||
|
||||
```
|
||||
[('token', 'v9fpCdldZIej2bco3uoUvGp06PowKFOf'),
|
||||
('team_id', 'T1512'),
|
||||
('team_domain', 'zulip.example.com'),
|
||||
('channel_id', 'C123'),
|
||||
('channel_name', 'integrations'),
|
||||
('thread_ts', 1532078950),
|
||||
('timestamp', 1532078950),
|
||||
('user_id', 'U21'),
|
||||
('user_name', 'Full Name'),
|
||||
('text', '@**test**'),
|
||||
('trigger_word', 'mention'),
|
||||
('service_id', 27)]
|
||||
```
|
||||
|
||||
* For successful requests, if data is returned, it returns that data,
|
||||
else it returns a blank response.
|
||||
* For failed requests, it returns the reason of failure, as returned by
|
||||
the server, or the exception message.
|
||||
60
api_docs/real-time-events.md
Normal file
60
api_docs/real-time-events.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# Real-time events API
|
||||
|
||||
Zulip's real-time events API lets you write software that reacts
|
||||
immediately to events happening in Zulip. This API is what powers the
|
||||
real-time updates in the Zulip web and mobile apps. As a result, the
|
||||
events available via this API cover all changes to data displayed in
|
||||
the Zulip product, from new messages to channel descriptions to
|
||||
emoji reactions to changes in user or organization-level settings.
|
||||
|
||||
## Using the events API
|
||||
|
||||
The simplest way to use Zulip's real-time events API is by using
|
||||
`call_on_each_event` from our Python bindings. You just need to write
|
||||
a Python function (in the examples below, the `lambda`s) and pass it
|
||||
into `call_on_each_event`; your function will be called whenever a new
|
||||
event matching the specified parameters (`event_types`, `narrow`,
|
||||
etc.) occurs in Zulip.
|
||||
|
||||
`call_on_each_event` takes care of all the potentially tricky details
|
||||
of long-polling, error handling, exponential backoff in retries, etc.
|
||||
It's cousin, `call_on_each_message`, provides an even simpler
|
||||
interface for processing Zulip messages.
|
||||
|
||||
More complex applications (like a Zulip terminal client) may need to
|
||||
instead use the raw [register](/api/register-queue) and
|
||||
[events](/api/get-events) endpoints.
|
||||
|
||||
## Usage examples
|
||||
|
||||
{start_tabs}
|
||||
{tab|python}
|
||||
|
||||
```
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
import zulip
|
||||
|
||||
# Pass the path to your zuliprc file here.
|
||||
client = zulip.Client(config_file="~/zuliprc")
|
||||
|
||||
# Print every message the current user would receive
|
||||
# This is a blocking call that will run forever
|
||||
client.call_on_each_message(lambda msg: sys.stdout.write(str(msg) + "\n"))
|
||||
|
||||
# Print every event relevant to the user
|
||||
# This is a blocking call that will run forever
|
||||
client.call_on_each_event(lambda event: sys.stdout.write(str(event) + "\n"))
|
||||
```
|
||||
|
||||
{end_tabs}
|
||||
|
||||
## Parameters
|
||||
|
||||
You may also pass in the following keyword arguments to `call_on_each_event`:
|
||||
|
||||
{generate_api_arguments_table|zulip.yaml|/real-time:post}
|
||||
|
||||
See the [GET /events](/api/get-events) documentation for
|
||||
more details on the format of individual events.
|
||||
64
api_docs/rest-error-handling.md
Normal file
64
api_docs/rest-error-handling.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# Error handling
|
||||
|
||||
Zulip's API will always return a JSON format response.
|
||||
The HTTP status code indicates whether the request was successful
|
||||
(200 = success, 4xx = user error, 5xx = server error).
|
||||
|
||||
Every response, both success and error responses, will contain at least
|
||||
two keys:
|
||||
|
||||
- `msg`: an internationalized, human-readable error message string.
|
||||
|
||||
- `result`: either `"error"` or `"success"`, which is redundant with the
|
||||
HTTP status code, but is convenient when print debugging.
|
||||
|
||||
Every error response will also contain an additional key:
|
||||
|
||||
- `code`: a machine-readable error string, with a default value of
|
||||
`"BAD_REQUEST"` for general errors.
|
||||
|
||||
Clients should always check `code`, rather than `msg`, when looking for
|
||||
specific error conditions. The string values for `msg` are
|
||||
internationalized (e.g., the server will send the error message
|
||||
translated into French if the user has a French locale), so checking
|
||||
those strings will result in buggy code.
|
||||
|
||||
!!! tip ""
|
||||
|
||||
If a client needs information that is only present in the string value
|
||||
of `msg` for a particular error response, then the developers
|
||||
implementing the client should [start a conversation here][api-design]
|
||||
in order to discuss getting a specific error `code` and/or relevant
|
||||
additional key/value pairs for that error response.
|
||||
|
||||
In addition to the keys described above, some error responses will
|
||||
contain other keys with further details that are useful for clients. The
|
||||
specific keys present depend on the error `code`, and are documented at
|
||||
the API endpoints where these particular errors appear.
|
||||
|
||||
**Changes**: Before Zulip 5.0 (feature level 76), all error responses
|
||||
did not contain a `code` key, and its absence indicated that no specific
|
||||
error `code` had been allocated for that error.
|
||||
|
||||
## Common error responses
|
||||
|
||||
Documented below are some error responses that are common to many
|
||||
endpoints:
|
||||
|
||||
{generate_code_example|/rest-error-handling:post|fixture}
|
||||
|
||||
## Ignored Parameters
|
||||
|
||||
In JSON success responses, all Zulip REST API endpoints may return
|
||||
an array of parameters sent in the request that are not supported
|
||||
by that specific endpoint.
|
||||
|
||||
While this can be expected, e.g., when sending both current and legacy
|
||||
names for a parameter to a Zulip server of unknown version, this often
|
||||
indicates either a bug in the client implementation or an attempt to
|
||||
configure a new feature while connected to an older Zulip server that
|
||||
does not support said feature.
|
||||
|
||||
{generate_code_example|/settings:patch|fixture}
|
||||
|
||||
[api-design]: https://chat.zulip.org/#narrow/channel/378-api-design
|
||||
32
api_docs/rest.md
Normal file
32
api_docs/rest.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# The Zulip REST API
|
||||
|
||||
The Zulip REST API powers the Zulip web and mobile apps, so anything
|
||||
you can do in Zulip, you can do with Zulip's REST API. To use this API:
|
||||
|
||||
* You'll need to [get an API key](/api/api-keys). You will likely
|
||||
want to [create a bot](/help/add-a-bot-or-integration), unless you're
|
||||
using the API to interact with
|
||||
your own account (e.g., exporting your personal message history).
|
||||
* Choose what language you'd like to use. You can download the
|
||||
[Python or JavaScript bindings](/api/installation-instructions), projects in
|
||||
[other languages](/api/client-libraries), or
|
||||
just make HTTP requests with your favorite programming language.
|
||||
* If you're making your own HTTP requests, you'll want to send the
|
||||
appropriate [HTTP basic authentication headers](/api/http-headers).
|
||||
* The Zulip API has a standard
|
||||
[system for reporting errors](/api/rest-error-handling).
|
||||
|
||||
Most other details are covered in the documentation for the individual
|
||||
endpoints:
|
||||
|
||||
!!! tip ""
|
||||
|
||||
You may use the `client.call_endpoint` method of our Python API
|
||||
bindings to call an endpoint that isn't documented here. For an
|
||||
example, see [Upload a custom emoji](/api/upload-custom-emoji).
|
||||
|
||||
{!rest-endpoints.md!}
|
||||
|
||||
Since Zulip is open source, you can also consult the
|
||||
[Zulip server source code](https://github.com/zulip/zulip/) as a
|
||||
workaround for how to do anything not documented here.
|
||||
121
api_docs/roles-and-permissions.md
Normal file
121
api_docs/roles-and-permissions.md
Normal file
@@ -0,0 +1,121 @@
|
||||
# Roles and permissions
|
||||
|
||||
Zulip offers several levels of permissions based on a
|
||||
[user's role](/help/user-roles) in a Zulip organization.
|
||||
|
||||
Here are some important details to note when working with these
|
||||
roles and permissions in Zulip's API:
|
||||
|
||||
## A user's role
|
||||
|
||||
A user's account data include a `role` property, which contains the
|
||||
user's role in the Zulip organization. These roles are encoded as:
|
||||
|
||||
* Organization owner: 100
|
||||
|
||||
* Organization administrator: 200
|
||||
|
||||
* Organization moderator: 300
|
||||
|
||||
* Member: 400
|
||||
|
||||
* Guest: 600
|
||||
|
||||
User account data also include these boolean properties that duplicate
|
||||
the related roles above:
|
||||
|
||||
* `is_owner` specifying whether the user is an organization owner.
|
||||
|
||||
* `is_admin` specifying whether the user is an organization administrator.
|
||||
|
||||
* `is_guest` specifying whether the user is a guest user.
|
||||
|
||||
These are intended as conveniences for simple clients, and clients
|
||||
should prefer using the `role` field, since only that one is updated
|
||||
by the [events API](/api/get-events).
|
||||
|
||||
Note that [`POST /register`](/api/register-queue) also returns an
|
||||
`is_moderator` boolean property specifying whether the current user is
|
||||
at least an organization moderator. The property will be true for admins
|
||||
and owners too.
|
||||
|
||||
|
||||
### User account data in the API
|
||||
|
||||
Endpoints that return the user account data / properties mentioned
|
||||
above are:
|
||||
|
||||
* [`GET /users`](/api/get-users)
|
||||
|
||||
* [`GET /users/{user_id}`](/api/get-user)
|
||||
|
||||
* [`GET /users/{email}`](/api/get-user-by-email)
|
||||
|
||||
* [`GET /users/me`](/api/get-own-user)
|
||||
|
||||
* [`GET /events`](/api/get-events)
|
||||
|
||||
* [`POST /register`](/api/register-queue)
|
||||
|
||||
Note that the [`POST /register` endpoint](/api/register-queue) returns
|
||||
the above boolean properties to describe the role of the current user,
|
||||
when `realm_user` is present in `fetch_event_types`.
|
||||
|
||||
Additionally, the specific events returned by the
|
||||
[`GET /events` endpoint](/api/get-events) containing data related
|
||||
to user accounts and roles are the [`realm_user` add
|
||||
event](/api/get-events#realm_user-add), and the
|
||||
[`realm_user` update event](/api/get-events#realm_user-update).
|
||||
|
||||
## Permission levels
|
||||
|
||||
Many areas of Zulip are customizable by the roles
|
||||
above, such as (but not limited to) [restricting message editing and
|
||||
deletion](/help/restrict-message-editing-and-deletion) and various
|
||||
permissions for different [channel types](/help/channel-permissions).
|
||||
The potential permission levels are:
|
||||
|
||||
* Everyone / Any user including Guests (least restrictive)
|
||||
|
||||
* Members
|
||||
|
||||
* Full members
|
||||
|
||||
* Moderators
|
||||
|
||||
* Administrators
|
||||
|
||||
* Owners
|
||||
|
||||
* Nobody (most restrictive)
|
||||
|
||||
These permission levels and policies in the API are designed to be
|
||||
cutoffs in that users with the specified role and above have the
|
||||
specified ability or access. For example, a permission level documented
|
||||
as 'moderators only' includes organization moderators, administrators,
|
||||
and owners.
|
||||
|
||||
Note that specific settings and policies in the Zulip API that use these
|
||||
permission levels will likely support a subset of those listed above.
|
||||
|
||||
## Group-based permissions
|
||||
|
||||
Some settings have been migrated to a more flexible system based on
|
||||
[user groups](/api/group-setting-values).
|
||||
|
||||
## Determining if a user is a full member
|
||||
|
||||
When a Zulip organization has set up a [waiting period before new members
|
||||
turn into full members](/help/restrict-permissions-of-new-members),
|
||||
clients will need to determine if a user's account has aged past the
|
||||
organization's waiting period threshold.
|
||||
|
||||
The `realm_waiting_period_threshold`, which is the number of days until
|
||||
a user's account is treated as a full member, is returned by the
|
||||
[`POST /register` endpoint](/api/register-queue) when `realm` is present
|
||||
in `fetch_event_types`.
|
||||
|
||||
Clients can compare the `realm_waiting_period_threshold` to a user
|
||||
accounts's `date_joined` property, which is the time the user account
|
||||
was created, to determine if a user has the permissions of a full
|
||||
member or a new member.
|
||||
79
api_docs/send-message.md
Normal file
79
api_docs/send-message.md
Normal file
@@ -0,0 +1,79 @@
|
||||
{generate_api_header(/messages:post)}
|
||||
|
||||
## Usage examples
|
||||
|
||||
{start_tabs}
|
||||
|
||||
{generate_code_example(python)|/messages:post|example}
|
||||
|
||||
{generate_code_example(javascript)|/messages:post|example}
|
||||
|
||||
{tab|curl}
|
||||
|
||||
{!curl-auth-credentials.md!}
|
||||
|
||||
``` curl
|
||||
# For channel messages
|
||||
curl -X POST {{ api_url }}/v1/messages \
|
||||
-u EMAIL_ADDRESS:API_KEY \
|
||||
--data-urlencode type=stream \
|
||||
--data-urlencode 'to="Denmark"' \
|
||||
--data-urlencode topic=Castle \
|
||||
--data-urlencode 'content=I come not, friends, to steal away your hearts.'
|
||||
|
||||
# For direct messages
|
||||
curl -X POST {{ api_url }}/v1/messages \
|
||||
-u EMAIL_ADDRESS:API_KEY \
|
||||
--data-urlencode type=direct \
|
||||
--data-urlencode 'to=[9]' \
|
||||
--data-urlencode 'content=With mirth and laughter let old wrinkles come.'
|
||||
```
|
||||
|
||||
{tab|zulip-send}
|
||||
|
||||
You can use `zulip-send`
|
||||
(available after you `pip install zulip`) to easily send Zulips from
|
||||
the command-line, providing the message content via STDIN.
|
||||
|
||||
```bash
|
||||
# For channel messages
|
||||
zulip-send --stream Denmark --subject Castle \
|
||||
--user othello-bot@example.com --api-key a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5
|
||||
|
||||
# For direct messages
|
||||
zulip-send hamlet@example.com \
|
||||
--user othello-bot@example.com --api-key a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5
|
||||
```
|
||||
|
||||
#### Passing in the message on the command-line
|
||||
|
||||
If you'd like, you can also provide the message on the command-line with the
|
||||
`-m` or `--message` flag, as follows:
|
||||
|
||||
|
||||
```bash
|
||||
zulip-send --stream Denmark --subject Castle \
|
||||
--message 'I come not, friends, to steal away your hearts.' \
|
||||
--user othello-bot@example.com --api-key a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5
|
||||
```
|
||||
|
||||
You can omit the `user` and `api-key` parameters if you have a `~/.zuliprc`
|
||||
file.
|
||||
|
||||
{end_tabs}
|
||||
|
||||
## Parameters
|
||||
|
||||
{generate_api_arguments_table|zulip.yaml|/messages:post}
|
||||
|
||||
{generate_parameter_description(/messages:post)}
|
||||
|
||||
## Response
|
||||
|
||||
{generate_return_values_table|zulip.yaml|/messages:post}
|
||||
|
||||
{generate_response_description(/messages:post)}
|
||||
|
||||
#### Example response(s)
|
||||
|
||||
{generate_code_example|/messages:post|fixture}
|
||||
14
api_docs/sidebar_index.md
Normal file
14
api_docs/sidebar_index.md
Normal file
@@ -0,0 +1,14 @@
|
||||
* [Overview](/api/rest)
|
||||
* [Installation instructions](/api/installation-instructions)
|
||||
* [API keys and zuliprc files](/api/api-keys)
|
||||
* [Configuring the Python bindings](/api/configuring-python-bindings)
|
||||
* [HTTP headers](/api/http-headers)
|
||||
* [Error handling](/api/rest-error-handling)
|
||||
* [Roles and permissions](/api/roles-and-permissions)
|
||||
* [Group-setting values](/api/group-setting-values)
|
||||
* [Message formatting](/api/message-formatting)
|
||||
* [Zulip URLs](/api/zulip-urls)
|
||||
* [Client libraries](/api/client-libraries)
|
||||
* [API changelog](/api/changelog)
|
||||
|
||||
{!rest-endpoints.md!}
|
||||
109
api_docs/zulip-urls.md
Normal file
109
api_docs/zulip-urls.md
Normal file
@@ -0,0 +1,109 @@
|
||||
# Zulip URLs
|
||||
|
||||
This page details how to properly construct and parse the URLs that
|
||||
the Zulip web app uses for various types of views.
|
||||
|
||||
Because other clients needs to be able to resolve and process these
|
||||
links in order to implement equivalent behavior that navigates
|
||||
directly in say the mobile apps, it's important to have a clear
|
||||
specification of exactly how these URLs work.
|
||||
|
||||
Essentially all of the data is encoded in the URL fragment (`#`) part
|
||||
of a URL; the protocol, host and path will just be the canonical URL
|
||||
for the Zulip server (In these examples,
|
||||
`https://zulip.example.com/`).
|
||||
|
||||
## Message feed views
|
||||
|
||||
Most links in Zulip are to message feed views, and for that reason
|
||||
these have the most developed syntax and legacy behavior.
|
||||
|
||||
Message feed URLs always start with `#narrow/`, follow by one or more
|
||||
[search operator/operand pairs](/api/construct-narrow), separated by
|
||||
`/`s. The operator may be negated by putting a `-` at the start of
|
||||
it. For example:
|
||||
|
||||
`https://zulip.example.com/#narrow/is/starred/sender/17/-channel/14`
|
||||
|
||||
is the feed of starred messages sent by user ID to everywhere but
|
||||
channel 14. The search documentation covers the valid operators and
|
||||
their meaning.
|
||||
|
||||
See also the relevant [message formatting
|
||||
documentation](/api/message-formatting) for details on Markdown
|
||||
representations of Zulip-internal links that will be translated into
|
||||
HTML containing links that use these URLs.
|
||||
|
||||
Here, we describe some special encoding rules.
|
||||
|
||||
### Operand encoding and decoding
|
||||
|
||||
Strings in operands are URL-encoded, and then additional substitution
|
||||
rules are applied to avoid over-zealous browser handling of certain
|
||||
characters in the URL fragment:
|
||||
|
||||
- `%` => `.`
|
||||
- `(` => `.28`
|
||||
- `)` => `.29`
|
||||
- `.` => `.2E`
|
||||
|
||||
They can decoded by applying the reverse transformation: Replace all
|
||||
`.` characters with `%`, and then do standard URL-decoding.
|
||||
|
||||
### Encoding channels
|
||||
|
||||
Channel operands must be encoded in one of the two modern fully
|
||||
supported formats:
|
||||
|
||||
- `42`: Just the ID of the channel. Clients should simply parse the
|
||||
channel ID to look up the channel, which is of course not guaranteed
|
||||
to be accessible to the acting user or even exist.
|
||||
- `42-channel-name`. The ID of the channel, with a human-readable hint
|
||||
of the channel name. Clients generating Zulip URLs are recommended
|
||||
to include channel name hints where there is a readable URL-encoding
|
||||
of the channel name, but to skip doing so for channel names written
|
||||
in non-ascii languages or where otherwise the slug would not make
|
||||
the URL nicer for humans. Clients must parse this format by
|
||||
discarding everything after the `-` and treating it identically to
|
||||
the simpler integer-only format. Note that means nothing enforces
|
||||
that the string have anything to do with the channel name;
|
||||
functionally, it just an optional hint.
|
||||
|
||||
These two formats allow Zulip URLs to stably refer to a specific
|
||||
channel, even though channels can be renamed, while still allowing the
|
||||
URLs to have user-friendly name hints most of the time.
|
||||
|
||||
There is an additional legacy format that was used prior to 2018 that
|
||||
clients are required to support:
|
||||
|
||||
- `channel-name`: Legacy format of just the channel name, URL-encoded
|
||||
and with spaces replaced with dashes. The legacy format should never
|
||||
take precedence over the modern format, so a link with
|
||||
`2016-election` as the slug must be parsed as the channel with ID
|
||||
2016, even if theoretically it could have been originally intended
|
||||
as referring to a channel named `2016 election`.
|
||||
|
||||
Clients are not recommended to ever generate this legacy format.
|
||||
|
||||
## zulip:// links for mobile login
|
||||
|
||||
Zulip's single-sign on login process for the mobile app ends with a
|
||||
redirect to `zulip://login` with the following query parameters:
|
||||
|
||||
- `email`: The email address for the authenticated account.
|
||||
- `otp_encrypted_api_key`: The API key for the client, encrypted using
|
||||
the `mobile_flow_otp` that the client provided when initiating the
|
||||
login attempt.
|
||||
- `realm`: The full URL of the Zulip organization.
|
||||
- `user_id`: The Zulip user ID for the authenticated account.
|
||||
|
||||
**Changes**: The `user_id` field was added to the set of included
|
||||
query parameters in Zulip 5.0 (feature level 128).
|
||||
|
||||
## Related articles
|
||||
|
||||
* [Message formatting API](/api/message-formatting)
|
||||
* [Construct a narrow](/api/construct-narrow) for search.
|
||||
* [Markdown formatting help](/help/format-your-message-using-markdown)
|
||||
* [Send a message](/api/send-message)
|
||||
|
||||
Reference in New Issue
Block a user