# This file contains the API definitions for the Zulip REST API. # # For details on the OpenAPI specification, see https://swagger.io/specification # # Our own documentation lives at # # https://zulip.readthedocs.io/en/latest/documentation/openapi.html # openapi: 3.0.1 info: version: 1.0.0 title: Zulip REST API description: | Powerful open source group chat contact: url: https://zulip.com license: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0.html servers: # Zulip Cloud - url: 'https://{subdomain}.zulipchat.com/api/v1' variables: subdomain: default: example # Self-hosted - url: '{server}/api/v1' variables: server: default: https:// # chat.zulip.org - url: 'https://chat.zulip.org/api/v1' # Development server - url: 'http://localhost:9991/api/v1' security: - basicAuth: [] ####################### # Endpoint definitions ####################### paths: /fetch_api_key: post: operationId: fetch_api_key tags: ["authentication"] description: | Given a username and password, fetch the user's API key. Used to authenticate the mobile and terminal apps when the server has EmailAuthBackend or LDAPAuthBackend enabled. parameters: - name: username in: query description: | The username to be used for authentication (typically, the email address, but it could be an LDAP username). schema: type: string required: true - name: password in: query schema: type: string description: | The user's Zulip password (or LDAP password, if LDAP authentication is in use). required: true responses: '200': description: Success. content: application/json: schema: $ref: '#/components/schemas/ApiKeyResponse' /dev_fetch_api_key: post: operationId: dev_fetch_api_key tags: ["authentication"] description: | For easy testing of mobile apps and other clients and against Zulip development servers, we support fetching a Zulip API key for any user on the development server without authentication (so that they can implement analogues of the one-click login process available for Zulip development servers on the web). **Note:** This endpoint is only available on Zulip development servers; for obvious security reasons it will always return an error in a Zulip production server. `POST {{ api_url }}/v1/dev_fetch_api_key` parameters: - name: username in: query description: | The email address for the user that owns the API key. schema: type: string example: iago@zulip.com required: true security: [] responses: '200': description: Success. content: application/json: schema: $ref: '#/components/schemas/ApiKeyResponse' /events: get: operationId: get_events tags: ["real_time_events"] description: | `GET {{ api_url }}/v1/events` This endpoint allows you to receive new events from [a registered event queue](/api/register-queue). parameters: - $ref: '#/components/parameters/QueueId' - name: last_event_id in: query description: | The highest event ID in this queue that you've received and wish to acknowledge. See the [code for `call_on_each_event`](https://github.com/zulip/python-zulip-api/blob/master/zulip/zulip/__init__.py) in the [zulip Python module](https://github.com/zulip/python-zulip-api) for an example implementation of correctly processing each event exactly once. schema: type: integer example: -1 - name: dont_block in: query description: | Set to `true` if the client is requesting a nonblocking reply. If not specified, the request will block until either a new event is available or a few minutes have passed, in which case the server will send the client a heartbeat event. schema: type: boolean default: false example: true responses: '200': description: Success. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - properties: events: type: array description: | An array of `event` objects (possibly zero-length if `dont_block` is set) with IDs newer than `last_event_id`. Event IDs are guaranteed to be increasing, but they are not guaranteed to be consecutive. items: type: object - example: { "events": [ { "id": 0, "message": { "avatar_url": "https://url/for/othello-bots/avatar", "client": "website", "content": "I come not, friends, to steal away your hearts.", "content_type": "text/x-markdown", "display_recipient": "Denmark", "id": 12345678, "recipient_id": 12314, "sender_email": "othello-bot@example.com", "sender_full_name": "Othello Bot", "sender_id": 13215, "sender_realm_str": "example", "sender_short_name": "othello-bot", "topic": "Castle", "topic_links": [], "timestamp": 1375978403, "type": "stream" }, "type": "message" }, { "id": 1, "message": { "avatar_url": "https://url/for/othello-bots/avatar", "client": "website", "content": "With mirth and laughter let old wrinkles come.", "content_type": "text/x-markdown", "display_recipient": [ { "email": "hamlet@example.com", "full_name": "Hamlet of Denmark", "id": 31572, "short_name": "hamlet" } ], "id": 12345679, "recipient_id": 18391, "sender_email": "othello-bot@example.com", "sender_full_name": "Othello Bot", "sender_id": 13215, "sender_realm_str": "example", "sender_short_name": "othello-bot", "subject": "", "topic_links": [], "timestamp": 1375978404, "type": "private" }, "type": "message" } ], "msg": "", "result": "success" } '400': description: Bad request. content: application/json: schema: $ref: '#/components/schemas/BadEventQueueIdError' delete: operationId: delete_queue tags: ["real_time_events"] description: | Delete a previously registered queue. `DELETE {{ api_url }}/v1/events` parameters: - $ref: '#/components/parameters/QueueId' responses: '200': description: Success. content: application/json: schema: $ref: '#/components/schemas/JsonSuccess' '400': description: Bad request. content: application/json: schema: $ref: '#/components/schemas/BadEventQueueIdError' /get_stream_id: get: operationId: get_stream_id tags: ["streams"] description: | Get the unique ID of a given stream. `GET {{ api_url }}/v1/get_stream_id` parameters: - $ref: '#/components/parameters/Stream' required: true responses: '200': description: Success. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - properties: stream_id: type: integer description: | The ID of the given stream. - example: { "msg": "", "result": "success", "stream_id": 15 } '400': description: Bad request. content: application/json: schema: allOf: - $ref: '#/components/schemas/CodedError' - example: { "code": "BAD_REQUEST", "msg": "Invalid stream name 'nonexistent'", "result": "error" } /mark_all_as_read: post: operationId: mark_all_as_read tags: ["messages"] description: | Marks all of the current user's unread messages as read. `POST {{ api_url }}/v1/mark_all_as_read` responses: '200': description: Success. content: application/json: schema: $ref: '#/components/schemas/JsonSuccess' /mark_stream_as_read: post: operationId: mark_stream_as_read tags: ["messages"] description: | Mark all the unread messages in a stream as read. parameters: - $ref: '#/components/parameters/StreamIdInQuery' required: true responses: '200': description: Success. content: application/json: schema: $ref: '#/components/schemas/JsonSuccess' /mark_topic_as_read: post: operationId: mark_topic_as_read tags: ["messages"] description: | Mark all the unread messages in a topic as read. parameters: - $ref: '#/components/parameters/StreamIdInQuery' required: true - name: topic_name in: query description: | The name of the topic whose messages should be marked as read. schema: type: string example: new coffee machine required: true responses: '200': description: Success. content: application/json: schema: $ref: '#/components/schemas/JsonSuccess' /messages: get: operationId: get_messages tags: ["messages"] description: | Fetch message history from a Zulip server. `GET {{ api_url }}/v1/messages` This `GET /api/v1/messages` endpoint is the primary way to fetch message history from a Zulip server. It is useful both for Zulip clients (e.g. the web, desktop, mobile, and terminal clients) as well as bots, API clients, backup scripts, etc. By specifying a [narrow filter](/api/construct-narrow), you can use this endpoint to fetch the messages matching any search query that is supported by Zulip's powerful full-text search backend. When a narrow is not specified, it can be used to fetch a user's message history (We recommend paginating to 1000 messages at a time). In either case, you specify an `anchor` message (or ask the server to calculate the first unread message for you and use that as the anchor), as well as a number of messages before and after the anchor message. The server returns those messages, sorted by message ID, as well as some metadata that makes it easy for a client to determine whether there are more messages matching the query that were not returned due to the `num_before` and `num_after` limits. We recommend using `num_before <= 1000` and `num_after <= 1000` to avoid generating very large HTTP responses. A maximum of 5000 messages can be obtained per request; attempting to exceed this will result in an error. parameters: - name: anchor in: query description: | Integer message ID to anchor fetching of new messages. Supports special string values for when the client wants the server to compute the anchor to use: * `newest`: The most recent message. * `oldest`: The oldest message. * `first_unread`: The oldest unread message matching the query, if any; otherwise, the most recent message. The special values of `'newest'` and `'oldest'` are also supported for anchoring the query at the most recent or oldest messages. **Changes**: String values are new in Zulip 2.2 (feature level 1). The `first_unread` functionality was supported in Zulip 2.1.x and older by not sending anchor and using use_first_unread_anchor. In Zulip 2.1.x and older, `oldest` can be emulated with `anchor=0`, and `newest` with `anchor=10000000000000000` (that specific large value works around a bug in Zulip 2.1.x and older in the `found_newest` return value). schema: oneOf: - type: string - type: integer example: 42 - name: num_before in: query description: | The number of messages with IDs less than the anchor to retrieve. schema: type: integer example: 4 required: true - name: num_after in: query description: | The number of messages with IDs greater than the anchor to retrieve. schema: type: integer example: 8 required: true - name: narrow in: query description: | The narrow where you want to fetch the messages from. See how to [construct a narrow](/api/construct-narrow). schema: type: array items: type: object default: [] example: [{"operand": "Denmark", "operator": "stream"}] - $ref: '#/components/parameters/ClientGravatar' - name: apply_markdown in: query description: | If `true`, message content is returned in the rendered HTML format. If `false`, message content is returned in the raw markdown-format text that user entered. schema: type: boolean default: true example: false - name: use_first_unread_anchor in: query description: | Legacy way to specify `anchor="first_unread"` in Zulip 2.1.x and older. Whether to use the (computed by the server) first unread message matching the narrow as the `anchor`. Mutually exclusive with `anchor`. **Changes**: Deprecated in Zulip 2.2, replaced by `anchor="first_unread"` instead. schema: type: boolean default: false example: true responses: '200': description: Success. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - properties: anchor: type: integer description: | The same `anchor` specified in the request (or the computed one, if `use_first_unread_anchor` is `true`). found_newest: type: boolean description: | Whether the `messages` list includes the very newest messages matching the narrow (used by clients that paginate their requests to decide whether there are more messages to fetch). found_oldest: type: boolean description: | Whether the `messages` list includes the very oldest messages matching the narrow (used by clients that paginate their requests to decide whether there are more messages to fetch). found_anchor: type: boolean description: | Whether the anchor message is included in the response. If the message with the ID specified in the request does not exist or did not match the narrow, this will be false. history_limited: type: boolean description: | Whether the message history was limited due to plan restrictions. This flag is set to `true` only when the oldest messages(`found_oldest`) matching the narrow is fetched. messages: type: array items: type: object - properties: anchor: type: integer description: | The same `anchor` specified in the request (or the computed one, if `use_first_unread_anchor` is `true`). found_newest: type: boolean description: | Whether the `messages` list includes the very newest messages matching the narrow (used by clients that paginate their requests to decide whether there are more messages to fetch). found_oldest: type: boolean description: | Whether the `messages` list includes the very oldest messages matching the narrow (used by clients that paginate their requests to decide whether there are more messages to fetch). found_anchor: type: boolean description: | Whether the anchor message is included in the response. If the message with the ID specified in the request does not exist or did not match the narrow, this will be false. history_limited: type: boolean description: | Whether the message history was limited due to plan restrictions. This flag is set to `true` only when the oldest messages(`found_oldest`) matching the narrow is fetched. messages: type: array description: | an array of `message` objects, each containing the following fields: items: type: object properties: avatar_url: type: string description: | The URL of the user's avatar. client: type: string description: | A Zulip "client" string, describing what Zulip client sent the message. content: type: string description: | The content/body of the message. content_type: type: string description: | The HTTP `content_type` for the message content. This will be `text/html` or `text/x-markdown`, depending on whether `apply_markdown` was set. display_recepient: oneOf: - type: string - type: array items: type: object description: | Data on the recipient of the message; either the name of a stream or a dictionary containing basic data on the users who received the message. flags: type: array description: | The user's [message flags][message-flags] for the message. items: type: string id: type: integer description: | The unique message ID. Messages should always be displayed sorted by ID. is_me_message: type: boolean description: | Whether the message is a [/me status message][status-messages] reactions: type: array description: | Data on any reactions to the message. items: type: object properties: emoji_code: type: integer description: | An encoded version of the emoji's unicode codepoint. emoji_name: type: string description: | Name of the emoji. reaction_type: type: string description: | If the reaction uses a [custom emoji](/help/add-custom-emoji), `reaction_type` will be set to `realm_emoji`. user_id: type: integer description: | The ID of the user who added the reaction. **Changes**: New in Zulip 2.2 (feature level 2). The `user` object is deprecated and will be removed in the future. user: type: object description: | Dictionary with data on the user who added the reaction, including the user ID as the `id` field. **Note**: In the [events API](/api/get-events-from-queue), this `user` dictionary confusing had the user ID in a field called `user_id` instead. We recommend ignoring fields other than the user ID. **Deprecated** and to be removed in a future release once core clients have migrated to use the `user_id` field. recipient_id: type: integer description: | A unique ID for the set of users receiving the message (either a stream or group of users). Useful primarily for hashing. sender_email: type: string description: | The Zulip display email address of the message's sender. sender_full_name: type: string description: | The full name of the message's sender. sender_id: type: integer description: | The user ID of the message's sender. sender_realm_str: type: string description: | A string identifier for the realm the sender is in. Unique only within the context of a given Zulip server. E.g. on `example.zulip.com`, this will be `example`. sender_short_name: type: string description: | Reserved for future use. stream_id: type: integer description: | Only present for stream messages; the ID of the stream. subject: type: string description: | The `topic` of the message (only present for stream messages). The field name is a legacy holdover from when topics were called "subjects" and will eventually change. topic_links: type: array items: type: string description: | Data on any links to be included in the `topic` line (these are generated by [custom linkification filters][linkification-filters] that match content in the message's topic.) **Changes**: New in Zulip 2.2 (feature level 1). Previously, this field was called `subject_links`; clients are recommended to rename `subject_links` to `topic_links` if present for compatibility with older Zulip servers. submessages: type: array items: type: string description: | Data used for certain experimental Zulip integrations. timestamp: type: integer description: | The UNIX timestamp for when the message was sent, in UTC seconds. type: type: string description: | The type of the message: `stream` or `private`. - example: { "anchor": 21, "found_newest": true, "found_anchor": true, "result": "success", "msg": "", "messages": [ { "subject": "", "sender_realm_str": "zulip", "type": "private", "content": "

