Bluesky · AsyncAPI Specification

Bluesky / AT Protocol Event Streams

Version 1.1.0

AsyncAPI definition for the public event streams of the Bluesky network and the underlying AT Protocol. Three streams are documented: * **`com.atproto.sync.subscribeRepos`** - the primary repository event stream ("firehose"). Binary WebSocket frames carrying two concatenated DAG-CBOR objects (header + payload). Implemented by every PDS and Relay; the public Bluesky relay is reachable at `wss://bsky.network` (legacy) and `wss://relay1.us-east.bsky.network` (Sync 1.1, with `prevData`). * **`com.atproto.sync.subscribeLabels`** - the label / negation stream, served by moderation services. Same binary CBOR frame format as `subscribeRepos`. * **Jetstream** - a simplified JSON projection of the firehose. Plain JSON-text WebSocket frames (optionally zstd-compressed). Operated by Bluesky at `jetstream{1,2}.{us-east,us-west}.bsky.network`. Schemas are reproduced verbatim from the upstream AT Protocol lexicons (`com.atproto.sync.subscribeRepos`, `com.atproto.label.subscribeLabels`, `com.atproto.label.defs`) and the `bluesky-social/jetstream` repository.

View Spec View on GitHub At-ProtocolDecentralizedFederatedOpen-SourceSocial NetworksSocial-MediaAsyncAPIWebhooksEvents

Channels

xrpc/com.atproto.sync.subscribeRepos
subscribe subscribeRepos
Subscribe to the repository event stream (firehose).
Repository event stream, aka Firehose endpoint. Outputs repo commits with diff data, and identity update events, for all repositories on the current server. Public; no auth. Implemented by PDS and Relay. Frames are binary WebSocket messages consisting of two concatenated DAG-CBOR objects: a header (`{op, t}`) followed by a payload whose shape depends on `t`.
xrpc/com.atproto.label.subscribeLabels
subscribe subscribeLabels
Subscribe to the label/negation stream.
Subscribe to stream of labels (and negations). Public endpoint implemented by mod services. Uses the same sequencing scheme as the repository event stream and the same binary CBOR header/payload framing.
subscribe
publish jetstreamSubscriberMessage
Send a `SubscriberSourcedMessage` to update subscription options after connecting. Currently supports the `options_update` message.
Jetstream WebSocket endpoint. Emits a simplified JSON projection of the AT Protocol firehose. Each WebSocket frame is one JSON event object (optionally zstd-compressed if `compress=true` is set on the query).

Messages

RepoCommitFrame
#commit
Repository commit event.
RepoSyncFrame
#sync
Sync event - asserts current repository state without including diff data on the firehose. Used for recovery / desync resolution.
RepoIdentityFrame
#identity
Account identity change event (handle, signing key, or PDS).
RepoAccountFrame
#account
Account hosting-status change event.
RepoHandleFrame
#handle
DEPRECATED - use `#identity` instead. Legacy handle change event.
RepoMigrateFrame
#migrate
DEPRECATED - use `#account` instead. Legacy account-migration event.
RepoTombstoneFrame
#tombstone
DEPRECATED - use `#account` instead. Legacy account-tombstone event.
RepoInfoFrame
#info
Informational message (not persisted, no `seq`). Currently the only defined name value is `OutdatedCursor`.
RepoErrorFrame
error
Error frame (`op = -1`). Possible `error` values for subscribeRepos: `FutureCursor`, `ConsumerTooSlow`. The connection is closed after this frame is delivered.
LabelsFrame
#labels
A batch of labels (and/or negations).
LabelInfoFrame
#info
Informational message on the label stream.
LabelErrorFrame
error
Error frame (`op = -1`). Possible `error` values for subscribeLabels: `FutureCursor`.
JetstreamCommitCreate
commit (create)
Jetstream commit event with `commit.operation = "create"`. Contains the full record JSON.
JetstreamCommitUpdate
commit (update)
Jetstream commit event with `commit.operation = "update"`. Contains the full record JSON, replacing the previous version.
JetstreamCommitDelete
commit (delete)
Jetstream commit event with `commit.operation = "delete"`. No record body.
JetstreamIdentity
identity
Jetstream identity event. Wraps the AT Protocol `#identity` event in a Jetstream envelope.
JetstreamAccount
account
Jetstream account event. Wraps the AT Protocol `#account` event in a Jetstream envelope.
JetstreamSubscriberSourcedMessage
SubscriberSourcedMessage
JSON message sent from client to Jetstream server after connecting. Currently the only supported `type` is `options_update`.

