openapi: 3.0.0 info: title: Ably Chat REST API version: 4.0.0 description: | # Chat API This API enables you to integrate certain chat functionality into your application without requiring a Chat SDK. It provides endpoints for sending and retrieving messages, updating and deleting messages, and fetching occupancy information for chat rooms. ## The Ably PubSub SDKs Whilst you can interact with these endpoints directly, it is recommended where possible to use the Ably PubSub SDKs - which provide a convenient `request` method for interacting with Ably APIs. By using this method, you can take advantage of built-in support for Ably’s authentication, pagination, and link headers, as well as automatic retry and fallback mechanics. This approach helps ensure consistent error handling, reduces setup overhead, and simplifies performing common operations against the Chat REST API. Using this method, instead of implementing your own request handling, will lead to more robust and maintainable client-side integrations. servers: - url: https://main.realtime.ably.net/ description: Production server for Ably REST API components: schemas: ErrorInfo: type: object properties: error: type: object properties: message: type: string description: Description of the error. example: "Invalid request payload. 'text' field is required." code: type: integer description: A unique error code generated by the server. example: 40001 statusCode: type: integer description: The HTTP status code associated with the error. example: 400 href: type: string description: A link to the relevant documentation for this error. example: "https://help.ably.io/error/40001" Message: type: object required: - text properties: text: type: string description: The content of the message example: "Hello world!" clientId: type: string description: The ID of the client that sent the message example: "user123" headers: type: object description: Optional headers for additional message context. example: { relativeTime: "10ms", urgency: "low" } metadata: type: object description: Additional metadata or properties associated with the message. example: { type: "chat", imageUrl: "https://example.com/image.jpg" } userClaim: type: string description: > The user claim attached to this message by the server. This is set automatically by the Ably server when the publishing user's JWT contains a matching `ably.room.` claim. This value is read-only and cannot be set by the client. example: '{"display_name":"Alice","role":"moderator"}' roomId: type: string description: The unique identifier of the room the message belongs to example: "room123" deprecated: true serial: type: string description: The unique identifier for the message example: "01726232498871-001@abcdefghij:001" timestamp: type: number format: unix-timestamp description: The timestamp when the message was created example: 1741973127428 action: type: string description: The action type of the message enum: [ message.create, message.update, message.delete ] example: "message.create" version: type: object description: Contains information about the current version of the message properties: serial: type: string description: The unique identifier for this version of the message. example: "01826232498871-001@abcdefghij:001" timestamp: type: number format: unix-timestamp description: The timestamp when this version was created. example: 1741973127428 clientId: type: string description: TThe client identifier of the user that created this version of the message. Only set for message.update and message.delete actions. example: "user123" description: type: string description: Optional description provided by the client that created this message version. Only set for message.update and message.delete actions. example: "Message updated by client" metadata: type: object description: Optional description provided by the client that created this message version. Only set for message.update and message.delete actions. example: { } reactions: type: object description: Represents a summary of all reactions on a message $ref: '#/components/schemas/MessageReactions' MessageReactions: type: object description: Represents a summary of all reactions on a message properties: unique: type: object description: Summary of all reactions of type `unique` on a message additionalProperties: $ref: '#/components/schemas/SummaryClientIdList' distinct: type: object description: Summary of all reactions of type `distinct` on a message additionalProperties: $ref: '#/components/schemas/SummaryClientIdList' multiple: type: object description: Summary of all reactions of type `multiple` on a message additionalProperties: $ref: '#/components/schemas/SummaryClientIdCounts' SummaryClientIdList: type: object description: The summary entry for aggregated reactions for unique and distinct reactions. properties: total: type: integer description: The total number of clients who have published a reaction with this name (or type, depending on context). clientIds: type: array items: type: string description: A list of the clientIds of all clients who have published a reaction with this name (or type, depending on context). clipped: type: boolean description: Whether the list of clientIds has been clipped due to exceeding the maximum size. SummaryClientIdCounts: type: object description: The per-name value for the multiple reactions. properties: total: type: integer description: The sum of the counts from all clients who have published a reaction with this name. clientIds: type: object additionalProperties: type: integer description: A list of the clientIds of all clients who have published a reaction with this name, and the count each of them have contributed. totalUnidentified: type: integer description: The sum of the counts from all unidentified clients who have published a reaction with this name, and so who are not included in the clientIds list. clipped: type: boolean description: Whether the list of clientIds has been clipped due to exceeding the maximum size. totalClientIds: type: integer description: The total number of unique clientIds in the map (equal to length of map if clipped is false). parameters: ClientIdParam: name: clientId in: query required: false description: Optional client ID. If provided, this must match the client ID used to authenticate the request. schema: type: string example: "some-client-id" AuthorizationHeader: name: Authorization in: header required: true description: A valid authentication token for accessing the requested resource. This can also be a base64 encoded API key when using basic authentication. schema: type: string example: "Bearer eyJhbGc..." ClientIdHeader: name: X-Ably-ClientId in: header required: false description: Optional client ID. If provided, this must match the client ID used to authenticate the request. schema: type: string example: "some-client-id" AcceptHeader: name: Accept in: header required: false description: | The content type the client is willing to accept in the response. Supported values are `application/json` and `application/x-msgpack`. schema: type: string enum: - application/json - application/x-msgpack example: "application/json" default: "application/json" paths: /chat/{version}/rooms/{roomName}/messages: post: summary: Send a message to a room description: | Sends a new message to a specified room. A successful request returns a response with the serial and creation timestamp of the newly sent message. This will also mean the message has been broadcast to all subscribing members of the room. tags: - rooms parameters: - name: version in: path required: true description: The version of the Chat API endpoint to use. schema: type: string example: v4 - name: roomName in: path required: true description: The unique identifier of the room to send the message to. The `roomName` must be URI-encoded. schema: type: string - $ref: '#/components/parameters/ClientIdHeader' - $ref: '#/components/parameters/AuthorizationHeader' - $ref: '#/components/parameters/AcceptHeader' - $ref: '#/components/parameters/ClientIdParam' requestBody: description: The message content and optional properties to send to the specified room. required: true content: application/json: schema: type: object properties: text: type: string description: | The main content of the message. This property is required. Empty strings will result in an error. example: "Hello World!" headers: type: object description: | Optional headers for adding additional information to a message, such as the relative timestamp of a livestream video, or flagging a message as important. Do not use the headers for authoritative information. Treat them like user input. example: liveStreamTime: "0:15:34.450" priority: "high" metadata: type: object description: | Optional metadata associated with the message. This can include animations, effects, or links, amongst others. This information is not read or processed by the server. Treat it like user input. example: animation: "wave_effect" imageUrl: "https://example.com/image.jpg" required: - text responses: '200': description: | Successfully sent the message to the room. content: application/json: schema: $ref: '#/components/schemas/Message' '400': description: Invalid request body. content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' '401': description: Unauthorized access. content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: error: message: "Unauthorized access." code: 40005 statusCode: 401 href: "https://help.ably.io/error/40101" '422': description: Moderation error. content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: error: message: "Message contains inappropriate language." code: 42201 statusCode: 422 href: "https://help.ably.io/error/42201" '500': description: Server error. content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: error: message: "Internal server error." code: 50001 statusCode: 500 href: "https://help.ably.io/error/50001" get: summary: Retrieve messages from a room description: | Fetches a list of messages from a specified room. The messages are returned in a paginated format with links to navigate through other pages. To query specific messages or control the set of messages returned, use the query parameters provided. tags: - rooms parameters: - name: version in: path required: true description: The version of the Chat API endpoint to use. schema: type: string example: v3 - name: roomName in: path required: true description: The unique identifier of the room to fetch messages from. The `roomName` must be URI-encoded. schema: type: string - name: limit in: query required: false description: The maximum number of messages to retrieve per request. schema: type: integer example: 50 - name: fromSerial in: query required: false description: The serial value to start fetching messages from, this must be URI encoded. If omitted, messages are retrieved from the beginning or end depending on the `orderBy` parameter. schema: type: string example: 01741966242815-000@cbf5P0_1gBmlrl25663776:000 - name: orderBy in: query required: false description: | The order of messages in the response, based on the order of creation. schema: type: string enum: [ oldestFirst, newestFirst ] default: newestFirst - $ref: '#/components/parameters/ClientIdHeader' - $ref: '#/components/parameters/AuthorizationHeader' - $ref: '#/components/parameters/AcceptHeader' - $ref: '#/components/parameters/ClientIdParam' responses: '200': description: A paginated list of messages retrieved from the room. headers: Link: description: If the response contains multiple pages, links shall be provided to navigate through the pages using the Link header. rel values used are `current`, `next`, and `first`. schema: type: string example: '<./messages?direction=backwards&limit=100>; rel="current", <./messages?cursor=01741782820772-000%40cbf5P0_1gBmlrl73660839%3A000&direction=backwards&limit=100>; rel="next", <./messages?direction=backwards&limit=100>; rel="first"' content: application/json: schema: type: array description: A list of retrieved messages. Each message contains the following fields items: $ref: '#/components/schemas/Message' '400': description: Invalid query parameters content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' '401': description: Unauthorized access. content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: error: message: "Unauthorized access." code: 40005 statusCode: 401 href: "https://help.ably.io/error/40101" '500': description: Server error. content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: error: message: "Internal server error." code: 50001 statusCode: 500 href: "https://help.ably.io/error/50001" /chat/{version}/rooms/{roomName}/occupancy: get: summary: Retrieve occupancy of a room description: | Fetches the occupancy metrics of a specified room. A successful request returns the number of active connections and presence members. tags: - rooms parameters: - name: version in: path required: true description: The version of the Chat API endpoint to use. schema: type: string example: v3 - name: roomName in: path required: true description: | The unique identifier of the room to retrieve occupancy information from. The `roomName` must be URI-encoded. schema: type: string - $ref: '#/components/parameters/ClientIdHeader' - $ref: '#/components/parameters/AuthorizationHeader' - $ref: '#/components/parameters/AcceptHeader' - $ref: '#/components/parameters/ClientIdParam' responses: '200': description: | Successfully retrieved the occupancy metrics. content: application/json: schema: type: object properties: connections: type: integer description: The number of active connections in the room. example: 103 presenceMembers: type: integer description: The number of presence members in the room. example: 95 '400': description: Invalid query parameters. content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' '401': description: Unauthorized access. content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: error: message: "Unauthorized access." code: 40005 statusCode: 401 href: "https://help.ably.io/error/40101" '500': description: Server error. content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: error: message: "Internal server error." code: 50001 statusCode: 500 href: "https://help.ably.io/error/50001" /chat/{version}/rooms/{roomName}/messages/{serial}: get: summary: Retrieve a single message from a room description: | Fetches a single message from a specified room. tags: - rooms parameters: - name: version in: path required: true description: The version of the Chat API endpoint to use. schema: type: string example: v3 - name: roomName in: path required: true description: The unique identifier of the room to fetch messages from. The `roomName` must be URI-encoded. schema: type: string - name: serial in: path required: true description: The unique identifier of the message to fetch. The `serial` must be URI-encoded. schema: type: string example: "01826232498871-001@abcdefghij:001" - $ref: '#/components/parameters/ClientIdHeader' - $ref: '#/components/parameters/AuthorizationHeader' - $ref: '#/components/parameters/AcceptHeader' - $ref: '#/components/parameters/ClientIdParam' responses: '200': description: A single message retrieved from the room. content: application/json: schema: $ref: '#/components/schemas/Message' '400': description: Invalid request. content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' '401': description: Unauthorized access. content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: error: message: "Unauthorized access." code: 40005 statusCode: 401 href: "https://help.ably.io/error/40101" '404': description: Message not found. content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: error: message: "Message not found." code: 40400 statusCode: 404 href: "https://help.ably.io/error/40401" '500': description: Server error. content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: error: message: "Internal server error." code: 50001 statusCode: 500 href: "https://help.ably.io/error/50001" put: summary: Update a message in a room description: | Updates an existing message in a specified room. **Important:** Omitting either the `headers` or `metadata` fields will result in removal of any existing values for those fields in the message. To retain original `headers` or `metadata`, you must include them explicitly in the update request. A successful request returns the updated message's `version` and the `timestamp` when the update occurred. This will broadcast the updated message to all subscribing members of the room. tags: - rooms parameters: - name: version in: path required: true description: The version of the Chat API endpoint to use. schema: type: string example: v3 - name: roomName in: path required: true description: | The unique identifier of the room that contains the message to be updated. The `roomName` must be URI-encoded. schema: type: string - name: serial in: path required: true description: | The unique identifier of the message you wish to update. The `serial` must be URI-encoded. schema: type: string example: "01926232498871-001@abcdefghij:001" - $ref: '#/components/parameters/ClientIdHeader' - $ref: '#/components/parameters/AuthorizationHeader' - $ref: '#/components/parameters/AcceptHeader' - $ref: '#/components/parameters/ClientIdParam' requestBody: description: The updated message content and optional properties, along with details related to the update operation. required: true content: application/json: schema: type: object properties: message: type: object description: The new content of the message, including text, headers, and metadata. properties: text: type: string description: | The main content of the updated message. This property is required. Empty strings will result in an error. example: "Updated Text Content" headers: type: object description: | Optional headers for providing context, such as the relative timestamp of a livestream or special tags for the message. If not included, existing headers will be removed. example: liveStreamTime: "0:20:15.100" priority: "medium" metadata: type: object description: | Optional metadata such as animations, effects, or links to other resources associated with the message. If not included, existing metadata will be removed. example: animation: "highlight_effect" imageUrl: "https://example.com/updated-image.jpg" required: - text description: type: string description: | Optional description for the action. This provides context about the update operation. example: "Message updated by user" metadata: type: object description: | Optional metadata specific to the action. This does not modify the metadata of the message itself. example: editedBy: "user-12345" reason: "Corrected typo" responses: '201': description: | Successfully updated the message. content: application/json: schema: $ref: '#/components/schemas/Message' '400': description: Invalid request body. content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' '401': description: Unauthorized access. content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: error: message: "Unauthorized access." code: 40005 statusCode: 401 href: "https://help.ably.io/error/40101" '404': description: Message not found. content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: error: message: "Message not found." code: 40400 statusCode: 404 href: "https://help.ably.io/error/40401" '500': description: Server error. content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: error: message: "Internal server error." code: 50001 statusCode: 500 href: "https://help.ably.io/error/50001" /chat/{version}/rooms/{roomName}/messages/{serial}/delete: post: summary: Delete a message in a room description: | Deletes a specific message in a room. A successful request returns the `version` and `timestamp` of the deleted message. This will also broadcast the deletion to all subscribing members of the room. tags: - rooms parameters: - name: version in: path required: true description: The version of the Chat API endpoint to use. schema: type: string example: v3 - name: roomName in: path required: true description: | The unique identifier of the room containing the message you wish to delete. The `roomName` should be URI-encoded. schema: type: string - name: serial in: path required: true description: | The unique identifier of the message you wish to delete. The `serial` must be URI-encoded. schema: type: string example: "01826232498871-001@abcdefghij:001" - $ref: '#/components/parameters/ClientIdHeader' - $ref: '#/components/parameters/AuthorizationHeader' - $ref: '#/components/parameters/AcceptHeader' - $ref: '#/components/parameters/ClientIdParam' requestBody: description: | Optional body containing additional information about the deletion action, such as a description and metadata. required: false content: application/json: schema: type: object properties: description: type: string description: | Optional description providing context for the operation, such as the reason for deleting the message. example: "Message deleted by user" metadata: type: object description: | Optional metadata associated with the delete operation. This does not affect the metadata of the message or room. example: deletedBy: "user-12345" flaggedAs: "inappropriate" responses: '200': description: | Successfully deleted the message. content: application/json: schema: $ref: '#/components/schemas/Message' '400': description: Invalid request body or missing required fields. content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' '401': description: Unauthorized access. content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: error: message: "Unauthorized access." code: 40005 statusCode: 401 href: "https://help.ably.io/error/40101" '404': description: Message not found. content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: error: message: "Message not found." code: 40400 statusCode: 404 href: "https://help.ably.io/error/40401" '500': description: Server error. content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: error: message: "Internal server error." code: 50001 statusCode: 500 href: "https://help.ably.io/error/50001" /chat/{version}/rooms/{roomName}/messages/{serial}/reactions: post: summary: Send a reaction to a message description: | Sends a reaction to a specified message in a room. A successful request returns the serial identifier of the newly sent reaction. This will also broadcast the reaction to all subscribing members of the room. tags: - rooms parameters: - name: version in: path required: true description: The version of the Chat API endpoint to use. schema: type: string example: v3 - name: roomName in: path required: true description: | The unique identifier of the room containing the message you wish to send a reaction to. The `roomName` must be URI-encoded. schema: type: string - name: serial in: path required: true description: | The unique identifier of the message you wish to send a reaction to. The `serial` must be URI-encoded. schema: type: string example: "01826232498871-001@abcdefghij:001" - $ref: '#/components/parameters/ClientIdHeader' - $ref: '#/components/parameters/AuthorizationHeader' - $ref: '#/components/parameters/AcceptHeader' - $ref: '#/components/parameters/ClientIdParam' requestBody: description: The reaction details to send to the specified message. required: true content: application/json: schema: type: object properties: type: type: string description: | The type of reaction. Must be one of the supported reaction types: - `unique`: Each user can have only one reaction of this type with a specific name (WhatsApp, iMessage style). - `distinct`: Each user can have only one reaction of each name (Slack style). - `multiple`: Users can have multiple reactions with counts (Medium style). example: "unique" enum: - "unique" - "distinct" - "multiple" name: type: string description: | The name of the reaction, such as an emoji or reaction identifier. Must not be empty. example: "like" count: type: integer description: | The count for the reaction. Only applicable for `multiple` type. For other types, this field is ignored and should not be provided. minimum: 1 example: 1 default: 1 required: - type - name responses: '201': description: | Successfully sent the reaction to the message. content: application/json: schema: type: object properties: serial: type: string description: The unique identifier for the reaction. example: "01826232498871-001@abcdefghij:001" '400': description: Invalid request body or parameters. content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' '401': description: Unauthorized access. content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: error: message: "Unauthorized access." code: 40005 statusCode: 401 href: "https://help.ably.io/error/40101" '404': description: Message not found. content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: error: message: "Message not found." code: 40400 statusCode: 404 href: "https://help.ably.io/error/40401" '500': description: Server error. content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: error: message: "Internal server error." code: 50001 statusCode: 500 href: "https://help.ably.io/error/50001" delete: summary: Delete a reaction from a message description: | Removes a specific reaction from a message in a room. A successful request returns the serial identifier of the deleted reaction. This will also broadcast the deletion to all subscribing members of the room. tags: - rooms parameters: - name: version in: path required: true description: The version of the Chat API endpoint to use. schema: type: string example: v3 - name: roomName in: path required: true description: | The unique identifier of the room containing the message with the reaction you wish to delete. The `roomName` must be URI-encoded. schema: type: string - name: serial in: path required: true description: | The unique identifier of the message containing the reaction you wish to delete. The `serial` must be URI-encoded. schema: type: string example: "01826232498871-001@abcdefghij:001" - name: type in: query required: true description: | The type of reaction to delete. Must match one of the supported reaction types. schema: type: string example: "unique" enum: - "unique" - "distinct" - "multiple" - name: name in: query required: true description: | The name of the reaction to delete. Required for all reaction types except `unique`. schema: type: string example: "like" - $ref: '#/components/parameters/ClientIdHeader' - $ref: '#/components/parameters/AuthorizationHeader' - $ref: '#/components/parameters/AcceptHeader' - $ref: '#/components/parameters/ClientIdParam' responses: '200': description: | Successfully deleted the reaction from the message. content: application/json: schema: type: object properties: serial: type: string description: The unique identifier for the delete annotation. example: "01826232498871-001@abcdefghij:001" '400': description: Invalid request parameters. content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' '401': description: Unauthorized access. content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: error: message: "Unauthorized access." code: 40005 statusCode: 401 href: "https://help.ably.io/error/40101" '404': description: Message or reaction not found. content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: error: message: "Message not found." code: 40400 statusCode: 404 href: "https://help.ably.io/error/40401" '500': description: Server error. content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: error: message: "Internal server error." code: 50001 statusCode: 500 href: "https://help.ably.io/error/50001" /chat/{version}/rooms/{roomName}/messages/{serial}/client-reactions: get: summary: Get reactions summary for a specific client description: | Gets the reactions summary for a specific client ID. A successful request returns a clipped message reactions summary for the specific client ID. The list of client IDs on all reaction types will be clipped to only include the requested user. tags: - rooms parameters: - name: version in: path required: true description: The version of the Chat API endpoint to use. schema: type: string example: v3 - name: roomName in: path required: true description: | The unique identifier of the room containing the message with the reaction you wish to delete. The `roomName` must be URI-encoded. schema: type: string - name: serial in: path required: true description: | The unique identifier of the message containing the reaction you wish to delete. The `serial` must be URI-encoded. schema: type: string example: "01826232498871-001@abcdefghij:001" - name: forClientId in: query required: false description: | If requesting data for a client ID other than the authenticated one, provide the required client ID in this parameter. schema: type: string example: "like" - $ref: '#/components/parameters/ClientIdHeader' - $ref: '#/components/parameters/AuthorizationHeader' - $ref: '#/components/parameters/AcceptHeader' - $ref: '#/components/parameters/ClientIdParam' responses: '200': description: | Successfully fetched the client reactions summary: the summary returned is clipped to only include the requested (or current) client ID. content: application/json: schema: $ref: '#/components/schemas/MessageReactions' '400': description: Invalid request parameters. content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' '401': description: Unauthorized access. content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: error: message: "Unauthorized access." code: 40005 statusCode: 401 href: "https://help.ably.io/error/40101" '404': description: Message or reaction not found. content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: error: message: "Message not found." code: 40400 statusCode: 404 href: "https://help.ably.io/error/40401" '500': description: Server error. content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: error: message: "Internal server error." code: 50001 statusCode: 500 href: "https://help.ably.io/error/50001"