Security experts agree that relational algorithms are an interesting new topic in the field of networking, and scholars concur.

", "flags": [ "read" ], "id": 16, "display_recipient": [ { "short_name": "hamlet", "id": 4, "is_mirror_dummy": false, "email": "hamlet@zulip.com", "full_name": "King Hamlet" }, { "short_name": "iago", "id": 5, "is_mirror_dummy": false, "email": "iago@zulip.com", "full_name": "Iago" }, { "short_name": "prospero", "id": 8, "is_mirror_dummy": false, "email": "prospero@zulip.com", "full_name": "Prospero from The Tempest" } ], "content_type": "text/html", "is_me_message": false, "sender_short_name": "hamlet", "timestamp": 1527921326, "sender_id": 4, "sender_full_name": "King Hamlet", "recipient_id": 27, "topic_links": [], "client": "populate_db", "avatar_url": "https://secure.gravatar.com/avatar/6d8cad0fd00256e7b40691d27ddfd466?d=identicon&version=1", "submessages": [], "sender_email": "hamlet@zulip.com", "reactions": [] }, { "subject": "Verona3", "stream_id": 5, "sender_realm_str": "zulip", "type": "stream", "content": "

Wait, is this from the frontend js code or backend python code

", "flags": [ "read" ], "id": 21, "display_recipient": "Verona", "content_type": "text/html", "is_me_message": false, "sender_short_name": "hamlet", "timestamp": 1527939746, "sender_id": 4, "sender_full_name": "King Hamlet", "recipient_id": 20, "topic_links": [], "client": "populate_db", "avatar_url": "https://secure.gravatar.com/avatar/6d8cad0fd00256e7b40691d27ddfd466?d=identicon&version=1", "submessages": [], "sender_email": "hamlet@zulip.com", "reactions": [] } ] } post: operationId: send_message tags: ["messages"] description: | Send a stream or a private message. `POST {{ api_url }}/v1/messages` parameters: - name: type in: query description: | The type of message to be sent. `private` for a private message and `stream` for a stream message. schema: type: string enum: - private - stream example: private required: true - name: to in: query description: | For stream messages, either the name or integer ID of the stream. For private messages, either a list containing integer user IDs or a list containing string email addresses. **Changes**: Support for using user/stream IDs was added in Zulip 2.0.0. content: application/json: schema: type: array items: type: integer example: [9, 10] required: true - $ref: '#/components/parameters/Topic' - $ref: '#/components/parameters/Content' responses: '200': description: Success. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - properties: id: type: integer description: | The unique ID assigned to the sent message. - example: { "msg": "", "id": 42, "result": "success" } '400': description: Bad request. content: application/json: schema: oneOf: - $ref: '#/components/schemas/NonExistingStreamError' - allOf: - $ref: '#/components/schemas/CodedError' - example: { "code": "BAD_REQUEST", "msg": "Invalid email 'eeshan@zulip.com'", "result": "error" } /messages/{message_id}: get: operationId: get_raw_message tags: ["messages"] description: | Get the raw content of a message. `GET {{ api_url }}/v1/messages/{msg_id}` This is a rarely-used endpoint relevant for clients that primarily work with HTML-rendered messages but might need to occasionally fetch the message's raw markdown (e.g. for pre-filling a message-editing UI). parameters: - $ref: '#/components/parameters/MessageId' responses: '200': description: Success. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - properties: raw_content: type: string description: | The raw content of the message. - example: { "raw_content": "**Don't** forget your towel!", "result": "success", "msg": "" } '400': description: Bad request. content: application/json: schema: $ref: '#/components/schemas/InvalidMessageError' patch: operationId: update_message tags: ["messages"] description: | Edit/update the content or topic of a message. `PATCH {{ api_url }}/v1/messages/{msg_id}` `{msg_id}` in the above URL should be replaced with the ID of the message you wish you update. parameters: - $ref: '#/components/parameters/MessageId' - $ref: '#/components/parameters/Topic' - name: propagate_mode in: query description: | Which message(s) should be edited: just the one indicated in `message_id`, messages in the same topic that had been sent after this one, or all of them. schema: type: string enum: - change_one - change_later - change_all default: change_one example: change_all - name: send_notification_to_old_thread in: query description: | Whether to send breadcrumb message to the old thread to notify users where the messages were moved to. **Changes**: New in Zulip 2.2 (feature level 9). schema: type: boolean default: true example: true - name: send_notification_to_new_thread in: query description: | Whether to send a notification message to the new thread to notify users where the messages came from. **Changes**: New in Zulip 2.2 (feature level 9). schema: type: boolean default: true example: true - $ref: '#/components/parameters/Content' - $ref: '#/components/parameters/StreamIdInQuery' responses: '200': description: Success. content: application/json: schema: $ref: '#/components/schemas/JsonSuccess' '400': description: Bad request. content: application/json: schema: allOf: - $ref: '#/components/schemas/CodedError' - properties: msg: enum: - Your organization has turned off message editing - You don't have permission to edit this message - The time limit for editing this message has past - Nothing to change - Topic can't be empty - example: { "code": "BAD_REQUEST", "msg": "You don't have permission to edit this message", "result": "error" } delete: operationId: delete_message tags: ["messages"] description: | Permanently delete a message. `DELETE {{ api_url }}/v1/messages/{msg_id}` This API corresponds to the [delete a message completely][delete-completely] feature documented in the Zulip Help Center. parameters: - $ref: '#/components/parameters/MessageId' responses: '200': description: Success. content: application/json: schema: $ref: '#/components/schemas/JsonSuccess' '400': description: Bad request. content: application/json: schema: oneOf: - $ref: '#/components/schemas/InvalidMessageError' - allOf: - $ref: '#/components/schemas/CodedError' - example: { "code": "BAD_REQUEST", "msg": "You don't have permission to delete this message", "result": "error" } /messages/{message_id}/history: get: operationId: get_message_history tags: ["messages"] description: | Fetch the message edit history of a previously edited message. `GET {{ api_url }}/v1/messages/{message_id}/history` Note that edit history may be disabled in some organizations; see the [Zulip Help Center documentation on editing messages][edit-settings]. [edit-settings]: /help/view-a-messages-edit-history parameters: - $ref: '#/components/parameters/MessageId' responses: '200': description: Success. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - properties: message_history: type: array items: type: object properties: topic: type: string description: | the topic for the message. prev_topic: type: string description: | the topic for the message before being edited. content: type: string description: | the body of the message. rendered_content: type: string description: | the already rendered, HTML version of `content`. prev_content: type: string description: | the body of the message before being edited. prev_rendered_content: type: string description: | the already rendered, HTML version of `prev_content`. user_id: type: integer description: | the ID of the user that made the edit. content_html_diff: type: string description: | an HTML diff between this version of the message and the previous one. timestamp: type: integer description: | the UNIX timestamp for this edit. description: | A chronologically sorted array of `snapshot` objects, each one with the values of the message after the edit. - example: { "message_history": [ { "content": "Hello!", "topic": "party at my houz", "rendered_content": "

Hello!

", "timestamp": 1530129122, "user_id": 5 }, { "topic": "party at my house", "content": "Howdy!", "prev_content": "Hello!", "rendered_content": "

Howdy!

", "user_id": 5, "prev_rendered_content": "

Hello!

", "content_html_diff": "

Howdy!

Hello!

", "prev_topic": "party at my houz", "timestamp": 1530129134 } ], "msg": "", "result": "success" } '400': description: Bad request. content: application/json: schema: $ref: '#/components/schemas/InvalidMessageError' /messages/flags: post: operationId: update_message_flags tags: ["messages"] description: | Add or remove flags in a list of messages. `POST {{ api_url }}/v1/messages/flags` For updating the `read` flag on common collections of messages, see also the [special endpoints for marking message as read in bulk](/api/mark-as-read-bulk). parameters: - name: messages in: query description: | An array containing the IDs of the target messages. schema: type: array items: type: integer example: [4, 8, 15] required: true - name: op in: query description: | Whether to `add` the flag or `remove` it. schema: type: string enum: - add - remove example: add required: true - name: flag in: query description: | The flag that should be added/removed. schema: type: string example: read required: true responses: '200': description: Success. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - properties: messages: type: array items: type: integer description: | An array with the IDs of the modified messages. - example: { "msg": "", "messages": [ 4, 18, 15 ], "result": "success" } /messages/render: post: operationId: render_message tags: ["messages"] description: | Render a message to HTML. `POST {{ api_url }}/v1/messages/render` parameters: - $ref: '#/components/parameters/Content' responses: '200': description: Success. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - properties: rendered: type: string description: | The rendered HTML. - example: { "msg": "", "rendered": "