Servers

wss
relay bsky.network
Public Bluesky Relay firehose. Hosts the binary CBOR-framed `com.atproto.sync.subscribeRepos` endpoint. Legacy endpoint; does not emit the Sync 1.1 `prevData` field.
wss
relay-sync-1-1 relay1.us-east.bsky.network
Bluesky Sync 1.1 relay. Same XRPC endpoints as `bsky.network`, but emits the inductive-firehose `prevData` field and `#sync` events.
wss
ozone mod.bsky.app
Bluesky's Ozone moderation service. Hosts the binary CBOR-framed `com.atproto.label.subscribeLabels` endpoint.
wss
jetstream2-us-east jetstream2.us-east.bsky.network
Public Jetstream instance (US-East). JSON projection of the firehose.
wss
jetstream1-us-east jetstream1.us-east.bsky.network
Public Jetstream instance (US-East).
wss
jetstream1-us-west jetstream1.us-west.bsky.network
Public Jetstream instance (US-West).
wss
jetstream2-us-west jetstream2.us-west.bsky.network
Public Jetstream instance (US-West).

AsyncAPI Specification

Raw ↑
asyncapi: '2.6.0'
info:
  title: Bluesky / AT Protocol Event Streams
  version: '1.1.0'
  description: |
    AsyncAPI definition for the public event streams of the Bluesky network and the
    underlying AT Protocol.

    Three streams are documented:

    * **`com.atproto.sync.subscribeRepos`** - the primary repository event stream
      ("firehose"). Binary WebSocket frames carrying two concatenated DAG-CBOR
      objects (header + payload). Implemented by every PDS and Relay; the public
      Bluesky relay is reachable at `wss://bsky.network` (legacy) and
      `wss://relay1.us-east.bsky.network` (Sync 1.1, with `prevData`).
    * **`com.atproto.sync.subscribeLabels`** - the label / negation stream, served
      by moderation services. Same binary CBOR frame format as `subscribeRepos`.
    * **Jetstream** - a simplified JSON projection of the firehose. Plain
      JSON-text WebSocket frames (optionally zstd-compressed). Operated by
      Bluesky at `jetstream{1,2}.{us-east,us-west}.bsky.network`.

    Schemas are reproduced verbatim from the upstream AT Protocol lexicons
    (`com.atproto.sync.subscribeRepos`, `com.atproto.label.subscribeLabels`,
    `com.atproto.label.defs`) and the `bluesky-social/jetstream` repository.
  contact:
    name: Bluesky Social PBC
    url: https://bsky.social
    email: [email protected]
  license:
    name: MIT
    url: https://github.com/bluesky-social/atproto/blob/main/LICENSE.txt
  termsOfService: https://bsky.social/about/support/tos
  x-references:
    - name: AT Protocol Event Stream specification
      url: https://atproto.com/specs/event-stream
    - name: AT Protocol Sync specification
      url: https://atproto.com/specs/sync
    - name: Bluesky Firehose advanced guide
      url: https://docs.bsky.app/docs/advanced-guides/firehose
    - name: subscribeRepos lexicon
      url: https://github.com/bluesky-social/atproto/blob/main/lexicons/com/atproto/sync/subscribeRepos.json
    - name: subscribeLabels lexicon
      url: https://github.com/bluesky-social/atproto/blob/main/lexicons/com/atproto/label/subscribeLabels.json
    - name: label defs lexicon
      url: https://github.com/bluesky-social/atproto/blob/main/lexicons/com/atproto/label/defs.json
    - name: Jetstream repository
      url: https://github.com/bluesky-social/jetstream

