Home
Mastodon
Mastodon Streaming and Web Push API
Mastodon Streaming and Web Push API
Version 1.0.0
AsyncAPI 2.6 description of the Mastodon real-time surface. Mastodon exposes two complementary asynchronous interfaces: * Streaming API - delivers timeline and notification events to a connected client over either a multiplexed WebSocket connection (`wss:///api/v1/streaming`) or one of several Server-Sent Events (SSE) endpoints under `/api/v1/streaming/...`. * Web Push - delivers notification events to an external push endpoint registered by the client. Mastodon implements the W3C / IETF Web Push standard (RFC 8030 for the protocol, RFC 8291 for message encryption, and RFC 8292 / VAPID for voluntary application server identification). Both surfaces emit the same event "shapes" (e.g. a notification, a new status, a deletion) but the transport, framing, subscription model and authentication differ. This document models each transport as one or more AsyncAPI channels. Sources: * https://docs.joinmastodon.org/methods/streaming/ * https://docs.joinmastodon.org/methods/push/ * https://docs.joinmastodon.org/entities/Notification/ * RFC 8030, RFC 8291, RFC 8292
Channels
/api/v1/streaming
publish sendControlMessage
Client -> server control message (subscribe / unsubscribe).
Multiplexed WebSocket entry point. After connecting, the client either passed `?stream=` (and any required `tag`/`list`) on the upgrade request, or sends one or more JSON `subscribe` control frames to attach to streams. The server emits framed JSON messages identifying which stream produced each event.
/api/v1/streaming/health
subscribe streamingHealth
Streaming server health probe.
Liveness check. Returns `OK` (plain text) when the streaming server is up.
/api/v1/streaming/user
subscribe streamUser
SSE stream of home timeline and notification events.
Home timeline plus notifications for the authenticated user. Requires the `read:statuses` and `read:notifications` scopes.
/api/v1/streaming/user/notification
subscribe streamUserNotification
SSE stream of notification events only.
Notification-only sub-stream for the authenticated user. Requires `read:notifications`.
/api/v1/streaming/public
subscribe streamPublic
SSE stream of the federated public timeline.
Federated (whole-known-network) public timeline.
/api/v1/streaming/public/local
subscribe streamPublicLocal
SSE stream of the local public timeline.
Local (this-instance-only) public timeline.
/api/v1/streaming/public/remote
subscribe streamPublicRemote
SSE stream of remote-only public timeline.
Federated public timeline excluding local posts.
/api/v1/streaming/hashtag
subscribe streamHashtag
SSE stream of statuses tagged with a hashtag (federated).
Federated stream of statuses bearing a given hashtag.
/api/v1/streaming/hashtag/local
subscribe streamHashtagLocal
SSE stream of locally-posted statuses tagged with a hashtag.
Local-instance stream of statuses bearing a given hashtag.
/api/v1/streaming/list
subscribe streamList
SSE stream of statuses from a list.
Stream of statuses from a user-curated list.
/api/v1/streaming/direct
subscribe streamDirect
SSE stream of direct-message conversation events.
Stream of direct-message conversations involving the authenticated user. Emits `conversation` events with the updated Conversation entity (containing the latest status).
webpush/{endpoint}
publish deliverWebPush
Encrypted Web Push notification delivered to the registered endpoint.
Outbound Web Push delivery from Mastodon to the push service URL that the client previously registered via `POST /api/v1/push/subscription`. Mastodon POSTs an `aes128gcm` encrypted body containing a notification payload, signed with the instance's VAPID key pair (RFC 8292). Decryption requires the `p256dh` and `auth` keys the client supplied at subscription time (RFC 8291). After decryption the plaintext body is a JSON object describing the notification.
Messages
✉
SubscribeControl
Subscribe control frame
Client asks the server to start delivering events for a stream.
✉
UnsubscribeControl
Unsubscribe control frame
Client asks the server to stop delivering events for a stream.
✉
WsStreamFrame
Multiplexed stream frame
Wrapped event delivered over the multiplexed WebSocket.
✉
WsErrorFrame
WebSocket error frame
Server-side error reported over the WebSocket.
✉
UpdateEvent
New status received
A new status (post) has appeared in the subscribed timeline.
✉
DeleteEvent
Status deleted
A status was deleted; payload is the deleted status ID as a string.
✉
NotificationEvent
Notification received
A notification (mention, follow, favourite, etc.) was created.
✉
StatusUpdateEvent
Status edited
A previously-seen status has been edited.
✉
ConversationEvent
Direct-message conversation updated
A direct-message conversation has a new or updated last status.
✉
FiltersChangedEvent
User filters changed
Notification that the user's keyword filters were modified; no payload.
✉
AnnouncementEvent
New announcement published
An administrator published a server-wide announcement.
✉
AnnouncementReactionEvent
Reaction added to an announcement
A user reacted with an emoji to a server announcement.
✉
AnnouncementDeleteEvent
Announcement deleted
A server announcement was removed; payload is its ID as a string.
✉
NotificationsMergedEvent
Grouped notifications updated
Server signals that previously delivered notifications have been grouped/merged. Clients that ignore grouping can ignore this.
✉
WebPushNotification
Encrypted Web Push notification body
Outbound RFC 8030 push message body (encrypted with aes128gcm per RFC 8291). The plaintext, after decryption with the subscription's `p256dh`/`auth` keys, is a JSON object describing the notification.
Servers
wss
websocket
{instance}/api/v1/streaming
Mastodon multiplexed WebSocket streaming endpoint. A single connection can subscribe to multiple streams using `subscribe` control messages, or be locked to a single stream by supplying the `stream` query parameter on connect.
https
sse
{instance}/api/v1/streaming
Mastodon Server-Sent Events base URL. Specific streams are exposed as sub-paths (e.g. `/user`, `/public`, `/hashtag`). Responses use `Content-Type: text/event-stream` and follow the SSE wire format.
https
webpush
{pushService}
External Web Push service (e.g. Mozilla autopush, Google FCM Web Push endpoint, Apple Web Push, or self-hosted). Mastodon acts as the application server and POSTs encrypted push messages to the `endpoint` URL provided by the client at subscription time, per RFC 8030. This server entry represents that outbound delivery channel from Mastodon's perspective.
AsyncAPI Specification
asyncapi: 2.6.0
info:
title: Mastodon Streaming and Web Push API
version: 1.0.0
description: |
AsyncAPI 2.6 description of the Mastodon real-time surface.
Mastodon exposes two complementary asynchronous interfaces:
* Streaming API - delivers timeline and notification events to a
connected client over either a multiplexed WebSocket connection
(`wss://<instance>/api/v1/streaming`) or one of several Server-Sent
Events (SSE) endpoints under `/api/v1/streaming/...`.
* Web Push - delivers notification events to an external push
endpoint registered by the client. Mastodon implements the W3C /
IETF Web Push standard (RFC 8030 for the protocol, RFC 8291 for
message encryption, and RFC 8292 / VAPID for voluntary application
server identification).
Both surfaces emit the same event "shapes" (e.g. a notification, a new
status, a deletion) but the transport, framing, subscription model and
authentication differ. This document models each transport as one or
more AsyncAPI channels.
Sources:
* https://docs.joinmastodon.org/methods/streaming/
* https://docs.joinmastodon.org/methods/push/
* https://docs.joinmastodon.org/entities/Notification/
* RFC 8030, RFC 8291, RFC 8292
contact:
name: Mastodon Documentation
url: https://docs.joinmastodon.org/methods/streaming/
license:
name: AGPL-3.0
url: https://www.gnu.org/licenses/agpl-3.0.html
termsOfService: https://joinmastodon.org/
defaultContentType: application/json
servers:
websocket:
url: "{instance}/api/v1/streaming"
protocol: wss
description: |
Mastodon multiplexed WebSocket streaming endpoint. A single
connection can subscribe to multiple streams using `subscribe`
control messages, or be locked to a single stream by supplying the
`stream` query parameter on connect.
variables:
instance:
default: mastodon.social
description: Hostname of the Mastodon instance (no scheme, no path).
security:
- userToken: []
- websocketSubprotocolToken: []
- accessTokenQuery: []
sse:
url: "{instance}/api/v1/streaming"
protocol: https
description: |
Mastodon Server-Sent Events base URL. Specific streams are exposed
as sub-paths (e.g. `/user`, `/public`, `/hashtag`). Responses use
`Content-Type: text/event-stream` and follow the SSE wire format.
variables:
instance:
default: mastodon.social
description: Hostname of the Mastodon instance (no scheme, no path).
security:
- userToken: []
- accessTokenQuery: []
webpush:
url: "{pushService}"
protocol: https
description: |
External Web Push service (e.g. Mozilla autopush, Google FCM Web
Push endpoint, Apple Web Push, or self-hosted). Mastodon acts as
the application server and POSTs encrypted push messages to the
`endpoint` URL provided by the client at subscription time, per
RFC 8030. This server entry represents that outbound delivery
channel from Mastodon's perspective.
variables:
pushService:
default: updates.push.services.mozilla.com
description: Hostname of the push service operating the subscription endpoint.
security:
- vapid: []
channels:
# ---------------------------------------------------------------------------
# WebSocket - multiplexed
# ---------------------------------------------------------------------------
/api/v1/streaming:
description: |
Multiplexed WebSocket entry point. After connecting, the client
either passed `?stream=<name>` (and any required `tag`/`list`) on
the upgrade request, or sends one or more JSON `subscribe` control
frames to attach to streams. The server emits framed JSON messages
identifying which stream produced each event.
bindings:
ws:
bindingVersion: 0.1.0
query:
type: object
properties:
stream:
type: string
description: Initial stream to subscribe to on connect.
enum:
- user
- user:notification
- public
- public:local
- public:remote
- public:media
- public:local:media
- hashtag
- hashtag:local
- list
- direct
tag:
type: string
description: Hashtag name (required when `stream` is `hashtag` or `hashtag:local`).
list:
type: string
description: List ID (required when `stream` is `list`).
access_token:
type: string
description: |
User OAuth token. Legacy; prefer the `Authorization`
header or the `Sec-WebSocket-Protocol` subprotocol value.
headers:
type: object
properties:
Authorization:
type: string
description: "`Bearer <user_token>` - preferred auth method."
Sec-WebSocket-Protocol:
type: string
description: Alternate location for the user OAuth token.
publish:
operationId: sendControlMessage
summary: Client -> server control message (subscribe / unsubscribe).
description: |
Manage stream subscriptions on an open WebSocket. The server has
no acknowledgement message for these frames; subsequent matching
events will simply start (or stop) flowing.
message:
oneOf:
- $ref: '#/components/messages/SubscribeControl'
- $ref: '#/components/messages/UnsubscribeControl'
subscribe:
operationId: receiveStreamFrame
summary: Server -> client stream event frame.
description: |
Every event the server pushes is wrapped in a JSON envelope
that identifies the originating stream(s) and the event name.
The `payload` field is itself JSON-encoded as a string for
object payloads (e.g. Status, Notification), and a bare string
for ID-only events (`delete`, `announcement.delete`).
message:
oneOf:
- $ref: '#/components/messages/WsStreamFrame'
- $ref: '#/components/messages/WsErrorFrame'
# ---------------------------------------------------------------------------
# SSE channels - one per documented endpoint
# ---------------------------------------------------------------------------
/api/v1/streaming/health:
description: Liveness check. Returns `OK` (plain text) when the streaming server is up.
bindings:
http:
bindingVersion: 0.3.0
type: request
method: GET
subscribe:
operationId: streamingHealth
summary: Streaming server health probe.
message:
name: HealthResponse
contentType: text/plain
payload:
type: string
const: "OK"
/api/v1/streaming/user:
description: |
Home timeline plus notifications for the authenticated user.
Requires the `read:statuses` and `read:notifications` scopes.
bindings:
http:
bindingVersion: 0.3.0
type: request
method: GET
subscribe:
operationId: streamUser
summary: SSE stream of home timeline and notification events.
message:
oneOf:
- $ref: '#/components/messages/UpdateEvent'
- $ref: '#/components/messages/DeleteEvent'
- $ref: '#/components/messages/NotificationEvent'
- $ref: '#/components/messages/StatusUpdateEvent'
- $ref: '#/components/messages/ConversationEvent'
- $ref: '#/components/messages/FiltersChangedEvent'
- $ref: '#/components/messages/AnnouncementEvent'
- $ref: '#/components/messages/AnnouncementReactionEvent'
- $ref: '#/components/messages/AnnouncementDeleteEvent'
- $ref: '#/components/messages/NotificationsMergedEvent'
/api/v1/streaming/user/notification:
description: |
Notification-only sub-stream for the authenticated user.
Requires `read:notifications`.
bindings:
http:
bindingVersion: 0.3.0
type: request
method: GET
subscribe:
operationId: streamUserNotification
summary: SSE stream of notification events only.
message:
oneOf:
- $ref: '#/components/messages/NotificationEvent'
- $ref: '#/components/messages/NotificationsMergedEvent'
/api/v1/streaming/public:
description: Federated (whole-known-network) public timeline.
parameters:
only_media:
description: When `true`, restrict to statuses with media attachments.
schema:
type: boolean
bindings:
http:
bindingVersion: 0.3.0
type: request
method: GET
subscribe:
operationId: streamPublic
summary: SSE stream of the federated public timeline.
message:
oneOf:
- $ref: '#/components/messages/UpdateEvent'
- $ref: '#/components/messages/DeleteEvent'
- $ref: '#/components/messages/StatusUpdateEvent'
/api/v1/streaming/public/local:
description: Local (this-instance-only) public timeline.
parameters:
only_media:
description: When `true`, restrict to statuses with media attachments.
schema:
type: boolean
bindings:
http:
bindingVersion: 0.3.0
type: request
method: GET
subscribe:
operationId: streamPublicLocal
summary: SSE stream of the local public timeline.
message:
oneOf:
- $ref: '#/components/messages/UpdateEvent'
- $ref: '#/components/messages/DeleteEvent'
- $ref: '#/components/messages/StatusUpdateEvent'
/api/v1/streaming/public/remote:
description: Federated public timeline excluding local posts.
parameters:
only_media:
description: When `true`, restrict to statuses with media attachments.
schema:
type: boolean
bindings:
http:
bindingVersion: 0.3.0
type: request
method: GET
subscribe:
operationId: streamPublicRemote
summary: SSE stream of remote-only public timeline.
message:
oneOf:
- $ref: '#/components/messages/UpdateEvent'
- $ref: '#/components/messages/DeleteEvent'
- $ref: '#/components/messages/StatusUpdateEvent'
/api/v1/streaming/hashtag:
description: Federated stream of statuses bearing a given hashtag.
parameters:
tag:
description: Hashtag name (without the leading `#`). Required.
schema:
type: string
bindings:
http:
bindingVersion: 0.3.0
type: request
method: GET
subscribe:
operationId: streamHashtag
summary: SSE stream of statuses tagged with a hashtag (federated).
message:
oneOf:
- $ref: '#/components/messages/UpdateEvent'
- $ref: '#/components/messages/DeleteEvent'
- $ref: '#/components/messages/StatusUpdateEvent'
/api/v1/streaming/hashtag/local:
description: Local-instance stream of statuses bearing a given hashtag.
parameters:
tag:
description: Hashtag name (without the leading `#`). Required.
schema:
type: string
bindings:
http:
bindingVersion: 0.3.0
type: request
method: GET
subscribe:
operationId: streamHashtagLocal
summary: SSE stream of locally-posted statuses tagged with a hashtag.
message:
oneOf:
- $ref: '#/components/messages/UpdateEvent'
- $ref: '#/components/messages/DeleteEvent'
- $ref: '#/components/messages/StatusUpdateEvent'
/api/v1/streaming/list:
description: Stream of statuses from a user-curated list.
parameters:
list:
description: List ID. Required.
schema:
type: string
bindings:
http:
bindingVersion: 0.3.0
type: request
method: GET
subscribe:
operationId: streamList
summary: SSE stream of statuses from a list.
message:
oneOf:
- $ref: '#/components/messages/UpdateEvent'
- $ref: '#/components/messages/DeleteEvent'
- $ref: '#/components/messages/StatusUpdateEvent'
/api/v1/streaming/direct:
description: |
Stream of direct-message conversations involving the authenticated
user. Emits `conversation` events with the updated Conversation
entity (containing the latest status).
bindings:
http:
bindingVersion: 0.3.0
type: request
method: GET
subscribe:
operationId: streamDirect
summary: SSE stream of direct-message conversation events.
message:
oneOf:
- $ref: '#/components/messages/ConversationEvent'
# ---------------------------------------------------------------------------
# Web Push - outbound from Mastodon to a registered push endpoint
# ---------------------------------------------------------------------------
webpush/{endpoint}:
description: |
Outbound Web Push delivery from Mastodon to the push service URL
that the client previously registered via
`POST /api/v1/push/subscription`. Mastodon POSTs an `aes128gcm`
encrypted body containing a notification payload, signed with the
instance's VAPID key pair (RFC 8292).
Decryption requires the `p256dh` and `auth` keys the client
supplied at subscription time (RFC 8291). After decryption the
plaintext body is a JSON object describing the notification.
parameters:
endpoint:
description: |
Opaque path component of the push service endpoint URL the
client registered. Treated as an opaque identifier by Mastodon.
schema:
type: string
bindings:
http:
bindingVersion: 0.3.0
type: request
method: POST
headers:
type: object
properties:
TTL:
type: integer
description: RFC 8030 message lifetime in seconds.
Urgency:
type: string
enum: [very-low, low, normal, high]
description: RFC 8030 delivery urgency hint.
Topic:
type: string
description: RFC 8030 topic for coalescing replaceable messages.
Content-Encoding:
type: string
const: aes128gcm
description: RFC 8188 / RFC 8291 message encryption scheme.
Authorization:
type: string
description: VAPID `vapid t=<JWT>, k=<public key>` credential (RFC 8292).
publish:
operationId: deliverWebPush
summary: Encrypted Web Push notification delivered to the registered endpoint.
message:
$ref: '#/components/messages/WebPushNotification'
components:
securitySchemes:
userToken:
type: oauth2
description: |
OAuth 2 user token passed as `Authorization: Bearer <token>`.
Required scopes depend on the stream (`read:statuses`,
`read:notifications`). As of Mastodon 4.2.0, user tokens are
required for streaming; public/app tokens were removed.
flows:
authorizationCode:
authorizationUrl: https://mastodon.social/oauth/authorize
tokenUrl: https://mastodon.social/oauth/token
scopes:
"read:statuses": Read timeline statuses.
"read:notifications": Read notifications.
"push": Manage Web Push subscriptions.
websocketSubprotocolToken:
type: httpApiKey
description: |
OAuth user token supplied via `Sec-WebSocket-Protocol` on the
WebSocket upgrade. Browser-friendly alternative to an
`Authorization` header.
name: Sec-WebSocket-Protocol
in: header
accessTokenQuery:
type: httpApiKey
description: |
Legacy: OAuth user token passed as the `access_token` query
parameter. Not recommended for new integrations.
name: access_token
in: query
vapid:
type: httpApiKey
description: |
VAPID (RFC 8292) credential the Mastodon application server
presents to the push service. Sent in the `Authorization`
header as `vapid t=<signed JWT>, k=<base64url public key>`.
name: Authorization
in: header
# ---------------------------------------------------------------------------
# Messages
# ---------------------------------------------------------------------------
messages:
# WebSocket control frames (client -> server)
SubscribeControl:
name: SubscribeControl
title: Subscribe control frame
summary: Client asks the server to start delivering events for a stream.
contentType: application/json
payload:
$ref: '#/components/schemas/SubscribeControl'
UnsubscribeControl:
name: UnsubscribeControl
title: Unsubscribe control frame
summary: Client asks the server to stop delivering events for a stream.
contentType: application/json
payload:
$ref: '#/components/schemas/UnsubscribeControl'
# WebSocket envelope (server -> client)
WsStreamFrame:
name: WsStreamFrame
title: Multiplexed stream frame
summary: Wrapped event delivered over the multiplexed WebSocket.
contentType: application/json
payload:
$ref: '#/components/schemas/WsStreamFrame'
WsErrorFrame:
name: WsErrorFrame
title: WebSocket error frame
summary: Server-side error reported over the WebSocket.
contentType: application/json
payload:
$ref: '#/components/schemas/WsErrorFrame'
# SSE events - each carries an `event:` name and a `data:` payload
UpdateEvent:
name: update
title: New status received
summary: A new status (post) has appeared in the subscribed timeline.
contentType: application/json
headers:
type: object
properties:
event:
type: string
const: update
payload:
$ref: '#/components/schemas/Status'
DeleteEvent:
name: delete
title: Status deleted
summary: A status was deleted; payload is the deleted status ID as a string.
contentType: text/plain
headers:
type: object
properties:
event:
type: string
const: delete
payload:
type: string
description: ID of the deleted status.
NotificationEvent:
name: notification
title: Notification received
summary: A notification (mention, follow, favourite, etc.) was created.
contentType: application/json
headers:
type: object
properties:
event:
type: string
const: notification
payload:
$ref: '#/components/schemas/Notification'
StatusUpdateEvent:
name: status.update
title: Status edited
summary: A previously-seen status has been edited.
contentType: application/json
headers:
type: object
properties:
event:
type: string
const: status.update
payload:
$ref: '#/components/schemas/Status'
ConversationEvent:
name: conversation
title: Direct-message conversation updated
summary: A direct-message conversation has a new or updated last status.
contentType: application/json
headers:
type: object
properties:
event:
type: string
const: conversation
payload:
$ref: '#/components/schemas/Conversation'
FiltersChangedEvent:
name: filters_changed
title: User filters changed
summary: Notification that the user's keyword filters were modified; no payload.
contentType: application/json
headers:
type: object
properties:
event:
type: string
const: filters_changed
payload:
type: "null"
AnnouncementEvent:
name: announcement
title: New announcement published
summary: An administrator published a server-wide announcement.
contentType: application/json
headers:
type: object
properties:
event:
type: string
const: announcement
payload:
$ref: '#/components/schemas/Announcement'
AnnouncementReactionEvent:
name: announcement.reaction
title: Reaction added to an announcement
summary: A user reacted with an emoji to a server announcement.
contentType: application/json
headers:
type: object
properties:
event:
type: string
const: announcement.reaction
payload:
$ref: '#/components/schemas/AnnouncementReactionPayload'
AnnouncementDeleteEvent:
name: announcement.delete
title: Announcement deleted
summary: A server announcement was removed; payload is its ID as a string.
contentType: text/plain
headers:
type: object
properties:
event:
type: string
const: announcement.delete
payload:
type: string
description: ID of the deleted announcement.
NotificationsMergedEvent:
name: notifications_merged
title: Grouped notifications updated
summary: |
Server signals that previously delivered notifications have been
grouped/merged. Clients that ignore grouping can ignore this.
contentType: application/json
headers:
type: object
properties:
event:
type: string
const: notifications_merged
payload:
type: "null"
# Web Push
WebPushNotification:
name: WebPushNotification
title: Encrypted Web Push notification body
summary: |
Outbound RFC 8030 push message body (encrypted with aes128gcm
per RFC 8291). The plaintext, after decryption with the
subscription's `p256dh`/`auth` keys, is a JSON object describing
the notification.
contentType: application/octet-stream
headers:
type: object
properties:
Content-Encoding:
type: string
const: aes128gcm
TTL:
type: integer
Urgency:
type: string
enum: [very-low, low, normal, high]
Topic:
type: string
payload:
$ref: '#/components/schemas/WebPushPlaintext'
# ---------------------------------------------------------------------------
# Schemas
# ---------------------------------------------------------------------------
schemas:
SubscribeControl:
type: object
required: [type, stream]
properties:
type:
type: string
const: subscribe
stream:
$ref: '#/components/schemas/StreamName'
tag:
type: string
description: Required when `stream` is `hashtag` or `hashtag:local`.
list:
type: string
description: Required when `stream` is `list`.
UnsubscribeControl:
type: object
required: [type, stream]
properties:
type:
type: string
const: unsubscribe
stream:
$ref: '#/components/schemas/StreamName'
tag:
type: string
list:
type: string
StreamName:
type: string
enum:
- user
- user:notification
- public
- public:local
- public:remote
- public:media
- public:local:media
- hashtag
- hashtag:local
- list
- direct
WsStreamFrame:
type: object
required: [stream, event, payload]
properties:
stream:
type: array
description: |
Stream identifiers this event matched. For most streams a
single-element array (e.g. `["user"]`); for parameterised
streams the parameter is included (e.g. `["hashtag","foo"]`,
`["list","12345"]`).
items:
type: string
minItems: 1
event:
type: string
description: Event name (same set as the SSE `event:` names).
enum:
- update
- delete
- notification
- status.update
- conversation
- filters_changed
- announcement
- announcement.reaction
- announcement.delete
- notifications_merged
payload:
description: |
JSON-encoded payload. For object events (`update`,
`notification`, `status.update`, `conversation`,
`announcement`, `announcement.reaction`) this is a string
containing JSON that must be parsed by the client. For
`delete` and `announcement.delete` it is a bare string ID.
For `filters_changed` and `notifications_merged` it may be
absent or `null`.
oneOf:
- type: string
- type: "null"
WsErrorFrame:
type: object
required: [error]
properties:
error:
type: string
status:
type: integer
# --- Mastodon entities (subset; only the fields most relevant to streaming) ---
Status:
type: object
description: |
Mastodon Status entity. See
https://docs.joinmastodon.org/entities/Status/ for the full schema.
required: [id, uri, created_at, account, content, visibility]
properties:
id:
type: string
uri:
type: string
format: uri
url:
type: string
format: uri
nullable: true
created_at:
type: string
format: date-time
edited_at:
type: string
format: date-time
nullable: true
account:
$ref: '#/components/schemas/Account'
content:
type: string
visibility:
type: string
enum: [public, unlisted, private, direct]
sensitive:
type: boolean
spoiler_text:
type: string
language:
type: string
nullable: true
in_reply_to_id:
type: string
nullable: true
in_reply_to_account_id:
type: string
nullable: true
reblog:
oneOf:
- { type: "null" }
- $ref: '#/components/schemas/Status'
media_attachments:
type: array
items:
type: object
mentions:
type: array
items:
type: object
tags:
type: array
items:
type: object
emojis:
type: array
items:
type: object
replies_count:
type: integer
reblogs_count:
type: integer
favourites_count:
type: integer
application:
type: object
nullable: true
Account:
type: object
description: |
Mastodon Account entity (subset). See
https://docs.joinmastodon.org/entities/Account/.
required: [id, username, acct, url]
properties:
id: { type: string }
username: { type: string }
acct: { type: string }
display_name: { type: string }
url: { type: string, format: uri }
avatar: { type: string, format: uri }
avatar_static: { type: string, format: uri }
header: { type: string, format: uri }
header_static: { type: string, format: uri }
locked: { type: boolean }
bot: { type: boolean }
created_at: { type: string, format: date-time }
note: { type: string }
followers_count: { type: integer }
following_count: { type: integer }
statuses_count: { type: integer }
Notification:
type: object
description: |
Mastodon Notification entity. See
https://docs.joinmastodon.org/entities/Notification/.
required: [id, type, created_at, account]
properties:
id:
type: string
type:
type: string
enum:
- mention
- status
- reblog
- follow
- follow_request
- favourite
- poll
- update
- admin.sign_up
- admin.report
- severed_relationships
- moderation_warning
- quote
- quoted_update
created_at:
type: string
format: date-time
account:
$ref: '#/components/schemas/Account'
status:
oneOf:
- { type: "null" }
- $ref: '#/components/schemas/Status'
report:
type: object
nullable: true
description: Present when `type` is `admin.report`.
Conversation:
type: object
description: |
Mastodon Conversation entity. See
https://docs.joinmastodon.org/entities/Conversation/.
required: [id, accounts, unread]
properties:
id:
type: string
accounts:
type: array
items:
$ref: '#/components/schemas/Account'
unread:
type: boolean
last_status:
oneOf:
- { type: "null" }
- $ref: '#/components/schemas/Status'
Announcement:
type: object
description: |
Mastodon Announcement entity. See
https://docs.joinmastodon.org/entities/Announcement/.
required: [id, content, published_at, all_day]
properties:
id: { type: string }
content: { type: string }
starts_at: { type: string, format: date-time, nullable: true }
ends_at: { type: string, format: date-time, nullable: true }
all_day: { type: boolean }
published_at: { type: string, format: date-time }
updated_at: { type: string, format: date-time }
read: { type: boolean }
mentions:
type: array
items:
type: object
statuses:
type: array
items:
type: object
tags:
type: array
items:
type: object
emojis:
type: array
items:
type: object
reactions:
type: array
items:
type: object
AnnouncementReactionPayload:
type: object
description: Payload for `announcement.reaction` events.
required: [name, count, announcement_id]
properties:
name:
type: string
description: Emoji shortcode or unicode character used as the reaction.
count:
type: integer
description: Updated total reaction count for that emoji.
announcement_id:
type: string
description: ID of the announcement the reaction is attached to.
WebPushPlaintext:
type: object
description: |
Plaintext JSON payload Mastodon places inside the encrypted Web
Push body. The exact shape is the Mastodon Web Push notification
payload (subject to change between server versions); the fields
below reflect the documented Mastodon implementation.
required:
- access_token
- notification_id
- notification_type
- title
- body
properties:
access_token:
type: string
description: |
The OAuth access token associated with the subscription, so
the receiving client can correlate the push to an account.
preferred_locale:
type: string
description: ISO 639 language code the user prefers.
notification_id:
type: string
description: ID of the Notification entity that triggered this push.
notification_type:
type: string
description: Notification type (same enum as `Notification.type`).
enum:
- mention
- status
- reblog
- follow
- follow_request
- favourite
- poll
- update
- admin.sign_up
# --- truncated at 32 KB (32 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/mastodon/refs/heads/main/asyncapi/mastodon-streaming.yml