foo

", "result": "success" } /messages/{message_id}/reactions: post: operationId: add_reaction tags: ["messages"] description: | Add an [emoji reaction](/help/emoji-reactions) to a message. `POST {{ api_url }}/v1/messages/{message_id}/reactions` parameters: - $ref: '#/components/parameters/MessageId' - $ref: '#/components/parameters/EmojiName' required: true - $ref: '#/components/parameters/EmojiCode' - $ref: '#/components/parameters/ReactionType' responses: '200': $ref: '#/components/responses/SimpleSuccess' '400': description: Bad request. content: application/json: schema: allOf: - $ref: '#/components/schemas/CodedError' - example: { "result": "error", "msg": "Invalid emoji code", "code": "BAD_REQUEST" } delete: operationId: remove_reaction tags: ["messages"] description: | Remove an [emoji reaction](/help/emoji-reactions) from a message. `DELETE {{ api_url }}/v1/messages/{message_id}/reactions` parameters: - $ref: '#/components/parameters/MessageId' - $ref: '#/components/parameters/EmojiName' required: false - $ref: '#/components/parameters/EmojiCode' - $ref: '#/components/parameters/ReactionType' responses: '200': $ref: '#/components/responses/SimpleSuccess' '400': description: Bad request. content: application/json: schema: allOf: - $ref: '#/components/schemas/CodedError' - example: { "result": "error", "msg": "Invalid message(s)", "code": "BAD_REQUEST" } /user_uploads: post: operationId: upload_file tags: ["messages"] description: | Upload a single file and get the corresponding URI. `POST {{ api_url }}/v1/user_uploads` Initially, only you will be able to access the link. To share the uploaded file, you'll need to [send a message][send-message] containing the resulting link. Users who can already access the link can reshare it with other users by sending additional Zulip messages containing the link. [uploaded-files]: /help/manage-your-uploaded-files [send-message]: /api/send-message requestBody: content: multipart/form-data: schema: properties: filename: type: string format: binary example: /path/to/file responses: '200': description: Success. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - properties: uri: type: string description: | The URI of the uploaded file. - example: { "msg": "", "result": "success", "uri": "/user_uploads/1/4e/m2A3MSqFnWRLUf9SaPzQ0Up_/zulip.txt" } /user_uploads/{realm_id_str}/{filename}: get: operationId: get_file_temporary_url tags: ["messages"] description: | Get a temporary URL for access to the file that doesn't require authentication. parameters: - name: realm_id_str in: path description: | The realm id. schema: type: integer example: 1 required: True - name: filename in: path description: | Path to the URL. schema: type: string example: 4e/m2A3MSqFnWRLUf9SaPzQ0Up_/zulip.txt required: True responses: '200': description: Success. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - properties: url: type: string description: | A temporary URL that can be used to access the uploaded file without Zulip's normal API authentication. - example: { "msg": "", "result": "success", "url": "/user_uploads/temporary/322F32632F39765378464E4C63306D3961396F4970705A4D74424565432F7A756C69702E7478743A316A5053616A3A3938625F44393446466D37357254315F4F414C425A4553464F6A55" } /users: get: operationId: get_users tags: ["users"] description: | Retrieve details on all users in the organization. Optionally includes values of [custom profile field](/help/add-custom-profile-fields). `GET {{ api_url }}/v1/users` parameters: - $ref: '#/components/parameters/ClientGravatar' - $ref: '#/components/parameters/IncludeCustomProfileFields' responses: '200': description: Success. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - properties: members: type: array description: | A list of `user` objects, each containing details about a user in the organization. items: $ref: '#/components/schemas/User' - example: { "msg": "", "result": "success", "members": [ { "is_active": true, "email": "AARON@zulip.com", "is_admin": false, "is_owner": false, "avatar_url": "https://secure.gravatar.com/avatar/818c212b9f8830dfef491b3f7da99a14?d=identicon&version=1", "bot_type": null, "timezone": "", "is_bot": false, "user_id": 7, "profile_data": {}, "is_guest": false, "date_joined": "2019-10-20T07:50:53.728864+00:00", "full_name": "aaron" }, { "date_joined": "2019-10-20T07:50:53.729659+00:00", "full_name": "King Hamlet", "is_guest": false, "profile_data": { "4": { "value": "vim" }, "2": { "value": "I am:\n* The prince of Denmark\n* Nephew to the usurping Claudius", "rendered_value": "

I am:

\n" }, "5": { "value": "1900-1-1" }, "7": { "value": "[11]" }, "6": { "value": "https://blog.zulig.org" }, "1": { "value": "+0-11-23-456-7890", "rendered_value": "

+0-11-23-456-7890

" }, "8": { "value": "zulipbot" }, "3": { "rendered_value": "

Dark chocolate

", "value": "Dark chocolate" } }, "user_id": 10, "is_bot": false, "bot_type": null, "timezone": "", "is_admin": false, "is_owner": false, "avatar_url": "https://secure.gravatar.com/avatar/6d8cad0fd00256e7b40691d27ddfd466?d=identicon&version=1", "is_active": true, "email": "hamlet@zulip.com" }, { "bot_owner_id": 11, "is_guest": false, "date_joined": "2019-10-20T12:52:17.862053+00:00", "full_name": "Iago's Bot", "email": "iago-bot@zulipdev.com", "is_active": true, "avatar_url": "https://secure.gravatar.com/avatar/7328586831cdbb1627649bd857b1ee8c?d=identicon&version=1", "is_admin": false, "is_owner": false, "user_id": 23, "bot_type": 1, "timezone": "", "is_bot": true } ] } post: operationId: create_user tags: ["users"] description: | Create a new user account via the API. `POST {{ api_url }}/v1/users` parameters: - name: email in: query description: | The email address of the new user. schema: type: string example: username@example.com required: true - name: password in: query description: | The password of the new user. schema: type: string example: abcd1234 required: true - name: full_name in: query description: | The full name of the new user. schema: type: string example: New User required: true - name: short_name in: query description: | The short name of the new user. Not user-visible. schema: type: string example: newuser required: true responses: '200': description: Success. content: application/json: schema: $ref: '#/components/schemas/JsonSuccess' '400': description: Bad request. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonError' - example: { "msg": "Email 'newbie@zulip.com' already in use", "result": "error" } /users/{user_id}: get: operationId: get_user tags: ["users"] description: | Fetch details for a single user in the organization. `GET {{ api_url }}/v1/users/{user_id}` You can also fetch details on [all users in the organization](/api/get-all-users). *This endpoint is new in Zulip Server 2.2.* parameters: - $ref: '#/components/parameters/UserId' - $ref: '#/components/parameters/ClientGravatar' - $ref: '#/components/parameters/IncludeCustomProfileFields' responses: '200': description: Success. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - properties: user: $ref: '#/components/schemas/User' - example: { "msg": "", "result": "success", "user": { "date_joined": "2019-10-20T07:50:53.729659+00:00", "full_name": "King Hamlet", "is_guest": false, "profile_data": { "4": { "value": "vim" }, "2": { "value": "I am:\n* The prince of Denmark\n* Nephew to the usurping Claudius", "rendered_value": "

I am:

\n" }, "5": { "value": "1900-1-1" }, "7": { "value": "[11]" }, "6": { "value": "https://blog.zulig.org" }, "1": { "value": "+0-11-23-456-7890", "rendered_value": "

+0-11-23-456-7890

" }, "8": { "value": "zulipbot" }, "3": { "rendered_value": "

Dark chocolate

", "value": "Dark chocolate" } }, "user_id": 10, "is_bot": false, "bot_type": null, "timezone": "", "is_admin": false, "is_owner": false, "avatar_url": "https://secure.gravatar.com/avatar/6d8cad0fd00256e7b40691d27ddfd466?d=identicon&version=1", "is_active": true, "email": "hamlet@zulip.com" } } patch: operationId: update_user tags: ["users"] description: | Administrative endpoint to update the details of another user in the organization. `PATCH {{ api_url }}/v1/users/{user_id}` Supports everything an administrator can do to edit details of another user's account, including editing full name, [role](/help/roles-and-permissions), and [custom profile fields](/help/add-custom-profile-fields). parameters: - $ref: '#/components/parameters/UserId' - name: full_name in: query description: | The user's full name. content: application/json: schema: type: string example: NewName required: false - name: role in: query description: | New [role](/help/roles-and-permissions) for the user. Supported roles include: * Organization owner: 100 * Organization administrator: 200 * Member: 400 * Guest: 600 Only organization owners can add or remove the owner permission. The owner permission cannot be removed from the only organization owner. **Changes**: New in Zulip 2.2 (feature level 8), replacing the previous pair of `is_admin` and `is_guest` boolean parameters. schema: type: integer example: 400 required: false - name: profile_data in: query description: | A dictionary containing the to be updated custom profile field data for the user. schema: type: array items: type: object example: [ { "id": 4, "value": "vim" }, { "id": 5, "value": "1909-04-05" }, ] required: false responses: '200': $ref: '#/components/responses/SimpleSuccess' '400': description: Bad request. content: application/json: schema: allOf: - $ref: '#/components/schemas/CodedError' - example: { "result": "error", "msg": "Guests cannot be organization administrators", "code": "BAD_REQUEST" } delete: operationId: deactivate_user tags: ["users"] description: | [Deactivates a user](https://zulip.com/help/deactivate-or-reactivate-a-user) given their user ID. `DELETE {{ api_url }}/v1/users/{user_id}` parameters: - $ref: '#/components/parameters/UserId' responses: '200': description: Success content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - example: { "msg": "", "result": "success", } '400': description: Bad Request content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonError' - example: { "msg": "Cannot deactivate the only organization administrator", "result": "error" } /users/{user_id}/reactivate: post: operationId: reactivate_user tags: ["users"] description: | [Reactivates a user](https://zulip.com/help/deactivate-or-reactivate-a-user) given their user ID. `POST {{ api_url }}/v1/users/{user_id}/reactivate` parameters: - $ref: '#/components/parameters/UserId' responses: '200': description: Success content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - example: { "msg": "", "result": "success", } /users/{email}/presence: get: operationId: get_user_presence tags: ["users"] description: | Get the presence status for a specific user. This endpoint is most useful for embedding data about a user's presence status in other sites (E.g. an employee directory). Full Zulip clients like mobile/desktop apps will want to use the main presence endpoint, which returns data for all active users in the organization, instead. `GET {{ api_url }}/v1/users/{email}/presence` See [Zulip's developer documentation](https://zulip.readthedocs.io/en/latest/subsystems/presence.html) for details on the data model for presence in Zulip. parameters: - name: email in: path description: | The email address of the user whose presence you want to fetch. schema: type: string example: iago@zulip.com required: true responses: '200': description: Success. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - properties: presence: type: object description: | An object containing the presence details for every client the user has logged into. additionalProperties: type: object properties: timestamp: type: integer description: | when this update was received; if the timestamp is more than a few minutes in the past, the user is offline. status: type: string description: | either `active` or `idle`: whether the user had recently interacted with Zulip at the time in the timestamp (this distinguishes orange vs. green dots in the Zulip web UI; orange/idle means we don't know whether the user is actually at their computer or just left the Zulip app open on their desktop). description: | `{client_name}` or `aggregated`: the keys for these objects are the names of the different clients where this user is logged in, like `website`, `ZulipDesktop`, `ZulipTerminal`, or `ZulipMobile`. There is also an `aggregated` key, which matches the contents of the object that has been updated most recently. For most applications, you'll just want to look at the `aggregated` key. - example: { "presence": { "website": { "timestamp": 1532697622, "status": "active", }, "ZulipMobile": { "timestamp": 1522687421, "status": "active", }, "aggregated": { "timestamp": 1532697622, "status": "active", } }, "result": "success", "msg": "" } /users/me: get: operationId: get_own_user tags: ["users"] description: | Get basic data about the user/bot that requests this endpoint. `GET {{ api_url }}/v1/users/me` responses: '200': description: Success content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - properties: avatar_url: type: string description: | URL for the user's avatar. **Changes**: New in Zulip 2.1.0. example: "x" avatar_version: type: integer description: | Version for the the user's avatar. Used for cache-busting requests for the user's avatar. Clients generally shouldn't need to use this; most avatar URLs sent by Zulip will already end with `?v={avatar_version}`. **Changes**: New in Zulip 2.2 (feature level 10). Previous versions do not return this field. example: 1 email: type: string description: | Email of the requesting user. example: "iago@zulip.com" full_name: type: string description: | Full name of the requesting user. example: "Iago" is_admin: type: boolean description: | A boolean indicating if the requesting user is an admin. example: true is_owner: type: boolean description: | A boolean indicating if the requesting user is an organization owner. **Changes**: New in Zulip 2.2 (feature level 8). example: false is_guest: type: boolean description: | A boolean indicating if the requesting user is a guest. **Changes**: New in Zulip 2.2 (feature level 10). Previous versions do not return this field. example: false is_bot: type: boolean description: | A boolean indicating if the requesting user is a bot. example: false is_active: type: boolean description: | A boolean specifying whether the user account has been deactivated. **Changes**: New in Zulip 2.2 (feature level 10). Previous versions do not return this field. example: true timezone: type: string description: | The time zone of the user. **Changes**: New in Zulip 2.2 (feature level 10). Previous versions do not return this field. example: "" date_joined: type: string description: | The time the user account was created. **Changes**: New in Zulip 2.2 (feature level 10). Previous versions do not return this field. example: "2019-10-20T07:50:53.728864+00:00" max_message_id: type: integer description: | The integer ID of the last message received by your account. **Deprecated**. We plan to remove this in favor of recommending using `GET /messages` with `anchor="newest"`. example: 30 pointer: type: integer description: | The integer ID of the message that the pointer is currently on. **Deprecated**. We plan to remove the `pointer` as a concept in Zulip. example: -1 user_id: type: integer description: | The user's ID. example: 1 profile_data: $ref: '#/components/schemas/profile_data' - example: { "avatar_url": "https://secure.gravatar.com/avatar/af4f06322c177ef4e1e9b2c424986b54?d=identicon&version=1", "avatar_version": 1, "email": "iago@zulip.com", "full_name": "Iago", "is_admin": true, "is_owner": false, "is_guest": false, "is_bot": false, "is_active": true, "timezone": "", "date_joined": "2019-10-20T07:50:53.728864+00:00", "max_message_id": 30, "msg": "", "pointer": -1, "result": "success", "user_id": 5, "profile_data": { "5": { "value": "2000-1-1" }, "4": { "value": "emacs" }, "7": { "value": "[10]" }, "1": { "value": "+1-234-567-8901", "rendered_value": "