defaultContentType: application/cbor

servers:
  relay:
    url: bsky.network
    protocol: wss
    description: |
      Public Bluesky Relay firehose. Hosts the binary CBOR-framed
      `com.atproto.sync.subscribeRepos` endpoint. Legacy endpoint; does not
      emit the Sync 1.1 `prevData` field.
  relay-sync-1-1:
    url: relay1.us-east.bsky.network
    protocol: wss
    description: |
      Bluesky Sync 1.1 relay. Same XRPC endpoints as `bsky.network`, but emits
      the inductive-firehose `prevData` field and `#sync` events.
  ozone:
    url: mod.bsky.app
    protocol: wss
    description: |
      Bluesky's Ozone moderation service. Hosts the binary CBOR-framed
      `com.atproto.label.subscribeLabels` endpoint.
  jetstream2-us-east:
    url: jetstream2.us-east.bsky.network
    protocol: wss
    description: |
      Public Jetstream instance (US-East). JSON projection of the firehose.
  jetstream1-us-east:
    url: jetstream1.us-east.bsky.network
    protocol: wss
    description: Public Jetstream instance (US-East).
  jetstream1-us-west:
    url: jetstream1.us-west.bsky.network
    protocol: wss
    description: Public Jetstream instance (US-West).
  jetstream2-us-west:
    url: jetstream2.us-west.bsky.network
    protocol: wss
    description: Public Jetstream instance (US-West).

