Crisp · AsyncAPI Specification

Crisp Realtime Surface (Webhooks + RTM)

Version 1.0.0

AsyncAPI description of Crisp's two realtime delivery surfaces: * **Web Hooks (v1)** — HTTP POST callbacks delivered to a subscriber URL registered on a Crisp website or Crisp plugin. Payload envelope: `{ website_id, event, data, timestamp }`. Plugin Hooks are signed with HMAC-SHA256 via the `X-Crisp-Signature` header. Website Hooks are not signed; URL-parameter secrets are used instead. Both share the same event taxonomy. * **RTM API (v1)** — Socket.IO (websocket transport only, WSS) stream of the same conversational events plus several RTM-only events (spam, people-import progress, widget action, media animation listing). The endpoint URL is dynamic and must be acquired through the REST API "Get Connect Endpoints" call before each connection. Event names are quoted verbatim from https://docs.crisp.chat/references/rtm-api/v1/ and https://docs.crisp.chat/references/web-hooks/v1/.

View Spec View on GitHub Customer ServiceLive ChatHelpdeskMessagingChatbotsAsyncAPIWebhooksEvents

Channels

/webhook
subscribe receiveCrispWebhook
Receive a Crisp Web Hook callback
Single inbound HTTP channel that fans out all webhook events. The specific event is carried inside the JSON envelope's `event` field — there is no per-event path.
rtm/authentication
publish sendAuthentication
Socket.IO event the client emits within ~10s of connecting to authenticate. Server replies with `authenticated` on success or `unauthorized` on failure.
rtm/session:update_availability
subscribe
rtm/session:update_verify
subscribe
rtm/session:request:initiated
subscribe
rtm/session:set_email
subscribe
rtm/session:set_phone
subscribe
rtm/session:set_address
subscribe
rtm/session:set_subject
subscribe
rtm/session:set_avatar
subscribe
rtm/session:set_nickname
subscribe
rtm/session:set_origin
subscribe
rtm/session:set_data
subscribe
rtm/session:set_segments
subscribe
rtm/session:set_block
subscribe
rtm/session:set_opened
subscribe
rtm/session:set_closed
subscribe
rtm/session:set_participants
subscribe
rtm/session:set_mentions
subscribe
rtm/session:set_routing
subscribe
rtm/session:set_inbox
subscribe
rtm/session:set_state
subscribe
rtm/session:sync:capabilities
subscribe
rtm/session:sync:geolocation
subscribe
rtm/session:sync:system
subscribe
rtm/session:sync:network
subscribe
rtm/session:sync:timezone
subscribe
rtm/session:sync:locales
subscribe
rtm/session:sync:pages
subscribe
rtm/session:sync:events
subscribe
rtm/session:sync:rating
subscribe
rtm/session:sync:topic
subscribe
rtm/session:removed
subscribe
rtm/session:error
subscribe
rtm/message:updated
subscribe
rtm/message:send
subscribe
rtm/message:received
subscribe
rtm/message:removed
subscribe
rtm/message:compose:send
subscribe
rtm/message:compose:receive
subscribe
rtm/message:acknowledge:read:send
subscribe
rtm/message:acknowledge:read:received
subscribe
rtm/message:acknowledge:unread:send
subscribe
rtm/message:acknowledge:delivered
subscribe
rtm/message:acknowledge:ignored
subscribe
rtm/message:notify:unread:send
subscribe
rtm/message:notify:unread:received
subscribe
rtm/spam:message
subscribe
RTM-only. Not delivered via Web Hooks.
rtm/spam:decision
subscribe
RTM-only. Not delivered via Web Hooks.
rtm/people:profile:created
subscribe
rtm/people:profile:updated
subscribe
rtm/people:profile:removed
subscribe
rtm/people:bind:session
subscribe
rtm/people:sync:profile
subscribe
rtm/people:import:progress
subscribe
RTM-only. Not delivered via Web Hooks.
rtm/people:import:done
subscribe
RTM-only. Not delivered via Web Hooks.
rtm/campaign:progress
subscribe
rtm/campaign:dispatched
subscribe
rtm/campaign:running
subscribe
rtm/browsing:request:initiated
subscribe
rtm/browsing:request:rejected
subscribe
rtm/call:request:initiated
subscribe
rtm/call:request:rejected
subscribe
rtm/identity:verify:request
subscribe
rtm/widget:action:processed
subscribe
RTM-only. Not delivered via Web Hooks.
rtm/status:health:changed
subscribe
rtm/website:update_visitors_count
subscribe
rtm/website:update_operators_availability
subscribe
rtm/website:users:available
subscribe
rtm/bucket:url:upload:generated
subscribe
rtm/bucket:url:avatar:generated
subscribe
rtm/bucket:url:website:generated
subscribe
rtm/bucket:url:campaign:generated
subscribe
rtm/bucket:url:helpdesk:generated
subscribe
rtm/bucket:url:status:generated
subscribe
rtm/bucket:url:processing:generated
subscribe
rtm/media:animation:listed
subscribe
RTM-only. Not delivered via Web Hooks.
rtm/email:subscribe
subscribe
rtm/email:track:view
subscribe
rtm/plugin:channel
subscribe
rtm/plugin:event
subscribe
rtm/plugin:subscription:updated
subscribe
rtm/plugin:settings:saved
subscribe
rtm/plan:subscription:updated
subscribe