+1-234-567-8901

" }, "2": { "rendered_value": "

Betrayer of Othello.

", "value": "Betrayer of Othello." }, "8": { "value": "zulip" }, "3": { "value": "Apples", "rendered_value": "

Apples

" }, "6": { "value": "https://zulip.readthedocs.io/en/latest/" } } } delete: operationId: deactivate_my_account tags: ["users"] description: | Delete the requesting user from the realm. responses: '200': description: Bad Request content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - example: { "msg": "", "result": "success", } '400': description: Bad Request content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonError' - example: { "msg": "Cannot deactivate the only organization administrator", "result": "error" } /users/me/{stream_id}/topics: get: operationId: get_stream_topics tags: ["streams"] description: | Get all the topics in a specific stream `GET {{ api_url }}/v1/users/me/{stream_id}/topics` parameters: - $ref: '#/components/parameters/StreamIdInPath' responses: '200': description: Success. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - properties: topics: type: array description: | An array of `topic` objects. items: type: object properties: max_id: description: | The message ID of the last message sent to this topic. type: integer name: description: | The name of the topic. type: string - example: { "msg": "", "result": "success", "topics": [ { "max_id": 26, "name": "Denmark3" }, { "max_id": 23, "name": "Denmark1" }, { "max_id": 6, "name": "Denmark2" } ] } '400': description: Bad request. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonError' - example: { "code": "BAD_REQUEST", "msg": "Invalid stream id", "result": "error" } /users/me/subscriptions: get: operationId: get_subscriptions tags: ["streams"] description: | Get all streams that the user is subscribed to. `GET {{ api_url }}/v1/users/me/subscriptions` # operationId can be used to record which view function # corresponds to an endpoint. TODO: Add these for more # endpoints, and perhaps use this to provide links to implementations. parameters: - $ref: '#/components/parameters/IncludeSubscribers' responses: '200': description: Success. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' # TODO: Is this the best way to declare required elements in 200 responses? - required: - subscriptions - properties: subscriptions: type: array description: | A list of dictionaries where each dictionary contains information about one of the subscribed streams. items: type: object properties: stream_id: type: integer description: | The unique ID of a stream. name: type: string description: | The name of a stream. description: type: string description: | The short description of a stream in text/markdown format, intended to be used to prepopulate UI for editing a stream's description. rendered_description: type: string description: | A short description of a stream rendered as HTML, intended to be used when displaying the stream description in a UI. One should use the standard Zulip rendered_markdown CSS when displaying this content so that emoji, LaTeX, and other syntax work correctly. And any client-side security logic for user-generated message content should be applied when displaying this HTML as though it were the body of a Zulip message. invite_only: type: boolean description: | Specifies whether the stream is private or not. Only people who have been invited can access a private stream. # TODO: This subscribers item should probably be declared optional more # explicitly in the OpenAPI format? subscribers: type: array items: type: integer description: | A list of user IDs of users who are also subscribed to a given stream. Included only if `include_subscribers` is `true`. desktop_notifications: type: boolean nullable: true description: | A boolean specifying whether desktop notifications are enabled for the given stream. A null value means the value of this setting should be inherited from the user-level default setting, enable_stream_desktop_notifications, for this stream. email_notifications: type: boolean nullable: true description: | A boolean specifying whether email notifications are enabled for the given stream. A null value means the value of this setting should be inherited from the user-level default setting, enable_stream_email_notifications, for this stream. wildcard_mentions_notify: type: boolean nullable: true description: | A boolean specifying whether wildcard mentions trigger notifications as though they were personal mentions in this stream. A null value means the value of this setting should be inherited from the user-level default setting, wildcard_mentions_notify, for this stream. push_notifications: type: boolean nullable: true description: | A boolean specifying whether push notifications are enabled for the given stream. A null value means the value of this setting should be inherited from the user-level default setting, enable_stream_push_notifications, for this stream. audible_notifications: type: boolean nullable: true description: | A boolean specifying whether audible notifications are enabled for the given stream. A null value means the value of this setting should be inherited from the user-level default setting, enable_stream_audible_notifications, for this stream. pin_to_top: type: boolean description: | A boolean specifying whether the given stream has been pinned to the top. email_address: type: string description: | Email address of the given stream, used for [sending emails to the stream](/help/message-a-stream-by-email). is_muted: type: boolean description: | Whether the user has muted the stream. Muted streams do not count towards your total unread count and do not show up in `All messages` view (previously known as `Home` view). **Changes**: Prior to Zulip 2.1, this feature was represented by the more confusingly named `in_home_view` (with the opposite value, `in_home_view=!is_muted`). in_home_view: type: boolean description: | Legacy property for if the given stream is muted, with inverted meeting. **Deprecated**; clients should use is_muted where available. is_old_stream: type: boolean description: | Whether the stream is old enough to have data in `stream_weekly_traffic`. **Deprecated**: To me removed. Clients should simply check whether stream_weekly_traffic is null. is_announcement_only: type: boolean description: | Whether only organization administrators can post to the stream. **Changes**: Deprecated in Zulip 2.2 (feature level 1), use `stream_post_policy` instead. is_web_public: type: boolean description: | Whether the stream has been configured to allow unauthenticated access to its message history from the web. color: type: string description: | The user's personal color for the stream. stream_post_policy: type: integer description: | Policy for which users can post messages to the stream. * 1 => Any user can post. * 2 => Only administrators can post. * 3 => Only new members can post. **Changes**: New in Zulip 2.2, replacing the previous `is_announcement_only` boolean. history_public_to_subscribers: type: boolean description: | Whether the history of the stream is public to its subscribers. Currently always true for public streams (i.e. invite_only=False implies history_public_to_subscribers=True), but clients should not make that assumption, as we may change that behavior in the future. first_message_id: type: integer description: | The id of the first message in the stream. Intended to help clients determine whether they need to display UI like the "more topics" widget that would suggest the stream has older history that can be accessed. stream_weekly_traffic: type: integer nullable: true description: | The average number of messages sent to the stream in recent weeks, rounded to the nearest integer. Null means the stream was recently created and there is insufficient data to estimate the average traffic. - example: { "msg": "", "result": "success", "subscriptions": [ { "audible_notifications": true, "color": "#e79ab5", "description": "A Scandinavian country", "desktop_notifications": true, "email_address": "Denmark+187b4125ed36d6af8b5d03ef4f65c0cf@zulipdev.com:9981", "is_muted": false, "invite_only": false, "name": "Denmark", "pin_to_top": false, "push_notifications": false, "stream_id": 1, "subscribers": [ 7, 10, 11, 12, 14 ] }, { "audible_notifications": true, "color": "#e79ab5", "description": "Located in the United Kingdom", "desktop_notifications": true, "email_address": "Scotland+f5786390183e60a1ccb18374f9d05649@zulipdev.com:9981", "is_muted": false, "invite_only": false, "name": "Scotland", "pin_to_top": false, "push_notifications": false, "stream_id": 3, "subscribers": [ 7, 11, 12, 14 ] } ] } post: operationId: subscribe tags: ["streams"] description: | Subscribe one or more users to one or more streams. `POST {{ api_url }}/v1/users/me/subscriptions` If any of the specified streams do not exist, they are automatically created, and configured using the `invite_only` setting specified in the arguments (see below). parameters: - name: subscriptions in: query description: | "A list of dictionaries containing the the key `name` and value specifying the name of the stream to subscribe. If the stream does not exist a new stream is created. The description of the stream created can be specified by setting the dictionary key `description` with an appropriate value. **Note**: This argument is called `streams` and not `subscriptions` in our Python API." schema: type: array items: type: object example: [{"name": "Verona", "description": "Italian City"}] required: true - name: invite_only in: query description: | A boolean specifying whether the streams specified in `subscriptions` are invite-only or not. schema: type: boolean default: false example: true - $ref: '#/components/parameters/Principals' - name: authorization_errors_fatal in: query description: | A boolean specifying whether authorization errors (such as when the requesting user is not authorized to access a private stream) should be considered fatal or not. When `True`, an authorization error is reported as such. When set to `False`, the returned JSON payload indicates that there was an authorization error, but the response is still considered a successful one. schema: type: boolean default: true example: false - $ref: '#/components/parameters/HistoryPublicToSubscribers' - $ref: '#/components/parameters/StreamPostPolicy' - name: announce in: query description: | If `announce` is `True` and one of the streams specified in `subscriptions` has to be created (i.e. doesn't exist to begin with), an announcement will be made notifying that a new stream was created. schema: type: boolean example: true responses: '200': description: Success. content: application/json: schema: oneOf: - allOf: - $ref: '#/components/schemas/AddSubscriptionsResponse' - example: { "already_subscribed": {}, "msg": "", "result": "success", "subscribed": { "iago@zulip.com": [ "new stream" ] } } - allOf: - $ref: '#/components/schemas/AddSubscriptionsResponse' - example: { "already_subscribed": { "newbie@zulip.com": [ "new stream" ] }, "msg": "", "result": "success", "subscribed": {} } '400': description: Success. content: application/json: schema: oneOf: - allOf: - $ref: '#/components/schemas/AddSubscriptionsResponse' - example: { "msg": "Unable to access stream (private_stream).", "result": "error" } - allOf: - $ref: '#/components/schemas/AddSubscriptionsResponse' - example: { "already_subscribed": {}, "msg": "", "result": "success", "subscribed": {}, "unauthorized": [ "private_stream" ] } patch: operationId: update_subscriptions tags: ["streams"] description: | Update which streams you are are subscribed to. parameters: - name: delete in: query description: | A list of stream names to unsubscribe from. schema: type: array items: type: string example: ['Verona', 'Denmark'] required: false - name: add in: query description: | A list of objects describing which streams to subscribe to, optionally including per-user subscription parameters (e.g. color) and if the stream is to be created, its description. schema: type: array items: type: object properties: name: type: string color: type: string description: type: string example: [ { "name": "Verona" }, { "name": "Denmark", "color": "#e79ab5", "description": "A Scandinavian country", } ] required: false responses: '200': description: Success. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - required: - subscribed - already_subscribed - removed - properties: subscribed: type: object description: | A dictionary where the key is the email address of the user/bot and the value is a list of the names of the streams that were subscribed to as a result of the query. additionalProperties: description: | `{email_id}`: A list of the names of streams that the user was subscribed to as a result of the query. type: array items: type: string already_subscribed: type: object description: | A dictionary where the key is the email address of the user/bot and the value is a list of the names of the streams that the user/bot is already subscribed to. additionalProperties: description: | `{email_id}`: A list of the names of streams that the user was already subscribed to. type: array items: type: string not_removed: type: array items: type: string description: | A list of the names of streams that the user is already unsubscribed from, and hence doesn't need to be unsubscribed. removed: type: array items: type: string description: | A list of the names of streams which were unsubscribed from as a result of the query. - example: { "msg": "", "subscribed": {}, "already_subscribed": {"iago@zulip.com":["Verona"]}, "not_removed": [], "removed": [ "new stream" ], "result": "success" } delete: operationId: unsubscribe tags: ["streams"] description: | Unsubscribe yourself or other users from one or more streams. `DELETE {{ api_url }}/v1/users/me/subscriptions` parameters: - name: subscriptions in: query description: | A list of stream names to unsubscribe from. This argument is called `streams` in our Python API. schema: type: array items: type: string example: ['Verona', 'Denmark'] required: true - $ref: '#/components/parameters/Principals' responses: '200': description: Success. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - properties: not_removed: type: array items: type: string description: | A list of the names of streams that the user is already unsubscribed from, and hence doesn't need to be unsubscribed. removed: type: array items: type: string description: | A list of the names of streams which were unsubscribed from as a result of the query. - example: { "msg": "", "not_removed": [], "removed": [ "new stream" ], "result": "success" } '400': description: Bad request. content: application/json: schema: $ref: '#/components/schemas/NonExistingStreamError' /users/{user_id}/subscriptions/{stream_id}: get: operationId: get_subscription_status tags: ["streams"] description: | Check whether a user is subscribed to a stream. `GET {{ api_url }}/v1/users/{user_id}/subscriptions/{stream_id}` **Changes**: New in Zulip 2.2 (feature level 11). parameters: - $ref: '#/components/parameters/UserId' example: 7 - $ref: '#/components/parameters/StreamIdInPath' example: 1 responses: '200': description: Success content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - properties: is_subscribed: type: boolean description: | Whether the user is subscribed to the stream. - example: { "msg": "", "result": "success", "is_subscribed": false } /users/me/subscriptions/muted_topics: patch: operationId: mute_topic tags: ["streams"] description: | This endpoint mutes/unmutes a topic within a stream that the current user is subscribed to. Muted topics are displayed faded in the Zulip UI, and are not included in the user's unread count totals. `PATCH {{ api_url }}/v1/users/me/subscriptions/muted_topics` parameters: - $ref: '#/components/parameters/Stream' required: false - $ref: '#/components/parameters/StreamIdInQuery' required: false - name: topic in: query description: | The topic to (un)mute. Note that the request will succeed regardless of whether any messages have been sent to the specified topic. schema: type: string example: dinner required: true - name: op in: query description: | Whether to mute (`add`) or unmute (`remove`) the provided topic. schema: type: string enum: - add - remove example: add required: true responses: '200': description: Success. content: application/json: schema: $ref: '#/components/schemas/JsonSuccess' '400': description: Bad request. content: application/json: schema: oneOf: - allOf: - $ref: '#/components/schemas/JsonError' - example: { "msg": "Topic already muted", "result": "error" } - allOf: - $ref: '#/components/schemas/JsonError' - example: { "msg": "Topic is not muted", "result": "error" } /realm/emoji/{emoji_name}: post: operationId: upload_custom_emoji tags: ["server_and_organizations"] description: | This endpoint is used to upload a custom emoji for use in the user's organization. Access to this endpoint depends on the [organization's configuration](https://zulip.com/help/only-allow-admins-to-add-emoji). `POST {{ api_url }}/v1/realm/emoji/{emoji_name}` parameters: - name: emoji_name required: true in: path description: | The name that should be associated with the uploaded emoji image/gif. schema: type: string requestBody: content: multipart/form-data: schema: properties: filename: type: string format: binary example: /path/to/img.png responses: '200': description: Success. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' /realm/emoji: get: operationId: get_custom_emoji tags: ["server_and_organizations"] description: | Get all the custom emoji in the user's organization. `GET {{ api_url }}/v1/realm/emoji` responses: '200': description: Success. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - properties: emoji: type: object description: | An object that contains `emoji` objects, each identified with their emoji ID as the key. additionalProperties: type: object description: | `{emoji_id}`: Object containing details about the emoji with the specified ID. It has the following properties: properties: id: type: string description: | The ID for this emoji, same as the object's key. name: type: string description: | The user-friendly name for this emoji. Users in the organization can use this emoji by writing this name between colons (`:name :`). source_url: type: string description: | The path relative to the organization's URL where the emoji's image can be found. deactivated: type: boolean description: | Whether the emoji has been deactivated or not. author_id: type: integer nullable: true description: | The user ID of the user who uploaded the custom emoji. Will be null if the uploader is unknown. **Changes**: New in Zulip 2.2 (feature level 7). Previously was accessible via and `author` object with an `id` field. - example: { "result": "success", "msg": "", "emoji": { "1": { "id": "1", "name": "green_tick", "source_url": "/user_avatars/1/emoji/images/1.png", "deactivated": false, "author_id": 5 } } } /users/me/subscriptions/properties: post: operationId: update_subscription_settings tags: ["streams"] description: | This endpoint is used to update the user's personal settings for the streams they are subscribed to, including muting, color, pinning, and per-stream notification settings. `POST {{ api_url }}/v1/users/me/subscriptions/properties` parameters: - name: subscription_data in: query description: | A list of objects that describe the changes that should be applied in each subscription. Each object represents a subscription, and must have a `stream_id` key that identifies the stream, as well as the `property` being modified and its new `value`. schema: type: array items: type: object example: [{"stream_id": 1, "property": "pin_to_top", "value": true}, {"stream_id": 3, "property": "color", "value": '#f00f00'}] required: true responses: '200': description: Success. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - properties: subscription_data: type: array items: type: object properties: property: type: string description: | The property to be changed. It is one of: *`color`: The hex value of the user's personal display color for the stream. *`is_muted`: Whether the stream is [muted](/help/mute-a-stream). **Changes**: Prior to Zulip 2.1, this feature was represented by the more confusingly named `in_home_view` (with the opposite value, `in_home_view=!is_muted`); for backwards-compatibility, modern Zulip still accepts that value. *`pin_to_top`: Whether to pin the stream at the top of the stream list. *`desktop_notifications`: Whether to show desktop notifications for all messages sent to the stream. *`audible_notifications`: Whether to play a sound notification for all messages sent to the stream. *`push_notifications`: Whether to trigger a mobile push notification for all messages sent to the stream. *`email_notifications`: Whether to trigger an email notification for all messages sent to the stream. enum: - color - push_notifications - is_muted - pin_to_top - desktop_notifications - audible_notifications - push_notifications - email_notifications value: description: | The desired value of the property oneOf: - type: boolean - type: string stream_id: description: | The desired value of the property type: integer description: | The same `subscription_data` array sent by the client for the request. - example: { "subscription_data": [ { "property": "pin_to_top", "value": true, "stream_id": 1 }, { "property": "color", "value": '#f00f00', "stream_id": 3 } ], "result": "success", "msg": "" } /realm/filters: get: operationId: get_linkifiers tags: ["server_and_organizations"] description: | List all of an organization's configured [linkifiers](/help/add-a-custom-linkification-filter), regular expression patterns that are automatically linkified when they appear in messages and topics. `GET {{ api_url }}/v1/realm/filters` responses: '200': description: Success. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - properties: filters: type: array items: type: array items: oneOf: - type: string - type: integer description: | An array of tuples, each representing one of the linkifiers set up in the organization. Each of these tuples contain the pattern, the formatted URL and the filter's ID, in that order. See the [Create linkifiers](/api/add-linkifiers) article for details on what each field means. - example: { "msg": "", "filters": [ [ "#(?P[0-9]+)", "https://github.com/zulip/zulip/issues/%(id)s", 1 ] ], "result": "success" } post: operationId: add_linkifier tags: ["server_and_organizations"] description: | Configure [linkifiers](/help/add-a-custom-linkification-filter), regular expression patterns that are automatically linkified when they appear in messages and topics. `POST {{ api_url }}/v1/realm/filters` parameters: - name: pattern in: query description: | The [Python regular expression](https://docs.python.org/3/howto/regex.html) that should trigger the linkifier. schema: type: string example: '#(?P[0-9]+)' required: true - name: url_format_string in: query description: | The URL used for the link. If you used named groups for the `pattern`, you can insert their content here with `%(name_of_the_capturing_group)s`. schema: type: string example: https://github.com/zulip/zulip/issues/%(id)s required: true responses: '200': description: Success. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - properties: id: type: integer description: | The numeric ID assigned to this filter. - example: { "id": 42, "result": "success", "msg": "" } /realm/filters/{filter_id}: delete: operationId: remove_linkifier tags: ["server_and_organizations"] description: | Remove [linkifiers](/help/add-a-custom-linkification-filter), regular expression patterns that are automatically linkified when they appear in messages and topics. `DELETE {{ api_url }}/v1/realm/filters/{filter_id}` parameters: - name: filter_id in: path description: | The ID of the filter that you want to remove. schema: type: integer example: 42 required: true responses: '200': description: Success. content: application/json: schema: $ref: '#/components/schemas/JsonSuccess' /register: post: operationId: register_queue tags: ["real_time_events"] description: | This powerful endpoint can be used to register a Zulip "event queue" (subscribed to certain types of "events", or updates to the messages and other Zulip data the current user has access to), as well as to fetch the current state of that data. parameters: - name: apply_markdown in: query description: | Set to `true` if you would like the content to be rendered in HTML format (otherwise the API will return the raw text that the user entered) schema: type: boolean default: false example: true - $ref: '#/components/parameters/ClientGravatar' - name: slim_presence in: query description: | Setting this to `true` will make presence dictionaries be keyed by user_id instead of email. **Changes**: New in Zulip 2.2 (Unstable with no feature level yet). schema: type: boolean default: false example: true - $ref: '#/components/parameters/Event_types' example: ['message'] - name: all_public_streams in: query description: | Set to `True` if you would like to receive events that occur within all public streams. schema: type: boolean default: false example: true - $ref: '#/components/parameters/IncludeSubscribers' - name: client_capabilities in: query description: | Dictionary containing details on features the client supports that are relevant to the format of responses sent by the server. * `notification_settings_null`: Boolean for whether the client can handle the current API with null values for stream-level notification settings (which means the stream is not customized and should inherit the user's global notification settings for stream messages). New in Zulip 2.1.0; in earlier Zulip releases, stream-level notification settings were simple booleans. schema: type: object example: { "notification_settings_null": true } - name: fetch_event_types in: query description: | Same as the `event_types` argument except that the values in `fetch_event_types` are used to fetch initial data. If `fetch_event_types` is not provided, `event_types` is used and if `event_types` is not provided, this argument defaults to `None`. schema: type: array items: type: string example: ['message'] - $ref: '#/components/parameters/Narrow' responses: '200': description: Success. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - properties: queue_id: type: string description: | The ID of the queue that has been allocated for your client. last_event_id: type: integer description: | The initial value of `last_event_id` to pass to `GET /api/v1/events`. zulip_feature_level: type: integer description: | The server's current [Zulip feature level](/api/changelog). zulip_version: type: string description: | The server's version. - example: { "last_event_id": -1, "msg": "", "queue_id": "1517975029:0", "realm_emoji": { "1": { "author_id": 5, "deactivated": false, "id": "1", "name": "green_tick", "source_url": "/user_avatars/1/emoji/images/1.png" } }, "result": "success", "zulip_feature_level": 2, "zulip_version": "2.1.0" } /server_settings: get: operationId: get_server_settings tags: ["server_and_organizations"] description: | Fetch global settings for a Zulip server. `GET {{ api_url }}/v1/server_settings` **Note:** this endpoint does not require any authentication at all, and you can use it to check: * If this is a Zulip server, and if so, what version of Zulip it's running. * What a Zulip client (e.g. a mobile app or [zulip-terminal](https://github.com/zulip/zulip-terminal/)) needs to know in order to display a login prompt for the server (e.g. what authentication methods are available). responses: '200': description: Success. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - properties: authentication_methods: type: object description: | Each key-value pair in the object indicates whether the authentication method is enabled on this server. **Changes**: Deprecated in Zulip 2.1, in favor of the more expressive `external_authentication_methods`. properties: password: description: | Whether the user can authenticate using password. type: boolean dev: description: | Whether the user can authenticate using development api key. type: boolean email: description: | Whether the user can authenticate using email. type: boolean ldap: description: | Whether the user can authenticate using ldap. type: boolean remoteuser: description: | Whether the user can authenticate using remoteuser. type: boolean github: description: | Whether the user can authenticate using their github account. type: boolean azuread: description: | Whether the user can authenticate using their azuread account. type: boolean gitlab: description: | Whether the user can authenticate using their gitlab account. type: boolean apple: description: | Whether the user can authenticate using their apple account. type: boolean google: description: | Whether the user can authenticate using their google account. type: boolean saml: description: | Whether the user can authenticate using saml. type: boolean external_authentication_methods: type: array description: | A list of dictionaries describing the available external authentication methods (E.g. Google, GitHub, or SAML) enabled for this organization. The list is sorted in the order in which these authentication methods should be displayed. **Changes**: New in Zulip 2.1. items: type: object properties: name: type: string description: | A unique, table, machine-readable name for the authentication method, intended to be used by clients with special behavior for specific authenatication methods to correctly identify the method. display_name: type: string description: | Display name of the authentication method, to be used in all buttons for the authentication method. display_icon: type: string nullable: true description: | URL for an image to be displayed as an icon in all buttons for the external authentication method. When null, no icon should be displayed. login_url: type: string description: | URL to be used to initiate authentication using this method. signup_url: type: string description: | URL to be used to initiate account registration using this method. zulip_version: type: string description: | The version of Zulip running in the server. zulip_feature_level: type: integer description: | An integer indicating what features are available on the server. The feature level increases monotonically; a value of N means the server supports all API features introduced before feature level N. This is designed to provide a simple way for client apps to decide whether the server supports a given feature or API change. See the [changelog](/api/changelog) for details on what each feature level means. **Changes**. New in Zulip 2.2. We recommend using an implied value of 0 for Zulip servers that do not send this field. push_notifications_enabled: type: boolean description: | Whether mobile/push notifications are enabled. is_incompatible: type: boolean description: | Whether the Zulip client that has sent a request to this endpoint is deemed incompatible with the server. email_auth_enabled: type: boolean description: | Setting for allowing users authenticate with an email-password combination. require_email_format_usernames: type: boolean description: | Whether all valid usernames for authentication to this organization will be email addresses. This is important for clients to know whether to do client side validation of email address format in a login prompt. This value will be false if the server has [LDAP authentication][ldap-auth] enabled with a username and password combination. realm_uri: type: string description: | The organization's canonical URL. realm_name: type: string description: | The organization's name (for display purposes). realm_icon: type: string description: | The URL for the organization's logo formatted as a square image, used for identifying the organization in small locations in the mobile and desktop apps. realm_description: type: string description: | HTML description of the organization, as configured by the [organization profile](/help/create-your-organization-profile). - example: { "authentication_methods": { "password": true, "dev": true, "email": true, "ldap": false, "remoteuser": false, "github": true, "azuread": false, "google": true, "saml": true }, "zulip_version": "2.0.6+git", "push_notifications_enabled": false, "msg": "", "is_incompatible": false, "email_auth_enabled": true, "require_email_format_usernames": true, "realm_uri": "http://localhost:9991", "realm_name": "Zulip Dev", "realm_icon": "https://secure.gravatar.com/avatar/62429d594b6ffc712f54aee976a18b44?d=identicon", "realm_description": "