channels:

  #####################################################################
  # com.atproto.sync.subscribeRepos
  #####################################################################
  xrpc/com.atproto.sync.subscribeRepos:
    description: |
      Repository event stream, aka Firehose endpoint. Outputs repo commits with
      diff data, and identity update events, for all repositories on the
      current server. Public; no auth. Implemented by PDS and Relay. Frames are
      binary WebSocket messages consisting of two concatenated DAG-CBOR
      objects: a header (`{op, t}`) followed by a payload whose shape depends
      on `t`.
    servers:
      - relay
      - relay-sync-1-1
    parameters:
      cursor:
        description: The last known event seq number to backfill from.
        schema:
          type: integer
          format: int64
    bindings:
      ws:
        method: GET
        query:
          type: object
          properties:
            cursor:
              type: integer
              description: The last known event seq number to backfill from.
        bindingVersion: '0.1.0'
    subscribe:
      operationId: subscribeRepos
      summary: Subscribe to the repository event stream (firehose).
      message:
        oneOf:
          - $ref: '#/components/messages/RepoCommitFrame'
          - $ref: '#/components/messages/RepoSyncFrame'
          - $ref: '#/components/messages/RepoIdentityFrame'
          - $ref: '#/components/messages/RepoAccountFrame'
          - $ref: '#/components/messages/RepoHandleFrame'
          - $ref: '#/components/messages/RepoMigrateFrame'
          - $ref: '#/components/messages/RepoTombstoneFrame'
          - $ref: '#/components/messages/RepoInfoFrame'
          - $ref: '#/components/messages/RepoErrorFrame'

  #####################################################################
  # com.atproto.label.subscribeLabels
  #####################################################################
  xrpc/com.atproto.label.subscribeLabels:
    description: |
      Subscribe to stream of labels (and negations). Public endpoint
      implemented by mod services. Uses the same sequencing scheme as the
      repository event stream and the same binary CBOR header/payload framing.
    servers:
      - ozone
    parameters:
      cursor:
        description: The last known event seq number to backfill from.
        schema:
          type: integer
          format: int64
    bindings:
      ws:
        method: GET
        query:
          type: object
          properties:
            cursor:
              type: integer
        bindingVersion: '0.1.0'
    subscribe:
      operationId: subscribeLabels
      summary: Subscribe to the label/negation stream.
      message:
        oneOf:
          - $ref: '#/components/messages/LabelsFrame'
          - $ref: '#/components/messages/LabelInfoFrame'
          - $ref: '#/components/messages/LabelErrorFrame'

  #####################################################################
  # Jetstream
  #####################################################################
  subscribe:
    description: |
      Jetstream WebSocket endpoint. Emits a simplified JSON projection of the
      AT Protocol firehose. Each WebSocket frame is one JSON event object
      (optionally zstd-compressed if `compress=true` is set on the query).
    servers:
      - jetstream2-us-east
      - jetstream1-us-east
      - jetstream1-us-west
      - jetstream2-us-west
    bindings:
      ws:
        method: GET
        query:
          type: object
          properties:
            wantedCollections:
              type: array
              description: |
                Filter events to only the listed collection NSIDs. Supports
                NSID prefixes (e.g., `app.bsky.graph.*`). Up to 100 entries.
              items:
                type: string
            wantedDids:
              type: array
              description: |
                Filter events to only the listed repository DIDs. Up to 10,000
                entries.
              items:
                type: string
                format: did
            maxMessageSizeBytes:
              type: integer
              description: |
                Maximum payload size, in bytes. Zero (the default) is treated
                as unlimited; negative values are treated as zero.
              default: 0
            cursor:
              type: integer
              format: int64
              description: |
                Unix microseconds timestamp to begin playback from. If absent
                or in the future, the stream operates in live-tail mode.
            compress:
              type: boolean
              description: When `true`, frames are zstd-compressed.
              default: false
            requireHello:
              type: boolean
              description: |
                When `true`, the server pauses event delivery until the
                client sends an `options_update` SubscriberSourcedMessage.
              default: false
        bindingVersion: '0.1.0'
    subscribe:
      operationId: jetstreamSubscribe
      summary: Subscribe to the Jetstream JSON event stream.
      message:
        oneOf:
          - $ref: '#/components/messages/JetstreamCommitCreate'
          - $ref: '#/components/messages/JetstreamCommitUpdate'
          - $ref: '#/components/messages/JetstreamCommitDelete'
          - $ref: '#/components/messages/JetstreamIdentity'
          - $ref: '#/components/messages/JetstreamAccount'
    publish:
      operationId: jetstreamSubscriberMessage
      summary: |
        Send a `SubscriberSourcedMessage` to update subscription options after
        connecting. Currently supports the `options_update` message.
      message:
        $ref: '#/components/messages/JetstreamSubscriberSourcedMessage'