Messages

WebhookEnvelope
Crisp Web Hook delivery envelope
HTTP POST body sent to the subscriber's URL.
AuthenticationRequest
Socket.IO `authentication` event
Authenticated
Socket.IO `authenticated` ack
Unauthorized
Socket.IO `unauthorized` ack
SessionEvent
Session namespace event
MessageEvent
Message namespace event
SpamEvent
Spam namespace event (RTM-only)
PeopleEvent
People namespace event
CampaignEvent
Campaign namespace event
BrowsingEvent
Browsing / MagicBrowse namespace event
CallEvent
Call request namespace event
IdentityEvent
Identity verification namespace event
WidgetEvent
Widget namespace event (RTM-only)
StatusEvent
Status-page namespace event
WebsiteEvent
Website-level namespace event
BucketEvent
Bucket signed-URL namespace event
MediaEvent
Media library namespace event (RTM-only)
EmailEvent
Email namespace event
PluginEvent
Plugin namespace event
PlanEvent
Plan namespace event

Servers

wss
rtm rtm.crisp.chat
Socket.IO RTM endpoint. The real host/path is dynamic and MUST be fetched per-connection from the REST API: `GET https://api.crisp.chat/v1/plugin/connect/endpoints`. The Socket.IO client should be created with `transports: ["websocket"]` (no HTTP long-polling, no insecure WS).
https
webhook {subscriberHost}
The subscriber's own HTTPS endpoint (configured per website or per plugin). Crisp performs `HTTP POST` with a JSON body. Successful delivery requires a 2xx response.

AsyncAPI Specification

Raw ↑
asyncapi: "2.6.0"
info:
  title: Crisp Realtime Surface (Webhooks + RTM)
  version: "1.0.0"
  description: |
    AsyncAPI description of Crisp's two realtime delivery surfaces:

    * **Web Hooks (v1)** — HTTP POST callbacks delivered to a subscriber URL
      registered on a Crisp website or Crisp plugin. Payload envelope:
      `{ website_id, event, data, timestamp }`.
      Plugin Hooks are signed with HMAC-SHA256 via the `X-Crisp-Signature`
      header. Website Hooks are not signed; URL-parameter secrets are used
      instead. Both share the same event taxonomy.
    * **RTM API (v1)** — Socket.IO (websocket transport only, WSS) stream of
      the same conversational events plus several RTM-only events
      (spam, people-import progress, widget action, media animation listing).
      The endpoint URL is dynamic and must be acquired through the REST API
      "Get Connect Endpoints" call before each connection.

    Event names are quoted verbatim from
    https://docs.crisp.chat/references/rtm-api/v1/ and
    https://docs.crisp.chat/references/web-hooks/v1/.
  contact:
    name: Crisp Developer Hub
    url: https://docs.crisp.chat/
  license:
    name: Proprietary
    url: https://crisp.chat/en/terms/