The Zulip development environment default organization. It's great for testing!

", "result": "success", "external_authentication_methods": [ { "name": "saml:idp_name", "display_name": "SAML", "display_icon": null, "login_url": "/accounts/login/social/saml/idp_name", "signup_url": "/accounts/register/social/saml/idp_name" }, { "name": "google", "display_name": "Google", "display_icon": "/static/images/landing-page/logos/googl_e-icon.png", "login_url": "/accounts/login/social/google", "signup_url": "/accounts/register/social/google" }, { "name": "github", "display_name": "GitHub", "display_icon": "/static/images/landing-page/logos/github-icon.png", "login_url": "/accounts/login/social/github", "signup_url": "/accounts/register/social/github" } ] } /settings/notifications: patch: operationId: update_notification_settings tags: ["users"] description: | This endpoint is used to edit the user's global notification settings. See [this endpoint](/api/update-subscription-properties) for per-stream notification settings. `PATCH {{ api_url }}/v1/settings/notifications` parameters: - name: enable_stream_desktop_notifications in: query description: | Enable visual desktop notifications for stream messages. schema: type: boolean example: true - name: enable_stream_email_notifications in: query description: | Enable email notifications for stream messages. schema: type: boolean example: true - name: enable_stream_push_notifications in: query description: | Enable mobile notifications for stream messages. schema: type: boolean example: true - name: enable_stream_audible_notifications in: query description: | Enable audible desktop notifications for stream messages. schema: type: boolean example: true - name: notification_sound in: query description: | Notification sound name. content: application/json: schema: type: string example: ding - name: enable_desktop_notifications in: query description: | Enable visual desktop notifications for private messages and @-mentions. schema: type: boolean example: true - name: enable_sounds in: query description: | Enable audible desktop notifications for private messages and @-mentions. schema: type: boolean example: true - name: enable_offline_email_notifications in: query description: | Enable email notifications for private messages and @-mentions received when the user is offline. schema: type: boolean example: true - name: enable_offline_push_notifications in: query description: | Enable mobile notification for private messages and @-mentions received when the user is offline. schema: type: boolean example: true - name: enable_online_push_notifications in: query description: | Enable mobile notification for private messages and @-mentions received when the user is online. schema: type: boolean example: true - name: enable_digest_emails in: query description: | Enable digest emails when the user is away. schema: type: boolean example: true - name: enable_login_emails in: query description: | Enable email notifications for new logins to account. schema: type: boolean example: true - name: message_content_in_email_notifications in: query description: | Include the message's content in missed messages email notifications. schema: type: boolean example: true - name: pm_content_in_desktop_notifications in: query description: | Include content of private messages in desktop notifications. schema: type: boolean example: true - name: wildcard_mentions_notify in: query description: | Whether wildcard mentions (E.g. @**all**) should send notifications like a personal mention. schema: type: boolean example: true - name: desktop_icon_count_display in: query description: | > Unread count summary (appears in desktop sidebar and browser tab) * 1 - All unreads * 2 - Private messages and mentions * 3 - None schema: type: integer enum: - 1 - 2 - 3 example: 1 - name: realm_name_in_notifications in: query description: | Include organization name in subject of missed message emails. schema: type: boolean example: true - name: presence_enabled in: query description: | Display the presence status to other users when online. schema: type: boolean example: true responses: '200': description: Success. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - properties: enable_desktop_notifications: type: boolean description: | The setting for `enable_desktop_notifications`, if it was changed in this request. enable_digest_emails: type: boolean description: | The setting for `enable_digest_emails`, if it was changed in this request. enable_offline_email_notifications: type: boolean description: | The setting for `enable_offline_email_notifications`, if it was changed in this request. enable_offline_push_notifications: type: boolean description: | The setting for `enable_offline_push_notifications`, if it was changed in this request. enable_online_push_notifications: type: boolean description: | The setting for `enable_online_push_notifications`, if it was changed in this request. enable_sounds: type: boolean description: | The setting for `enable_sounds`, if it was changed in this request. enable_stream_email_notifications: type: boolean description: | The setting for `enable_stream_email_notifications`, if it was changed in this request. enable_stream_push_notifications: type: boolean description: | The setting for `enable_stream_push_notifications`, if it was changed in this request. enable_stream_audible_notifications: type: boolean description: | The setting for `enable_stream_audible_notifications`, if it was changed in this request. message_content_in_email_notifications: type: boolean description: | The setting for `message_content_in_email_notifications`, if it was changed in this request. - example: { "enable_offline_push_notifications": true, "enable_online_push_notifications": true, "msg": "", "result": "success" } /streams: get: operationId: get_streams tags: ["streams"] description: | Get all streams that the user has access to. `GET {{ api_url }}/v1/streams` parameters: - name: include_public in: query description: | Include all public streams. schema: type: boolean default: true example: false - name: include_subscribed in: query description: | Include all streams that the user is subscribed to. schema: type: boolean default: true example: false - name: include_all_active in: query description: | Include all active streams. The user must have administrative privileges to use this parameter. schema: type: boolean default: false example: true - name: include_default in: query description: | Include all default streams for the user's realm. schema: type: boolean default: false example: true - name: include_owner_subscribed in: query description: | If the user is a bot, include all streams that the bot's owner is subscribed to. schema: type: boolean default: false example: true responses: '200': description: Success. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - properties: streams: description: | A list of `stream` objects with details on the requested streams. type: array items: type: object properties: stream_id: type: integer description: | The unique ID of the stream. name: type: string description: | The name of the stream. description: type: string description: | The short description of the stream in text/markdown format, intended to be used to prepopulate UI for editing a stream's description. invite_only: type: boolean description: | Specifies whether the stream is private or not. Only people who have been invited can access a private stream. rendered_description: type: string description: | The short description of the stream rendered as HTML, intended to be used when displaying the stream description in a UI. One should use the standard Zulip rendered_markdown CSS when displaying this content so that emoji, LaTeX, and other syntax work correctly. And any client-side security logic for user-generated message content should be applied when displaying this HTML as though it were the body of a Zulip message. is_web_public: type: boolean description: | Whether the stream has been configured to allow unauthenticated access to its message history from the web. stream_post_policy: type: integer description: | Policy for which users can post messages to the stream. * 1 => Any user can post. * 2 => Only administrators can post. * 3 => Only new members can post. **Changes**: New in Zulip 2.2, replacing the previous `is_announcement_only` boolean. history_public_to_subscribers: type: boolean description: | Whether the history of the stream is public to its subscribers. Currently always true for public streams (i.e. invite_only=False implies history_public_to_subscribers=True), but clients should not make that assumption, as we may change that behavior in the future. first_message_id: type: integer description: | The id of the first message in the stream. Intended to help clients determine whether they need to display UI like the "more topics" widget that would suggest the stream has older history that can be accessed. is_announcement_only: type: boolean description: | Whether the given stream is announcement only or not. **Changes**: Deprecated in Zulip 2.2 (feature level 1), use `stream_post_policy` instead. - example: { "msg": "", "result": "success", "streams": [ { "description": "A Scandinavian country", "invite_only": false, "name": "Denmark", "stream_id": 1 }, { "description": "Yet another Italian city", "invite_only": false, "name": "Rome", "stream_id": 2 }, { "description": "Located in the United Kingdom", "invite_only": false, "name": "Scotland", "stream_id": 3 }, { "description": "A northeastern Italian city", "invite_only": false, "name": "Venice", "stream_id": 4 }, { "description": "A city in Italy", "invite_only": false, "name": "Verona", "stream_id": 5 }, { "description": "New stream for testing", "invite_only": false, "name": "new stream", "stream_id": 6 } ] } '400': description: Bad request. content: application/json: schema: allOf: - $ref: '#/components/schemas/CodedError' - example: { "code": "BAD_REQUEST", "msg": "User not authorized for this query", "result": "error" } /streams/{stream_id}: delete: operationId: delete_stream tags: ["streams"] description: | [Delete the stream](/help/delete-a-stream) with the ID `stream_id`. `DELETE {{ api_url }}/v1/streams/{stream_id}` parameters: - $ref: '#/components/parameters/StreamIdInPath' responses: '200': description: Success. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - example: { "msg": "", "result": "success" } '400': description: Bad request. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonError' - properties: msg: type: string - example: { "code": "BAD_REQUEST", "msg": "Invalid stream id", "result": "error" } patch: operationId: update_stream tags: ["streams"] description: | Configure the stream with the ID `stream_id`. This endpoint supports an organization administrator editing any property of a stream, including: * Stream [name](/help/rename-a-stream) and [description](/help/change-the-stream-description) * Stream [permissions](/help/stream-permissions), including [privacy](/help/change-the-privacy-of-a-stream) and [who can send](/help/stream-sending-policy). `PATCH {{ api_url }}/v1/streams/{stream_id}` parameters: - $ref: '#/components/parameters/StreamIdInPath' - name: description in: query description: | The new description for the stream. content: application/json: schema: type: string example: This stream is related to football dicsussions. required: false - name: new_name in: query description: | The new name for the stream. content: application/json: schema: type: string example: Italy required: false - name: is_private in: query description: | Change whether the stream is a private stream. schema: type: boolean example: true required: false - name: is_announcement_only in: query description: | Whether the stream is limited to announcements. **Changes**: Deprecated in Zulip 2.2 (feature level 1), use `stream_post_policy` instead. schema: type: boolean example: true required: false - $ref: '#/components/parameters/StreamPostPolicy' - $ref: '#/components/parameters/HistoryPublicToSubscribers' responses: '200': description: Success. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - example: { "msg": "", "result": "success" } '400': description: Bad request. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonError' - example: { "code": "BAD_REQUEST", "msg": "Invalid stream id", "result": "error" } /typing: post: operationId: set_typing_status tags: ["users"] description: | Send an event indicating that the user has started or stopped typing on their client. See [the typing notification docs](https://zulip.readthedocs.io/en/latest/subsystems/typing-indicators.html) for details on Zulip's typing notifications protocol. `POST {{ api_url }}/v1/typing` parameters: - name: op in: query description: | Whether the user has started (`start`) or stopped (`stop`) to type. schema: type: string enum: - start - stop example: start required: true - name: to in: query description: | The user_ids of the recipients of the message being typed. Typing notifications are only supported for private messages. Send a JSON-encoded list of user_ids. (Use a list even if there is only one recipient.). **Changes**: Before Zulip 2.0, this parameter accepted only a JSON-encoded list of email addresses. Support for the email address-based format was removed in Zulip 2.2 (feature level 11). schema: type: array items: type: integer example: [9, 10] required: true responses: '200': description: Success. content: application/json: schema: $ref: '#/components/schemas/JsonSuccess' /user_groups/create: post: operationId: create_user_group tags: ["users"] description: | Create a new [user group](/help/user-groups). `POST {{ api_url }}/v1/user_groups/create` parameters: - name: name in: query description: | The name of the user group. schema: type: string example: marketing required: true - name: description in: query description: | The description of the user group. schema: type: string example: The marketing team. required: true - name: members in: query description: | An array containing the user IDs of the initial members for the new user group. schema: type: array items: type: integer example: [1, 2, 3, 4] required: true responses: '200': description: Success. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - example: { "msg": "", "result": "success" } '400': description: Bad request. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonError' - example: { "result": "error", "code": "BAD_REQUEST", "msg": "Invalid user ID: 500" } /user_groups/{group_id}: patch: operationId: update_user_group tags: ["users"] description: | Update the name or description of a [user group](/help/user-groups). `PATCH {{ api_url }}/v1/user_groups/{group_id}` parameters: - $ref: '#/components/parameters/GroupId' - name: name in: query description: | The new name of the group. schema: type: string example: marketing team required: true - name: description in: query description: | The new description of the group. schema: type: string example: The marketing team. required: true responses: '200': $ref: '#/components/responses/SimpleSuccess' '400': description: Bad request. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonError' - example: { "code": "BAD_REQUEST", "msg": "Invalid user group", "result": "error" } delete: operationId: remove_user_group tags: ["users"] description: | Delete a [user group](/help/user-groups). `DELETE {{ api_url }}/v1/user_groups/{group_id}` parameters: - $ref: '#/components/parameters/GroupId' responses: '200': description: Success. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - example: { "result": "success", "msg": "", } '400': description: Bad request. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonError' - example: { "code": "BAD_REQUEST", "msg": "Invalid user group", "result": "error" } /user_groups: get: operationId: get_user_groups tags: ["users"] description: | Fetches all of the user groups in the organization. `GET {{ api_url }}/v1/user_groups` responses: '200': description: Success. content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - properties: user_groups: type: array items: type: object properties: description: type: string description: | The human-readable description of the user group. id: type: integer description: | The user group's integer id. members: type: array description: | The integer User IDs of the user group members. items: type: integer name: type: string description: | User group name. description: | A list of `user_group` objects, which contain a `description`, a `name`, their `id` and the list of members of the user group. - example: { "msg": "", "result": "success", "user_groups": [ { "description": "Characters of Hamlet", "id": 1, "name": "hamletcharacters", "members": [3, 4] }, { "description": "Other users", "id": 2, "name": "other users", "members": [1, 2] } ] } /real-time: # This entry is a hack; it exists to give us a place to put the text # documenting the arguments for call_on_each_event and friends. post: tags: ["real_time_events"] description: | (Ignored) parameters: - $ref: '#/components/parameters/Narrow' - $ref: '#/components/parameters/Event_types' example: ['message'] security: - basicAuth: [] responses: # Makeshift response for this hack entry. '200': description: Success /rest-error-handling: post: operationId: rest_error_handling tags: ["real_time_events"] description: | Common error to many endpoints responses: '400': description: | Bad request. content: application/json: schema: oneOf: - allOf: - $ref: '#/components/schemas/InvalidApiKeyError' - allOf: - $ref: '#/components/schemas/MissingArgumentError' - allOf: - $ref: '#/components/schemas/UserNotAuthorizedError' /zulip-outgoing-webhook: post: operationId: zulip_outgoing_webhooks tags: ["webhooks"] description: | Outgoing Webhooks allows to build or set up Zulip integrations which are notified when certain types of messages are sent in Zulip. responses: '200': description: | Success content: application/json: schema: allOf: - $ref: '#/components/schemas/JsonSuccess' - properties: data: type: string description: | It contains the content of the message (in Markdown). trigger: type: string description: | It contains the trigger method. token: type: string description: | A string of alphanumeric characters that can be use to authenticate the webhook request (each bot user uses a fixed token). message: type: object description: | A dict containing details on the message which triggered the outgoing webhook bot_email: type: string description: | Email of the bot user - example: { "data": "@**Outgoing Webhook Test** Zulip is the world\u2019s most productive group chat!", "trigger": "mention", "token": "xvOzfurIutdRRVLzpXrIIHXJvNfaJLJ0", "message": { "subject": "Verona2", "sender_email": "iago@zulip.com", "timestamp": 1527876931, "client": "website", "submessages": [ ], "recipient_id": 20, "topic_links": [ ], "sender_full_name": "Iago", "avatar_url": "https://secure.gravatar.com/avatar/1f4f1575bf002ae562fea8fc4b861b09?d=identicon&version=1", "rendered_content": "