components:

  messages:

    #################################################################
    # subscribeRepos frames
    #################################################################
    RepoCommitFrame:
      name: RepoCommitFrame
      title: '#commit'
      summary: Repository commit event.
      contentType: application/cbor
      payload:
        $ref: '#/components/schemas/RepoCommitFrame'

    RepoSyncFrame:
      name: RepoSyncFrame
      title: '#sync'
      summary: |
        Sync event - asserts current repository state without including diff
        data on the firehose. Used for recovery / desync resolution.
      contentType: application/cbor
      payload:
        $ref: '#/components/schemas/RepoSyncFrame'

    RepoIdentityFrame:
      name: RepoIdentityFrame
      title: '#identity'
      summary: Account identity change event (handle, signing key, or PDS).
      contentType: application/cbor
      payload:
        $ref: '#/components/schemas/RepoIdentityFrame'

    RepoAccountFrame:
      name: RepoAccountFrame
      title: '#account'
      summary: Account hosting-status change event.
      contentType: application/cbor
      payload:
        $ref: '#/components/schemas/RepoAccountFrame'

    RepoHandleFrame:
      name: RepoHandleFrame
      title: '#handle'
      summary: DEPRECATED - use `#identity` instead. Legacy handle change event.
      contentType: application/cbor
      payload:
        $ref: '#/components/schemas/RepoHandleFrame'

    RepoMigrateFrame:
      name: RepoMigrateFrame
      title: '#migrate'
      summary: DEPRECATED - use `#account` instead. Legacy account-migration event.
      contentType: application/cbor
      payload:
        $ref: '#/components/schemas/RepoMigrateFrame'

    RepoTombstoneFrame:
      name: RepoTombstoneFrame
      title: '#tombstone'
      summary: DEPRECATED - use `#account` instead. Legacy account-tombstone event.
      contentType: application/cbor
      payload:
        $ref: '#/components/schemas/RepoTombstoneFrame'

    RepoInfoFrame:
      name: RepoInfoFrame
      title: '#info'
      summary: |
        Informational message (not persisted, no `seq`). Currently the only
        defined name value is `OutdatedCursor`.
      contentType: application/cbor
      payload:
        $ref: '#/components/schemas/InfoFrame'

    RepoErrorFrame:
      name: RepoErrorFrame
      title: error
      summary: |
        Error frame (`op = -1`). Possible `error` values for subscribeRepos:
        `FutureCursor`, `ConsumerTooSlow`. The connection is closed after this
        frame is delivered.
      contentType: application/cbor
      payload:
        $ref: '#/components/schemas/ErrorFrame'

    #################################################################
    # subscribeLabels frames
    #################################################################
    LabelsFrame:
      name: LabelsFrame
      title: '#labels'
      summary: A batch of labels (and/or negations).
      contentType: application/cbor
      payload:
        $ref: '#/components/schemas/LabelsFrame'

    LabelInfoFrame:
      name: LabelInfoFrame
      title: '#info'
      summary: Informational message on the label stream.
      contentType: application/cbor
      payload:
        $ref: '#/components/schemas/InfoFrame'

    LabelErrorFrame:
      name: LabelErrorFrame
      title: error
      summary: |
        Error frame (`op = -1`). Possible `error` values for subscribeLabels:
        `FutureCursor`.
      contentType: application/cbor
      payload:
        $ref: '#/components/schemas/ErrorFrame'

    #################################################################
    # Jetstream messages
    #################################################################
    JetstreamCommitCreate:
      name: JetstreamCommitCreate
      title: commit (create)
      summary: |
        Jetstream commit event with `commit.operation = "create"`. Contains
        the full record JSON.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/JetstreamCommitCreate'

    JetstreamCommitUpdate:
      name: JetstreamCommitUpdate
      title: commit (update)
      summary: |
        Jetstream commit event with `commit.operation = "update"`. Contains
        the full record JSON, replacing the previous version.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/JetstreamCommitUpdate'

    JetstreamCommitDelete:
      name: JetstreamCommitDelete
      title: commit (delete)
      summary: |
        Jetstream commit event with `commit.operation = "delete"`. No record
        body.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/JetstreamCommitDelete'

    JetstreamIdentity:
      name: JetstreamIdentity
      title: identity
      summary: |
        Jetstream identity event. Wraps the AT Protocol `#identity` event in
        a Jetstream envelope.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/JetstreamIdentity'

    JetstreamAccount:
      name: JetstreamAccount
      title: account
      summary: |
        Jetstream account event. Wraps the AT Protocol `#account` event in a
        Jetstream envelope.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/JetstreamAccount'

    JetstreamSubscriberSourcedMessage:
      name: JetstreamSubscriberSourcedMessage
      title: SubscriberSourcedMessage
      summary: |
        JSON message sent from client to Jetstream server after connecting.
        Currently the only supported `type` is `options_update`.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/JetstreamSubscriberSourcedMessage'

  schemas:

    #################################################################
    # Shared firehose frame primitives
    #################################################################
    FirehoseFrameHeader:
      type: object
      description: |
        DAG-CBOR object that prefixes every WebSocket frame. `op = 1` for
        regular messages (with `t` set to the short-form type, e.g.
        `#commit`); `op = -1` for error frames (no `t`).
      required: [op]
      properties:
        op:
          type: integer
          enum: [1, -1]
          description: 1 = regular message; -1 = error frame.
        t:
          type: string
          description: |
            Short-form lexicon type identifier, e.g. `#commit`, `#identity`,
            `#account`, `#handle`, `#migrate`, `#tombstone`, `#info`,
            `#sync`, `#labels`. Required when `op = 1`.

    ErrorFrame:
      type: object
      description: |
        Payload of an error frame. The connection is closed by the server
        immediately after the frame is sent.
      required: [error]
      properties:
        error:
          type: string
          description: Short error name.
        message:
          type: string
          description: Optional human-readable error message.

    InfoFrame:
      type: object
      description: |
        Informational message payload. Not persisted; has no `seq`.
      required: [name]
      properties:
        name:
          type: string
          enum: [OutdatedCursor]
          description: Short info name. Known values - `OutdatedCursor`.
        message:
          type: string
          description: Optional human-readable message.

    #################################################################
    # com.atproto.sync.subscribeRepos payload schemas
    #################################################################
    RepoCommitFrame:
      type: object
      description: |
        `#commit` payload. Represents an update of repository state. Empty
        commits (no record changes, only `rev`/signature update) are allowed.
      required:
        - seq
        - rebase
        - tooBig
        - repo
        - commit
        - rev
        - since
        - blocks
        - ops
        - blobs
        - time
      properties:
        seq:
          type: integer
          format: int64
          description: The stream sequence number of this message.
        rebase:
          type: boolean
          description: DEPRECATED - unused.
        tooBig:
          type: boolean
          description: |
            DEPRECATED - replaced by `#sync` event and data limits. Indicates
            this commit contained too many ops or was too large; consumers
            need a separate fetch to recover.
        repo:
          type: string
          format: did
          description: |
            The repo this event comes from. (All other message types use
            `did` for the same purpose.)
        commit:
          type: string
          format: cid
          description: Repo commit object CID.
        rev:
          type: string
          format: tid
          description: |
            The rev of the emitted commit. Also present inside the commit
            block in `blocks` (unless `tooBig`).
        since:
          type: string
          format: tid
          nullable: true
          description: The rev of the last emitted commit from this repo (if any).
        blocks:
          type: string
          format: byte
          description: |
            CAR file (binary) containing relevant blocks as a diff since the
            previous repo state. The commit block must be the first entry in
            the CAR header `roots` list. Maximum 2,000,000 bytes.
          maxLength: 2000000
        ops:
          type: array
          maxItems: 200
          description: Repo mutation operations included in this commit.
          items:
            $ref: '#/components/schemas/RepoOp'
        blobs:
          type: array
          description: |
            DEPRECATED - will soon always be empty. List of new blob CIDs
            referenced by records in this commit.
          items:
            type: string
            format: cid
        prevData:
          type: string
          format: cid
          description: |
            Root CID of the MST tree for the previous commit (the `since`
            revision). Required for the Sync 1.1 / "inductive" firehose.
        time:
          type: string
          format: date-time
          description: Timestamp of when this message was originally broadcast.

    RepoOp:
      type: object
      description: A repo operation - a mutation of a single record.
      required: [action, path, cid]
      properties:
        action:
          type: string
          enum: [create, update, delete]
        path:
          type: string
          description: '`{collection}/{rkey}` path of the affected record.'
        cid:
          type: string
          format: cid
          nullable: true
          description: |
            For creates and updates, the new record CID. For deletions, null.
        prev:
          type: string
          format: cid
          description: |
            For updates and deletes, the previous record CID (required for
            inductive firehose). For creates, this field is omitted.

    RepoSyncFrame:
      type: object
      description: |
        `#sync` payload. Updates the repo to a new state without including the
        diff on the firehose. Used to recover from broken commit streams or
        data-loss incidents.
      required: [seq, did, blocks, rev, time]
      properties:
        seq:
          type: integer
          format: int64
        did:
          type: string
          format: did
          description: |
            The account this repo event corresponds to. Must match the value
            inside the commit object.
        blocks:
          type: string
          format: byte
          description: |
            CAR file (binary) containing the commit, as a block. CAR header's
            first root must be the commit block CID. Maximum 10,000 bytes.
          maxLength: 10000
        rev:
          type: string
          description: |
            The rev of the commit. Must match the value inside the commit
            object.
        time:
          type: string
          format: date-time

    RepoIdentityFrame:
      type: object
      description: |
        `#identity` payload. Signals that an account's identity may have
        changed (handle, signing key, or PDS endpoint). Downstream services
        should refresh their identity cache.
      required: [seq, did, time]
      properties:
        seq:
          type: integer
          format: int64
        did:
          type: string
          format: did
        time:
          type: string
          format: date-time
        handle:
          type: string
          format: handle
          description: |
            Current handle for the account, or `handle.invalid` if validation
            fails. Optional; presence or absence does NOT indicate that the
            handle itself changed.

    RepoAccountFrame:
      type: object
      description: |
        `#account` payload. Signals an account-status change on the emitting
        host (PDS or Relay). The status reflects the host that emitted the
        event, which may differ from the currently active PDS.
      required: [seq, did, time, active]
      properties:
        seq:
          type: integer
          format: int64
        did:
          type: string
          format: did
        time:
          type: string
          format: date-time
        active:
          type: boolean
          description: |
            True if the host can still serve the account's repository.
        status:
          type: string
          enum:
            - takendown
            - suspended
            - deleted
            - deactivated
            - desynchronized
            - throttled
          description: |
            If `active = false`, optionally indicates why the account is not
            active.

    RepoHandleFrame:
      type: object
      description: DEPRECATED - use `#identity` instead. Legacy handle event.
      required: [seq, did, handle, time]
      properties:
        seq:
          type: integer
          format: int64
        did:
          type: string
          format: did
        handle:
          type: string
          format: handle
        time:
          type: string
          format: date-time

    RepoMigrateFrame:
      type: object
      description: DEPRECATED - use `#account` instead. Legacy migrate event.
      required: [seq, did, migrateTo, time]
      properties:
        seq:
          type: integer
          format: int64
        did:
          type: string
          format: did
        migrateTo:
          type: string
          nullable: true
        time:
          type: string
          format: date-time

    RepoTombstoneFrame:
      type: object
      description: DEPRECATED - use `#account` instead. Legacy tombstone event.
      required: [seq, did, time]
      properties:
        seq:
          type: integer
          format: int64
        did:
          type: string
          format: did
        time:
          type: string
          format: date-time

    #################################################################
    # com.atproto.label.subscribeLabels payload schemas
    #################################################################
    LabelsFrame:
      type: object
      description: '`#labels` payload - a batch of labels and/or negations.'
      required: [seq, labels]
      properties:
        seq:
          type: integer
          format: int64
        labels:
          type: array
          items:
            $ref: '#/components/schemas/Label'

    Label:
      type: object
      description: |
        Metadata tag on an atproto resource (eg, repo or record). Defined by
        `com.atproto.label.defs#label`.
      required: [src, uri, val, cts]
      properties:
        ver:
          type: integer
          description: The AT Protocol version of the label object.
        src:
          type: string
          format: did
          description: DID of the actor who created this label.
        uri:
          type: string
          format: uri
          description: |
            AT URI of the record, repository (account), or other resource
            this label applies to.
        cid:
          type: string
          format: cid
          description: |
            Optional; CID of the specific version of the `uri` resource this
            label applies to.
        val:
          type: string
          maxLength: 128
          description: Short string name of the value/type of this label.
        neg:
          type: boolean
          description: |
            If true, this is a negation label that overrides a previous
            label.
        cts:
          type: string
          format: date-time
          description: Timestamp when this label was created.
        exp:
          type: string
          format: date-time
          description: |
            Timestamp at which this label expires (no longer applies).
        sig:
          type: string
          format: byte
          description: Signature of the dag-cbor encoded label.

    #################################################################
    # Jetstream payload schemas
    #################################################################
    JetstreamEventBase:
      type: object
      description: Fields present on every Jetstream event.
      required: [did, time_us, kind]
      properties:
        did:
          type: string
          format: did
          description: DID of the repository that produced the event.
        time_us:
          type: integer
          format: int64
          description: |
            Unix microseconds timestamp at which Jetstream processed the
            event. Also the cursor value to resume from.
        kind:
          type: string
          enum: [commit, identity, account]

    JetstreamCommitBase:
      allOf:
        - $ref: '#/components/schemas/JetstreamEventBase'
        - type: object
          required: [commit]
          properties:
            kind:
              type: string
              enum: [commit]

    JetstreamCommitCreate:
      allOf:
        - $ref: '#/components/schemas/JetstreamCommitBase'
        - type: object
          properties:
            commit:
              type: object
              required: [rev, operation, collection, rkey, record, cid]
              properties:
                rev:
                  type: string
                  format: tid
                operation:
                  type: string
                  enum: [create]
                collection:
                  type: string
                  description: NSID of the record's collection.
                rkey:
                  type: string
                  description: Record key.
                record:
                  type: object
                  description: |
                    Full record contents as JSON. Schema depends on the
                    `collection` NSID (e.g. `app.bsky.feed.post`,
                    `app.bsky.feed.like`, `app.bsky.graph.follow`).
                cid:
                  type: string
                  format: cid

    JetstreamCommitUpdate:
      allOf:
        - $ref: '#/components/schemas/JetstreamCommitBase'
        - type: object
          properties:
            commit:
              type: object
              required: [rev, operation, collection, rkey, record, cid]
              properties:
                rev:
                  type: string
                  format: tid
                operation:
                  type: string
                  enum: [update]
                collection:
                  type: string
                rkey:
                  type: string
                record:
                  type: object
                  description: New full record contents, replacing the prior version.
                cid:
                  type: string
                  format: cid

    JetstreamCommitDelete:
      allOf:
        - $ref: '#/components/schemas/JetstreamCommitBase'
        - type: object
          properties:
            commit:
              type: object
              required: [rev, operation, collection, rkey]
              properties:
                rev:
                  type: string
                  format: tid
                operation:
                  type: string
                  enum: [delete]
                collection:
                  type: string
                rkey:
                  type: string

    JetstreamIdentity:
      allOf:
        - $ref: '#/components/schemas/JetstreamEventBase'
        - type: object
          required: [identity]
          properties:
            kind:
              type: string
              enum: [identity]
            identity:
              type: object
              description: |
                Embedded AT Protocol `#identity` event. Fields mirror the
                `com.atproto.sync.subscribeRepos#identity` payload.
              required: [did, seq, time]
              properties:
                did:
                  type: string
                  format: did
                handle:
                  type: string
                  format: handle
                seq:
                  type: integer
                  format: int64
                time:
                  type: string
                  format: date-time

    JetstreamAccount:
      allOf:
        - $ref: '#/components/schemas/JetstreamEventBase'
        - type: object
          required: [account]
          properties:
            kind:
              type: string
              enum: [account]
            account:
              type: object
              description: |
                Embedded AT Protocol `#account` event. Fields mirror the
                `com.atproto.sync.subscribeRepos#account` payload.
              required: [active, did, seq, time]
              properties:
                active:
                  type: boolean
                did:
                  type: string
                  format: did
                seq:
                  type: integer
                  format: int64
                time:
                  type: string
                  format: date-time
                status:
                  type: string
                  enum:
                    - takendown
                    - suspended
                    - deleted
                    - deactivated
                    - desynchronized
                    - throttled

    JetstreamSubscriberSourcedMessage:
      type: object
      description: |
        Message sent from a Jetstream client to the server after connecting,
        used to update subscription options on the fly. Maximum 10 MB per
        message; payload limits - 100 collections and 10,000 DIDs.
      required: [type, payload]
      properties:
        type:
          type: string
          enum: [options_update]
        payload:
          type: object
          properties:
            wantedCollections:
              type: array
              items:
                type: string
            wantedDids:
              type: array
  

# --- truncated at 32 KB (32 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/bluesky/refs/heads/main/asyncapi/bluesky-asyncapi.yml