defaultContentType: application/json

servers:
  rtm:
    url: rtm.crisp.chat
    protocol: wss
    description: |
      Socket.IO RTM endpoint. The real host/path is dynamic and MUST be
      fetched per-connection from the REST API:
      `GET https://api.crisp.chat/v1/plugin/connect/endpoints`.
      The Socket.IO client should be created with
      `transports: ["websocket"]` (no HTTP long-polling, no insecure WS).
    security:
      - rtmAuthentication: []
  webhook:
    url: "{subscriberHost}"
    protocol: https
    description: |
      The subscriber's own HTTPS endpoint (configured per website or per
      plugin). Crisp performs `HTTP POST` with a JSON body. Successful
      delivery requires a 2xx response.
    variables:
      subscriberHost:
        default: subscriber.example.com
        description: Hostname of the consumer's webhook receiver.

channels:
  # ---------------------------------------------------------------- WEBHOOK
  /webhook:
    description: |
      Single inbound HTTP channel that fans out all webhook events.
      The specific event is carried inside the JSON envelope's `event`
      field — there is no per-event path.
    bindings:
      http:
        type: request
        method: POST
    subscribe:
      operationId: receiveCrispWebhook
      summary: Receive a Crisp Web Hook callback
      bindings:
        http:
          type: request
          method: POST
          headers:
            type: object
            properties:
              X-Crisp-Hook-Origin:
                type: string
                description: Origin of the hook (e.g. `plugin` or `website`).
              X-Crisp-Request-Timestamp:
                type: string
                description: UNIX timestamp at which the hook was emitted.
              X-Crisp-Signature:
                type: string
                description: |
                  HMAC-SHA256 of `timestamp;body` computed with the plugin
                  signature secret. **Plugin Hooks only** — Website Hooks
                  are not signed.
              X-Delivery-Attempt-Count:
                type: integer
                description: Current delivery attempt number.
              X-Delivery-Attempt-Limit:
                type: integer
                description: Maximum allowed delivery attempts.
      message:
        oneOf:
          - $ref: "#/components/messages/WebhookEnvelope"

  # -------------------------------------------------------------------- RTM
  rtm/authentication:
    description: |
      Socket.IO event the client emits within ~10s of connecting to
      authenticate. Server replies with `authenticated` on success or
      `unauthorized` on failure.
    publish:
      operationId: sendAuthentication
      message:
        $ref: "#/components/messages/AuthenticationRequest"
    subscribe:
      operationId: onAuthenticationResult
      message:
        oneOf:
          - $ref: "#/components/messages/Authenticated"
          - $ref: "#/components/messages/Unauthorized"

  # -- Session ---------------------------------------------------------------
  "rtm/session:update_availability":
    subscribe: { message: { $ref: "#/components/messages/SessionEvent" } }
  "rtm/session:update_verify":
    subscribe: { message: { $ref: "#/components/messages/SessionEvent" } }
  "rtm/session:request:initiated":
    subscribe: { message: { $ref: "#/components/messages/SessionEvent" } }
  "rtm/session:set_email":
    subscribe: { message: { $ref: "#/components/messages/SessionEvent" } }
  "rtm/session:set_phone":
    subscribe: { message: { $ref: "#/components/messages/SessionEvent" } }
  "rtm/session:set_address":
    subscribe: { message: { $ref: "#/components/messages/SessionEvent" } }
  "rtm/session:set_subject":
    subscribe: { message: { $ref: "#/components/messages/SessionEvent" } }
  "rtm/session:set_avatar":
    subscribe: { message: { $ref: "#/components/messages/SessionEvent" } }
  "rtm/session:set_nickname":
    subscribe: { message: { $ref: "#/components/messages/SessionEvent" } }
  "rtm/session:set_origin":
    subscribe: { message: { $ref: "#/components/messages/SessionEvent" } }
  "rtm/session:set_data":
    subscribe: { message: { $ref: "#/components/messages/SessionEvent" } }
  "rtm/session:set_segments":
    subscribe: { message: { $ref: "#/components/messages/SessionEvent" } }
  "rtm/session:set_block":
    subscribe: { message: { $ref: "#/components/messages/SessionEvent" } }
  "rtm/session:set_opened":
    subscribe: { message: { $ref: "#/components/messages/SessionEvent" } }
  "rtm/session:set_closed":
    subscribe: { message: { $ref: "#/components/messages/SessionEvent" } }
  "rtm/session:set_participants":
    subscribe: { message: { $ref: "#/components/messages/SessionEvent" } }
  "rtm/session:set_mentions":
    subscribe: { message: { $ref: "#/components/messages/SessionEvent" } }
  "rtm/session:set_routing":
    subscribe: { message: { $ref: "#/components/messages/SessionEvent" } }
  "rtm/session:set_inbox":
    subscribe: { message: { $ref: "#/components/messages/SessionEvent" } }
  "rtm/session:set_state":
    subscribe: { message: { $ref: "#/components/messages/SessionEvent" } }
  "rtm/session:sync:capabilities":
    subscribe: { message: { $ref: "#/components/messages/SessionEvent" } }
  "rtm/session:sync:geolocation":
    subscribe: { message: { $ref: "#/components/messages/SessionEvent" } }
  "rtm/session:sync:system":
    subscribe: { message: { $ref: "#/components/messages/SessionEvent" } }
  "rtm/session:sync:network":
    subscribe: { message: { $ref: "#/components/messages/SessionEvent" } }
  "rtm/session:sync:timezone":
    subscribe: { message: { $ref: "#/components/messages/SessionEvent" } }
  "rtm/session:sync:locales":
    subscribe: { message: { $ref: "#/components/messages/SessionEvent" } }
  "rtm/session:sync:pages":
    subscribe: { message: { $ref: "#/components/messages/SessionEvent" } }
  "rtm/session:sync:events":
    subscribe: { message: { $ref: "#/components/messages/SessionEvent" } }
  "rtm/session:sync:rating":
    subscribe: { message: { $ref: "#/components/messages/SessionEvent" } }
  "rtm/session:sync:topic":
    subscribe: { message: { $ref: "#/components/messages/SessionEvent" } }
  "rtm/session:removed":
    subscribe: { message: { $ref: "#/components/messages/SessionEvent" } }
  "rtm/session:error":
    subscribe: { message: { $ref: "#/components/messages/SessionEvent" } }

  # -- Message ---------------------------------------------------------------
  "rtm/message:updated":
    subscribe: { message: { $ref: "#/components/messages/MessageEvent" } }
  "rtm/message:send":
    subscribe: { message: { $ref: "#/components/messages/MessageEvent" } }
  "rtm/message:received":
    subscribe: { message: { $ref: "#/components/messages/MessageEvent" } }
  "rtm/message:removed":
    subscribe: { message: { $ref: "#/components/messages/MessageEvent" } }
  "rtm/message:compose:send":
    subscribe: { message: { $ref: "#/components/messages/MessageEvent" } }
  "rtm/message:compose:receive":
    subscribe: { message: { $ref: "#/components/messages/MessageEvent" } }
  "rtm/message:acknowledge:read:send":
    subscribe: { message: { $ref: "#/components/messages/MessageEvent" } }
  "rtm/message:acknowledge:read:received":
    subscribe: { message: { $ref: "#/components/messages/MessageEvent" } }
  "rtm/message:acknowledge:unread:send":
    subscribe: { message: { $ref: "#/components/messages/MessageEvent" } }
  "rtm/message:acknowledge:delivered":
    subscribe: { message: { $ref: "#/components/messages/MessageEvent" } }
  "rtm/message:acknowledge:ignored":
    subscribe: { message: { $ref: "#/components/messages/MessageEvent" } }
  "rtm/message:notify:unread:send":
    subscribe: { message: { $ref: "#/components/messages/MessageEvent" } }
  "rtm/message:notify:unread:received":
    subscribe: { message: { $ref: "#/components/messages/MessageEvent" } }

  # -- Spam (RTM-only) -------------------------------------------------------
  "rtm/spam:message":
    description: RTM-only. Not delivered via Web Hooks.
    subscribe: { message: { $ref: "#/components/messages/SpamEvent" } }
  "rtm/spam:decision":
    description: RTM-only. Not delivered via Web Hooks.
    subscribe: { message: { $ref: "#/components/messages/SpamEvent" } }

  # -- People ----------------------------------------------------------------
  "rtm/people:profile:created":
    subscribe: { message: { $ref: "#/components/messages/PeopleEvent" } }
  "rtm/people:profile:updated":
    subscribe: { message: { $ref: "#/components/messages/PeopleEvent" } }
  "rtm/people:profile:removed":
    subscribe: { message: { $ref: "#/components/messages/PeopleEvent" } }
  "rtm/people:bind:session":
    subscribe: { message: { $ref: "#/components/messages/PeopleEvent" } }
  "rtm/people:sync:profile":
    subscribe: { message: { $ref: "#/components/messages/PeopleEvent" } }
  "rtm/people:import:progress":
    description: RTM-only. Not delivered via Web Hooks.
    subscribe: { message: { $ref: "#/components/messages/PeopleEvent" } }
  "rtm/people:import:done":
    description: RTM-only. Not delivered via Web Hooks.
    subscribe: { message: { $ref: "#/components/messages/PeopleEvent" } }

  # -- Campaign --------------------------------------------------------------
  "rtm/campaign:progress":
    subscribe: { message: { $ref: "#/components/messages/CampaignEvent" } }
  "rtm/campaign:dispatched":
    subscribe: { message: { $ref: "#/components/messages/CampaignEvent" } }
  "rtm/campaign:running":
    subscribe: { message: { $ref: "#/components/messages/CampaignEvent" } }

  # -- Browsing --------------------------------------------------------------
  "rtm/browsing:request:initiated":
    subscribe: { message: { $ref: "#/components/messages/BrowsingEvent" } }
  "rtm/browsing:request:rejected":
    subscribe: { message: { $ref: "#/components/messages/BrowsingEvent" } }

  # -- Call ------------------------------------------------------------------
  "rtm/call:request:initiated":
    subscribe: { message: { $ref: "#/components/messages/CallEvent" } }
  "rtm/call:request:rejected":
    subscribe: { message: { $ref: "#/components/messages/CallEvent" } }

  # -- Identity / Widget / Status -------------------------------------------
  "rtm/identity:verify:request":
    subscribe: { message: { $ref: "#/components/messages/IdentityEvent" } }
  "rtm/widget:action:processed":
    description: RTM-only. Not delivered via Web Hooks.
    subscribe: { message: { $ref: "#/components/messages/WidgetEvent" } }
  "rtm/status:health:changed":
    subscribe: { message: { $ref: "#/components/messages/StatusEvent" } }

  # -- Website ---------------------------------------------------------------
  "rtm/website:update_visitors_count":
    subscribe: { message: { $ref: "#/components/messages/WebsiteEvent" } }
  "rtm/website:update_operators_availability":
    subscribe: { message: { $ref: "#/components/messages/WebsiteEvent" } }
  "rtm/website:users:available":
    subscribe: { message: { $ref: "#/components/messages/WebsiteEvent" } }

  # -- Bucket ----------------------------------------------------------------
  "rtm/bucket:url:upload:generated":
    subscribe: { message: { $ref: "#/components/messages/BucketEvent" } }
  "rtm/bucket:url:avatar:generated":
    subscribe: { message: { $ref: "#/components/messages/BucketEvent" } }
  "rtm/bucket:url:website:generated":
    subscribe: { message: { $ref: "#/components/messages/BucketEvent" } }
  "rtm/bucket:url:campaign:generated":
    subscribe: { message: { $ref: "#/components/messages/BucketEvent" } }
  "rtm/bucket:url:helpdesk:generated":
    subscribe: { message: { $ref: "#/components/messages/BucketEvent" } }
  "rtm/bucket:url:status:generated":
    subscribe: { message: { $ref: "#/components/messages/BucketEvent" } }
  "rtm/bucket:url:processing:generated":
    subscribe: { message: { $ref: "#/components/messages/BucketEvent" } }

  # -- Media (RTM-only) ------------------------------------------------------
  "rtm/media:animation:listed":
    description: RTM-only. Not delivered via Web Hooks.
    subscribe: { message: { $ref: "#/components/messages/MediaEvent" } }

  # -- Email -----------------------------------------------------------------
  "rtm/email:subscribe":
    subscribe: { message: { $ref: "#/components/messages/EmailEvent" } }
  "rtm/email:track:view":
    subscribe: { message: { $ref: "#/components/messages/EmailEvent" } }

  # -- Plugin ----------------------------------------------------------------
  "rtm/plugin:channel":
    subscribe: { message: { $ref: "#/components/messages/PluginEvent" } }
  "rtm/plugin:event":
    subscribe: { message: { $ref: "#/components/messages/PluginEvent" } }
  "rtm/plugin:subscription:updated":
    subscribe: { message: { $ref: "#/components/messages/PluginEvent" } }
  "rtm/plugin:settings:saved":
    subscribe: { message: { $ref: "#/components/messages/PluginEvent" } }

  # -- Plan ------------------------------------------------------------------
  "rtm/plan:subscription:updated":
    subscribe: { message: { $ref: "#/components/messages/PlanEvent" } }