@Outgoing Webhook Test Zulip is the world\u2019s most productive group chat!

", "sender_id": 5, "stream_id": 5, "content": "@**Outgoing Webhook Test** Zulip is the world\u2019s most productive group chat!", "display_recipient": "Verona", "type": "stream", "id": 112, "is_me_message": false, "reactions": [ ], "sender_realm_str": "zulip", "sender_short_name": "iago" }, "bot_email": "outgoing-bot@localhost" } components: ####################### # Security definitions ####################### securitySchemes: BasicAuth: type: http scheme: basic description: | Basic authentication, with the user's email as the username, and the API key as the password. The API key can be fetched using the `/fetch_api_key` or `/dev_fetch_api_key` endpoints. schemas: User: type: object description: | A dictionary containing basic data on a given Zulip user. properties: email: type: string description: | The Zulip API email address of the user or bot. If you do not have permission to view the email address of the target user, this will be a fake email address that is usable for the Zulip API but nothing else. is_bot: type: boolean description: | A boolean specifying whether the user is a bot or full account. avatar_url: type: string nullable: true description: | URL for the the user's avatar. Will be `null` if the `client_gravatar` query parameter was set to `True` and the user's avatar is hosted by the Gravatar provider (i.e. the user has never uploaded an avatar). avatar_version: type: integer description: | Version for the the user's avatar. Used for cache-busting requests for the user's avatar. Clients generally shouldn't need to use this; most avatar URLs sent by Zulip will already end with `?v={avatar_version}`. full_name: type: string description: | Full name of the user or bot, used for all display purposes. is_admin: type: boolean description: | A boolean specifying whether the user is an organization administrator. is_owner: type: boolean description: | A boolean specifying whether the user is an organization owner. If true, is_admin will also be true. **Changes**: New in Zulip 2.2 (feature level 8). bot_type: type: integer nullable: true description: | An integer describing the type of bot: * `null` if the user isn't a bot. * `1` for a `Generic` bot. * `2` for an `Incoming webhook` bot. * `3` for an `Outgoing webhook` bot. * `4` for an `Embedded` bot. user_id: type: integer description: | The unique ID of the user. bot_owner_id: type: integer nullable: true description: | If the user is a bot (i.e. `is_bot` is `True`), `bot_owner` is the user ID of the bot's owner (usually, whoever created the bot). Will be null for legacy bots that do not have an owner. **Changes**: New in Zulip 2.2 (feature level 1). In previous versions, there was a `bot_owner` field containing the email address of the bot's owner. is_active: type: boolean description: | A boolean specifying whether the user account has been deactivated. is_guest: type: boolean description: | A boolean specifying whether the user is a guest user. timezone: type: string description: | The time zone of the user. date_joined: type: string description: | The time the user account was created. profile_data: $ref: '#/components/schemas/profile_data' profile_data: type: object description: | A dictionary containing custom profile field data for the user. Each entry maps the integer ID of a custom profile field in the organization to a dictionary containing the user's data for that field. Generally the data includes just a single `value` key; for those custom profile fields supporting markdown, a `rendered_value` key will also be present. additionalProperties: type: object description: | '{id}': Object with data about what value user filled in the custom profile field with id `id`. properties: value: type: string description: | User's personal value for this custom profile field. rendered_value: type: string description: | The `value` rendered in HTML. Will only be present for custom profile field types that support markdown rendering. This user-generated HTML content should be rendered using the same CSS and client-side security protections as are used for message content. JsonResponse: type: object properties: result: type: string JsonSuccess: allOf: - $ref: '#/components/schemas/JsonResponse' - required: - result - msg - properties: result: enum: - success msg: type: string - example: { "msg": "", "result": "success" } JsonError: allOf: - $ref: '#/components/schemas/JsonResponse' - required: - result - msg - properties: result: enum: - error msg: type: string ApiKeyResponse: allOf: - $ref: '#/components/schemas/JsonSuccess' - required: - api_key - email - properties: api_key: type: string description: | The API key that can be used to authenticate as the requested user. email: type: string description: | The email address of the user who owns the API key. - example: { "api_key": "gjA04ZYcqXKalvYMA8OeXSfzUOLrtbZv", "email": "iago@zulip.com", "msg": "", "result": "success" } CodedError: allOf: - $ref: '#/components/schemas/JsonError' - properties: code: type: string description: | A string that identifies the error. BadEventQueueIdError: allOf: - $ref: '#/components/schemas/CodedError' - properties: queue_id: type: string description: | The string that identifies the invalid event queue. - example: { "code": "BAD_EVENT_QUEUE_ID", "msg": "Bad event queue id: 1518820930:1", "queue_id": "1518820930:1", "result": "error" } InvalidMessageError: allOf: - $ref: '#/components/schemas/JsonSuccess' - properties: raw_content: type: string description: | The raw content of the message. - example: { "msg": "Invalid message(s)", "code": "BAD_REQUEST", "result": "error" } NonExistingStreamError: allOf: - $ref: '#/components/schemas/CodedError' - properties: stream: type: string description: | The name of the stream that could not be found. - example: { "code": "STREAM_DOES_NOT_EXIST", "msg": "Stream 'nonexistent_stream' does not exist", "result": "error", "stream": "nonexistent_stream" } AddSubscriptionsResponse: allOf: - $ref: '#/components/schemas/JsonSuccess' - properties: subscribed: type: object description: | A dictionary where the key is the email address of the user/bot and the value is a list of the names of the streams that were subscribed to as a result of the query. additionalProperties: description: | `{email_address}`: List of the names of the streams that were subscribed to as a result of the query. type: array items: type: string already_subscribed: type: object description: | A dictionary where the key is the email address of the user/bot and the value is a list of the names of the streams that the user/bot is already subscribed to. additionalProperties: description: | {email_address}`: List of the names of the streams that the user is already subscribed to. type: array items: type: string unauthorized: type: array items: type: string description: | A list of names of streams that the requesting user/bot was not authorized to subscribe to. InvalidApiKeyError: allOf: - $ref: '#/components/schemas/JsonError' - example: { "msg": "Invalid API key", "result": "error" } MissingArgumentError: allOf: - $ref: '#/components/schemas/CodedError' - properties: var_name: type: string description: | It contains the information about the missing argument. - example: { "code": "REQUEST_VARIABLE_MISSING", "msg": "Missing 'content' argument", "result": "error", "var_name": "content" } UserNotAuthorizedError: allOf: - $ref: '#/components/schemas/CodedError' - example: { "code": "BAD_REQUEST", "msg": "User not authorized for this query", "result": "error" } ################### # Shared responses ################### responses: SimpleSuccess: description: Success. content: application/json: schema: $ref: '#/components/schemas/JsonSuccess' #################### # Shared parameters #################### parameters: Event_types: name: event_types in: query description: | A JSON-encoded array indicating which types of events you're interested in. Values that you might find useful include: * **message** (messages) * **subscription** (changes in your subscriptions) * **realm_user** (changes to users in the organization and their properties, such as their name). If you do not specify this argument, you will receive all events, and have to filter out the events not relevant to your client in your client code. For most applications, one is only interested in messages, so one specifies: `event_types=['message']` schema: type: array items: type: string required: false Narrow: name: narrow in: query description: | A JSON-encoded array of length 2 indicating the narrow for which you'd like to receive events for. For instance, to receive events for the stream `Denmark`, you would specify `narrow=['stream', 'Denmark']`. Another example is `narrow=['is', 'private']` for private messages. Default is `[]`. schema: type: array items: anyOf: - type: string - type: integer default: [] example: ['stream', 'Denmark'] required: false GroupId: name: group_id in: path description: | The ID of the target user group. schema: type: integer example: 42 required: true Topic: name: topic in: query description: | The topic of the message. Only required for stream messages (`type="stream"`), ignored otherwise. Maximum length of 60 characters. schema: type: string example: Castle QueueId: name: queue_id in: query description: | The ID of an event queue that was previously registered via `POST /api/v1/register` (see [Register a queue](/api/register-queue)). schema: type: string example: 1375801870:2942 required: true Stream: name: stream in: query description: | The name of the stream to access. schema: type: string example: Denmark StreamIdInQuery: name: stream_id in: query description: | The ID of the stream to access. schema: type: integer example: 42 StreamIdInPath: name: stream_id in: path description: | The ID of the stream to access. schema: type: integer example: 42 required: true ClientGravatar: name: client_gravatar in: query description: | Whether the client supports computing gravatars URLs. If enabled, `avatar_url` will be included in the response only if there is a Zulip avatar, and will be `null` for users who are using gravatar as their avatar. This option significantly reduces the compressed size of user data, since gravatar URLs are long, random strings and thus do not compress well. The `client_gravatar` field is set to `true` if clients can compute their own gravatars. schema: type: boolean default: false example: true Content: name: content in: query description: | The content of the message. Maximum message size of 10000 bytes. schema: type: string example: Hello required: true MessageId: name: message_id in: path description: | The target message's ID. schema: type: integer example: 42 required: true UserId: name: user_id in: path description: | The target user's ID. schema: type: integer example: 12 required: true StreamPostPolicy: name: stream_post_policy in: query description: | Policy for which users can post messages to the stream. * 1 => Any user can post. * 2 => Only administrators can post. * 3 => Only new members can post. **Changes**: New in Zulip 2.2, replacing the previous `is_announcement_only` boolean. schema: type: integer default: 1 example: 2 required: false HistoryPublicToSubscribers: name: history_public_to_subscribers in: query description: | Whether the stream's message history should be available to newly subscribed members, or users can only access messages they actually received while subscribed to the stream. Corresponds to the [shared history](/help/stream-permissions) option in documentation. schema: type: boolean default: None example: false required: false IncludeSubscribers: name: include_subscribers in: query description: | Whether each returned stream object should include a `subscribers` field containing a list of the user IDs of its subscribers. (This may be significantly slower in organizations with thousands of users subscribed to many streams.) **Changes**: New in Zulip 2.1.0. schema: type: boolean default: false example: true EmojiName: name: emoji_name in: query description: | The target emoji's human-readable name. To find an emoji's name, hover over a message to reveal three icons on the right, then click the smiley face icon. Images of available reaction emojis appear. Hover over the emoji you want, and note that emoji's text name. schema: type: string example: 'octopus' IncludeCustomProfileFields: name: include_custom_profile_fields in: query description: | Whether the client wants [custom profile field](/help/add-custom-profile-fields) data to be included in the response. **Changes**: New in Zulip 2.1.0. Previous versions do no offer these data via the API. schema: type: boolean default: false example: true Principals: name: principals in: query description: | A list of user ids (preferred) or Zulip display email addresses of the users to be subscribed to or unsubscribed from the streams specified in the `subscriptions` argument. If not provided, then the requesting user/bot is subscribed. **Changes**: The integer format is new in Zulip 2.2 (Feature level 9). schema: type: array items: oneOf: - type: string - type: integer default: [] example: ['ZOE@zulip.com'] ReactionType: name: reaction_type in: query description: | If an app is adding/removing a vote on an existing reaction, it should pass this parameter using the value the server provided for the existing reaction for specificity. Supported values: * `unicode_emoji`: Unicode emoji (`emoji_code` will be its unicode codepoint). * `realm_emoji`: Custom emoji. (`emoji_code` will be its ID). * `zulip_extra_emoji`: Special emoji included with Zulip. Exists to namespace the `zulip` emoji. **Changes**: In Zulip 2.2 (feature level 2), this become optional for [custom emoji](/help/add-custom-emoji); previously, this endpoint assumed `unicode_emoji` if this parameter was not specified. schema: type: string example: 'unicode_emoji' required: false EmojiCode: name: emoji_code in: query description: | A unique ID, defining the specific emoji codepoint requested, within the namespace of the `reaction_type`. For most API clients, you won't need this, but it's important for Zulip apps to handle rare corner cases when adding/removing votes on an emoji reaction added previously by another user. If the existing reaction was added when the Zulip server was using a previous version of the emoji data mapping between Unicode codepoints and human-readable names, sending the `emoji_code` in the data for the original reaction allows the Zulip server to correctly interpret your upvote as an upvote rather than a reaction with a "diffenent" emoji. schema: type: string example: '1f419' required: false