components:
  securitySchemes:
    rtmAuthentication:
      type: userPassword
      description: |
        Sent as the Socket.IO `authentication` event with
        `{ username: <identifier>, password: <key>, tier: <plugin|user>,
        events: [...] }`. Acquired the same way as REST credentials
        (plugin token or user token).

  messages:
    # Webhook envelope ------------------------------------------------------
    WebhookEnvelope:
      name: WebhookEnvelope
      title: Crisp Web Hook delivery envelope
      summary: HTTP POST body sent to the subscriber's URL.
      contentType: application/json
      payload:
        $ref: "#/components/schemas/WebhookEnvelope"

    # RTM handshake ---------------------------------------------------------
    AuthenticationRequest:
      name: authentication
      title: Socket.IO `authentication` event
      payload:
        $ref: "#/components/schemas/AuthenticationPayload"
    Authenticated:
      name: authenticated
      title: Socket.IO `authenticated` ack
      payload:
        type: object
        additionalProperties: true
    Unauthorized:
      name: unauthorized
      title: Socket.IO `unauthorized` ack
      payload:
        type: object
        additionalProperties: true

    # RTM event groups ------------------------------------------------------
    SessionEvent:
      name: SessionEvent
      title: Session namespace event
      payload: { $ref: "#/components/schemas/RtmEnvelope" }
    MessageEvent:
      name: MessageEvent
      title: Message namespace event
      payload: { $ref: "#/components/schemas/RtmEnvelope" }
    SpamEvent:
      name: SpamEvent
      title: Spam namespace event (RTM-only)
      payload: { $ref: "#/components/schemas/RtmEnvelope" }
    PeopleEvent:
      name: PeopleEvent
      title: People namespace event
      payload: { $ref: "#/components/schemas/RtmEnvelope" }
    CampaignEvent:
      name: CampaignEvent
      title: Campaign namespace event
      payload: { $ref: "#/components/schemas/RtmEnvelope" }
    BrowsingEvent:
      name: BrowsingEvent
      title: Browsing / MagicBrowse namespace event
      payload: { $ref: "#/components/schemas/RtmEnvelope" }
    CallEvent:
      name: CallEvent
      title: Call request namespace event
      payload: { $ref: "#/components/schemas/RtmEnvelope" }
    IdentityEvent:
      name: IdentityEvent
      title: Identity verification namespace event
      payload: { $ref: "#/components/schemas/RtmEnvelope" }
    WidgetEvent:
      name: WidgetEvent
      title: Widget namespace event (RTM-only)
      payload: { $ref: "#/components/schemas/RtmEnvelope" }
    StatusEvent:
      name: StatusEvent
      title: Status-page namespace event
      payload: { $ref: "#/components/schemas/RtmEnvelope" }
    WebsiteEvent:
      name: WebsiteEvent
      title: Website-level namespace event
      payload: { $ref: "#/components/schemas/RtmEnvelope" }
    BucketEvent:
      name: BucketEvent
      title: Bucket signed-URL namespace event
      payload: { $ref: "#/components/schemas/RtmEnvelope" }
    MediaEvent:
      name: MediaEvent
      title: Media library namespace event (RTM-only)
      payload: { $ref: "#/components/schemas/RtmEnvelope" }
    EmailEvent:
      name: EmailEvent
      title: Email namespace event
      payload: { $ref: "#/components/schemas/RtmEnvelope" }
    PluginEvent:
      name: PluginEvent
      title: Plugin namespace event
      payload: { $ref: "#/components/schemas/RtmEnvelope" }
    PlanEvent:
      name: PlanEvent
      title: Plan namespace event
      payload: { $ref: "#/components/schemas/RtmEnvelope" }

  schemas:
    WebhookEnvelope:
      type: object
      required: [website_id, event, data, timestamp]
      properties:
        website_id:
          type: string
          description: Crisp website identifier the event belongs to.
        event:
          type: string
          description: Exact event name (e.g. `message:send`).
          enum:
            - session:update_availability
            - session:update_verify
            - session:request:initiated
            - session:set_email
            - session:set_phone
            - session:set_address
            - session:set_subject
            - session:set_avatar
            - session:set_nickname
            - session:set_origin
            - session:set_data
            - session:set_segments
            - session:set_block
            - session:set_opened
            - session:set_closed
            - session:set_participants
            - session:set_mentions
            - session:set_routing
            - session:set_inbox
            - session:set_state
            - session:sync:capabilities
            - session:sync:geolocation
            - session:sync:system
            - session:sync:network
            - session:sync:timezone
            - session:sync:locales
            - session:sync:pages
            - session:sync:events
            - session:sync:rating
            - session:sync:topic
            - session:removed
            - session:error
            - message:updated
            - message:send
            - message:received
            - message:removed
            - message:compose:send
            - message:compose:receive
            - message:acknowledge:read:send
            - message:acknowledge:read:received
            - message:acknowledge:unread:send
            - message:acknowledge:delivered
            - message:acknowledge:ignored
            - message:notify:unread:send
            - message:notify:unread:received
            - people:profile:created
            - people:profile:updated
            - people:profile:removed
            - people:bind:session
            - people:sync:profile
            - campaign:progress
            - campaign:dispatched
            - campaign:running
            - browsing:request:initiated
            - browsing:request:rejected
            - call:request:initiated
            - call:request:rejected
            - identity:verify:request
            - status:health:changed
            - website:update_visitors_count
            - website:update_operators_availability
            - website:users:available
            - bucket:url:upload:generated
            - bucket:url:avatar:generated
            - bucket:url:website:generated
            - bucket:url:campaign:generated
            - bucket:url:helpdesk:generated
            - bucket:url:status:generated
            - bucket:url:processing:generated
            - email:subscribe
            - email:track:view
            - plugin:channel
            - plugin:event
            - plugin:subscription:updated
            - plugin:settings:saved
            - plan:subscription:updated
        data:
          type: object
          description: Event-specific payload. Shape varies per `event`.
          additionalProperties: true
        timestamp:
          type: integer
          format: int64
          description: UNIX timestamp (milliseconds) at emission.

    RtmEnvelope:
      type: object
      description: |
        Generic envelope used by every RTM event. Mirrors the Web Hooks
        body but is emitted over Socket.IO. Per-event `data` shapes are
        documented at https://docs.crisp.chat/references/rtm-api/v1/.
      required: [website_id, data]
      properties:
        website_id: { type: string }
        data:
          type: object
          additionalProperties: true
        timestamp:
          type: integer
          format: int64

    AuthenticationPayload:
      type: object
      required: [tier, username, password]
      properties:
        tier:
          type: string
          enum: [plugin, user]
          description: Token tier (matches the REST `X-Crisp-Tier` value).
        username:
          type: string
          description: Token identifier.
        password:
          type: string
          format: password
          description: Token key.
        events:
          type: array
          description: Optional event-name filter list to subscribe to.
          items: { type: string }