asyncapi: '3.0.0'
info:
  title: Bitvavo Request for Quote WebSocket API
  version: 1.5.0
  description: |
    WebSocket API for market makers participating in the Bitvavo Request for Quote (RFQ) platform.

    Once you [authenticate the session](/docs/rfq-websocket-api/introduction/#authentication), you can subscribe to RFQ requests and submit firm quotes on this connection.

servers:
  rfq_prod_primary:
    host: connection.bitvavo.com:8004
    pathname: /rfq/v1
    protocol: wss
    description: Primary production RFQ Maker WebSocket endpoint.
    security:
      - $ref: '#/components/securitySchemes/hmacSha256'
  rfq_prod_secondary:
    host: connection.bitvavo.com:9004
    pathname: /rfq/v1
    protocol: wss
    description: Secondary production RFQ Maker WebSocket endpoint for failover.
    security:
      - $ref: '#/components/securitySchemes/hmacSha256'
  rfq_uat_primary:
    host: connection.bitvavo-uat.com:8004
    pathname: /rfq/v1
    protocol: wss
    description: Primary UAT RFQ Maker WebSocket endpoint.
    security:
      - $ref: '#/components/securitySchemes/hmacSha256'
  rfq_uat_secondary:
    host: connection.bitvavo-uat.com:9004
    pathname: /rfq/v1
    protocol: wss
    description: Secondary UAT RFQ Maker WebSocket endpoint for failover.
    security:
      - $ref: '#/components/securitySchemes/hmacSha256'

defaultContentType: application/json

channels:

  authenticate:
    messages:
      AuthenticateAction:
        $ref: '#/components/messages/AuthenticateAction'
  authenticateReply:
    messages:
      AuthenticatedEvent:
        $ref: '#/components/messages/AuthenticatedEvent'
      ErrorEvent:
        $ref: '#/components/messages/ErrorEvent'

  subscribeToRfqRequests:
    messages:
      SubscribeAction:
        $ref: '#/components/messages/SubscribeAction'
  subscribeToRfqRequestsReply:
    messages:
      SubscribedEvent:
        $ref: '#/components/messages/SubscribedEvent'
      RfqRequestEvent:
        $ref: '#/components/messages/RfqRequestEvent'
      RfqTerminationEvent:
        $ref: '#/components/messages/RfqTerminationEvent'
      ErrorEvent:
        $ref: '#/components/messages/ErrorEvent'

  unsubscribeFromRfqRequests:
    messages:
      UnsubscribeAction:
        $ref: '#/components/messages/UnsubscribeAction'
  unsubscribeFromRfqRequestsReply:
    messages:
      UnsubscribedEvent:
        $ref: '#/components/messages/UnsubscribedEvent'
      ErrorEvent:
        $ref: '#/components/messages/ErrorEvent'

  sendNewFirmQuote:
    messages:
      NewFirmQuoteAction:
        $ref: '#/components/messages/NewFirmQuoteAction'
  sendNewFirmQuoteReply:
    messages:
      QuoteAckEvent:
        $ref: '#/components/messages/QuoteAckEvent'
      QuoteNackEvent:
        $ref: '#/components/messages/QuoteNackEvent'
      RfqTradeEvent:
        $ref: '#/components/messages/RfqTradeEvent'

operations:

  authenticate:
    action: send
    channel:
      $ref: '#/channels/authenticate'
    summary: Authenticate session
    description: |
      Authenticates the WebSocket session so that you can subscribe to RFQ channels and submit firm quotes.

      Before you send the `authenticate` action, you must create the signature. To learn how, see [Step 1: Create a signature](/docs/rfq-websocket-api/introduction/#create-a-signature).
    tags:
      - name: Actions
    reply:
      channel:
        $ref: '#/channels/authenticateReply'

  subscribeToRfqRequests:
    action: send
    channel:
      $ref: '#/channels/subscribeToRfqRequests'
    summary: Subscribe to RFQ requests
    description: |
      Subscribes to `rfqRequest` and `rfqTermination` events for the specified `rfqTypes`. Once subscribed, the server sends events whenever a taker starts, refreshes, or ends an RFQ session that matches your subscription.
    tags:
      - name: Channels
    security:
      - $ref: '#/components/securitySchemes/hmacSha256'
    reply:
      channel:
        $ref: '#/channels/subscribeToRfqRequestsReply'

  unsubscribeFromRfqRequests:
    action: send
    channel:
      $ref: '#/channels/unsubscribeFromRfqRequests'
    summary: Unsubscribe from RFQ requests
    description: |
      Unsubscribes from `rfqRequest` and `rfqTermination` events for the specified `rfqTypes`.
    
      RFQ sessions that you are already participating in continue to their final state, so you may still receive `rfqTermination` events for those sessions.
    tags:
      - name: Channels
    security:
      - $ref: '#/components/securitySchemes/hmacSha256'
    reply:
      channel:
        $ref: '#/channels/unsubscribeFromRfqRequestsReply'

  sendNewFirmQuote:
    action: send
    channel:
      $ref: '#/channels/sendNewFirmQuote'
    summary: Submit firm quote
    description: |
      Submits a firm quote during the collection window of an active RFQ cycle. Quotes that arrive after the window closes are rejected with `collectionMiss`.
    tags:
      - name: Actions
    security:
      - $ref: '#/components/securitySchemes/hmacSha256'
    reply:
      channel:
        $ref: '#/channels/sendNewFirmQuoteReply'

components:
  schemas:
    RequestId:
      type: integer
      format: int64
      description: |
        An identifier that you assign to the request. The server echoes it back in the matching response so you can correlate the two.
      examples:
        - 9021001

    TimestampMs:
      type: integer
      format: int64
      description: A Unix timestamp in milliseconds.
      examples:
        - 1739462400123

    RfqId:
      type: integer
      format: int64
      description: The unique identifier of the RFQ session.
      examples:
        - 840001234567

    RfqCycleId:
      type: integer
      format: int32
      description: |
        The identifier of the current cycle within the RFQ session. A cycle is one round of quote collection. It begins when the taker starts or refreshes the RFQ session, and ends when the collection window closes.

        The value starts at 0 for the first cycle, and increases by 1 each time the taker refreshes the RFQ.
      examples:
        - 2

    ClientQuoteId:
      type: string
      format: uuid
      description: |
        A unique identifier (UUID) that you assign to the quote. Used for tracing only.
      examples:
        - 5d8f2ab0-09d0-4f11-8b4a-3f8ea4c4a5cb

    QuoteId:
      type: integer
      format: int64
      description: The internal identifier of the quote, assigned by Bitvavo. Used for tracing and reporting.
      examples:
        - 90011223344

    TradeId:
      type: integer
      format: int64
      description: The unique identifier of the resulting trade.
      examples:
        - 778899001

    OperatorId:
      type: integer
      format: int64
      description: The numeric identifier of the operator.
      examples:
        - 12345

    MakerFeeBps:
      type: string
      description: The maker fee in basis points.
      examples:
        - '80.0'

    Asset:
      type: string
      description: The code of the asset (for example, `BTC` or `EUR`).
      examples:
        - BTC

    AmountType:
      type: string
      enum: [BASE, QUOTE]
      description: |
        The asset in which `amount` is denominated. Possible values:

        - `BASE` — `amount` is denominated in the base asset.
        - `QUOTE` — `amount` is denominated in the quote asset.
      examples:
        - BASE

    Side:
      type: string
      enum: [BUY, SELL]
      description: |
        The side of the trade from the perspective of the taker. Possible values:

        - `BUY` — the taker buys the base asset.
        - `SELL` — the taker sells the base asset.
      examples:
        - BUY

    RfqType:
      type: string
      enum: [priceGuarantee, priceGuaranteeUK, priceGuaranteeConvert]
      description: |
        The type of the RFQ. Possible values:

        - `priceGuarantee` — the standard Price Guarantee RFQ for spot markets.
        - `priceGuaranteeUK` — the Price Guarantee RFQ variant for United Kingdom customers.
        - `priceGuaranteeConvert` — the Price Guarantee RFQ variant used for asset-to-asset conversions (the Convert product).
      examples:
        - priceGuarantee

    SubscriptionChannel:
      type: object
      additionalProperties: false
      required: [name, rfqTypes]
      properties:
        name:
          type: string
          enum: [rfqRequests]
          description: The name of the channel. Currently, `rfqRequests` is the only available channel. It streams `rfqRequest` and `rfqTermination` events.
        rfqTypes:
          type: array
          description: |
            The types of RFQ requests to subscribe to. Possible values:

            - `priceGuarantee` — the standard Price Guarantee RFQ for spot markets.
            - `priceGuaranteeUK` — the Price Guarantee RFQ variant for United Kingdom customers.
            - `priceGuaranteeConvert` — the Price Guarantee RFQ variant used for asset-to-asset conversions (the Convert product).
          items:
            $ref: '#/components/schemas/RfqType'
      examples:
        - name: rfqRequests
          rfqTypes:
            - priceGuarantee

    SubscriptionState:
      type: object
      description: The subscriptions that are currently active on your session, grouped by channel.
      additionalProperties: false
      required:
        - rfqRequests
      properties:
        rfqRequests:
          type: array
          description: |
            The RFQ types that are currently active on the `rfqRequests` channel. Possible values:

            - `priceGuarantee` — the standard Price Guarantee RFQ for spot markets.
            - `priceGuaranteeUK` — the Price Guarantee RFQ variant for United Kingdom customers.
            - `priceGuaranteeConvert` — the Price Guarantee RFQ variant used for asset-to-asset conversions (the Convert product).
          items:
            $ref: '#/components/schemas/RfqType'

    AuthenticateActionPayload:
      type: object
      additionalProperties: false
      required: [action, key, signature, timestamp]
      properties:
        action:
          type: string
          enum: [authenticate]
          example: authenticate
          description: Set to `authenticate` to start the session.
        requestId:
          $ref: '#/components/schemas/RequestId'
        key:
          type: string
          description: Your Bitvavo API key.
          examples:
            - bva_uat_maker_7f3a2c1d
        signature:
          type: string
          description: The HMAC-SHA256 hex-encoded signature over the string `<timestamp>GET/rfq/v1`, computed with your API secret.
          examples:
            - 118067f093bef0f7b99bbc2a967a000fa288226d24b5c8ebc10e9cfb4229a6fa
        timestamp:
          $ref: '#/components/schemas/TimestampMs'
        window:
          type: integer
          description: The time in milliseconds in which your request is allowed to execute. Default 10000, maximum 60000.
          minimum: 1
          maximum: 60000
          examples:
            - 10000
      examples:
        - action: authenticate
          requestId: 9021001
          key: bva_uat_maker_7f3a2c1d
          signature: 118067f093bef0f7b99bbc2a967a000fa288226d24b5c8ebc10e9cfb4229a6fa
          timestamp: 1739462400123
          window: 10000

    AuthenticatedEventPayload:
      type: object
      additionalProperties: false
      required: [event, authenticated]
      properties:
        event:
          type: string
          enum: [authenticate]
          example: authenticate
          description: Confirmation that the server accepted the authentication.
        requestId:
          $ref: '#/components/schemas/RequestId'
        authenticated:
          type: boolean
          description: Indicates whether the session is now authenticated.
          examples:
            - true
      examples:
        - event: authenticate
          requestId: 9021001
          authenticated: true

    SubscribeActionPayload:
      type: object
      additionalProperties: false
      required: [action, channels]
      properties:
        action:
          type: string
          enum: [subscribe]
          example: subscribe
          description: Set to `subscribe` to start the subscription.
        requestId:
          $ref: '#/components/schemas/RequestId'
        channels:
          type: array
          description: The channels to subscribe to.
          items:
            $ref: '#/components/schemas/SubscriptionChannel'
      examples:
        - action: subscribe
          requestId: 9021002
          channels:
            - name: rfqRequests
              rfqTypes:
                - priceGuarantee
                - priceGuaranteeConvert

    UnsubscribeActionPayload:
      type: object
      additionalProperties: false
      required: [action, channels]
      properties:
        action:
          type: string
          enum: [unsubscribe]
          example: unsubscribe
          description: Set to `unsubscribe` to end the subscription.
        requestId:
          $ref: '#/components/schemas/RequestId'
        channels:
          type: array
          description: The channels to unsubscribe from.
          items:
            $ref: '#/components/schemas/SubscriptionChannel'
      examples:
        - action: unsubscribe
          requestId: 9021003
          channels:
            - name: rfqRequests
              rfqTypes:
                - priceGuarantee

    NewFirmQuoteActionPayload:
      type: object
      additionalProperties: false
      required:
        - action
        - rfqId
        - rfqCycleId
        - clientQuoteId
        - price
      properties:
        action:
          type: string
          enum: [ firmQuote ]
          example: firmQuote
          description: Set to `firmQuote` to submit a firm quote.
        requestId:
          $ref: '#/components/schemas/RequestId'
        rfqId:
          $ref: '#/components/schemas/RfqId'
        rfqCycleId:
          $ref: '#/components/schemas/RfqCycleId'
        clientQuoteId:
          $ref: '#/components/schemas/ClientQuoteId'
        price:
          type: string
          description: The price per unit of the base asset in the quote currency, with your spread included.
          examples:
            - '41280.55'
        operatorId:
          $ref: '#/components/schemas/OperatorId'
      examples:
        - action: firmQuote
          requestId: 9021004
          rfqId: 840001234567
          rfqCycleId: 2
          clientQuoteId: 5d8f2ab0-09d0-4f11-8b4a-3f8ea4c4a5cb
          price: '41280.55'
          operatorId: 12345

    SubscribedEventPayload:
      type: object
      additionalProperties: false
      required: [event, subscriptions]
      properties:
        event:
          type: string
          enum: [subscribed]
          example: subscribed
          description: Confirmation that the server accepted the subscription, together with the list of subscriptions that are active for your session.
        requestId:
          $ref: '#/components/schemas/RequestId'
        subscriptions:
          $ref: '#/components/schemas/SubscriptionState'
      examples:
        - event: subscribed
          subscriptions:
            rfqRequests:
              - priceGuarantee
              - priceGuaranteeConvert

    UnsubscribedEventPayload:
      type: object
      additionalProperties: false
      required: [event, subscriptions]
      properties:
        event:
          type: string
          enum: [unsubscribed]
          example: unsubscribed
          description: Confirmation that the server accepted the unsubscription, together with the list of subscriptions that remain active for your session.
        requestId:
          $ref: '#/components/schemas/RequestId'
        subscriptions:
          $ref: '#/components/schemas/SubscriptionState'
      examples:
        - event: unsubscribed
          subscriptions:
            rfqRequests:
              - priceGuarantee

    ErrorEventPayload:
      type: object
      additionalProperties: false
      required: [event, errorCode, error]
      properties:
        action:
          type: string
          description: The action that caused the error, if applicable.
          examples:
            - subscribe
        event:
          type: string
          enum: [error]
          example: error
          description: The details of an error returned by the server.
        errorCode:
          type: integer
          description: The Bitvavo error code.
          examples:
            - 320
        error:
          type: string
          description: A human-readable description of the error.
          examples:
            - RFQ maker access required. Contact Bitvavo to enable RFQ participation.
        requestId:
          $ref: '#/components/schemas/RequestId'
        operatorId:
          $ref: '#/components/schemas/OperatorId'
      examples:
        - action: subscribe
          event: error
          errorCode: 320
          error: RFQ maker access required. Contact Bitvavo to enable RFQ participation.

    RfqRequestEventPayload:
      type: object
      additionalProperties: false
      required:
        - event
        - rfqId
        - rfqCycleId
        - rfqType
        - base
        - quote
        - takerSide
        - amountType
        - amount
        - requestedFirmMs
        - expiresAfterMs
        - makerFeeBps
        - feeCurrency
        - timestamp
        - collectionWindowMs
      properties:
        event:
          type: string
          enum: [rfqRequest]
          example: rfqRequest
          description: The details of a new RFQ session, or a refresh of an active session. Includes `base`, `quote`, `takerSide`, `amount`, and `collectionWindowMs`.
        rfqId:
          $ref: '#/components/schemas/RfqId'
        rfqCycleId:
          $ref: '#/components/schemas/RfqCycleId'
        rfqType:
          $ref: '#/components/schemas/RfqType'
        base:
          $ref: '#/components/schemas/Asset'
        quote:
          $ref: '#/components/schemas/Asset'
        takerSide:
          $ref: '#/components/schemas/Side'
        amountType:
          $ref: '#/components/schemas/AmountType'
        amount:
          type: string
          description: The amount you trade against, denominated in the asset indicated by `amountType`.
          examples:
            - '0.25000000'
        requestedFirmMs:
          type: integer
          format: int64
          description: |
            The duration in milliseconds for which the taker requests the quote to remain firm. Measured from the `timestamp` in this message. For Price Guarantee, the value is 5000 ms.
          examples:
            - 5000
        expiresAfterMs:
          type: integer
          format: int64
          description: |
            The time in milliseconds during which the RFQ remains valid after `requestedFirmMs` ends. The RFQ expires only if no refresh arrives within `requestedFirmMs + expiresAfterMs` after `timestamp`. For Price Guarantee, the value is typically <= 5000 ms.
          examples:
            - 5000
        collectionWindowMs:
          type: integer
          format: int32
          description: |
            The duration of the collection window in milliseconds for this cycle. Submit your firm quote before the window closes. For Price Guarantee, the value is 100 ms.
          examples:
            - 100
        makerFeeBps:
          $ref: '#/components/schemas/MakerFeeBps'
        feeCurrency:
          $ref: '#/components/schemas/Asset'
        timestamp:
          $ref: '#/components/schemas/TimestampMs'
      examples:
        - event: rfqRequest
          rfqId: 840001234567
          rfqCycleId: 2
          rfqType: priceGuarantee
          base: BTC
          quote: EUR
          takerSide: BUY
          amountType: BASE
          amount: '0.25000000'
          requestedFirmMs: 5000
          expiresAfterMs: 5000
          collectionWindowMs: 100
          makerFeeBps: '80.0'
          feeCurrency: EUR
          timestamp: 1739462400200

    QuoteAckEventPayload:
      type: object
      additionalProperties: false
      required: [event, rfqId, rfqCycleId, clientQuoteId, quoteId, timestamp]
      properties:
        event:
          type: string
          enum: [quoteAck]
          example: quoteAck
          description: The quote entered the competition, and you are now a participant in the RFQ session.
        rfqId:
          $ref: '#/components/schemas/RfqId'
        rfqCycleId:
          $ref: '#/components/schemas/RfqCycleId'
        clientQuoteId:
          $ref: '#/components/schemas/ClientQuoteId'
        quoteId:
          $ref: '#/components/schemas/QuoteId'
        timestamp:
          $ref: '#/components/schemas/TimestampMs'
        operatorId:
          $ref: '#/components/schemas/OperatorId'
        requestId:
          $ref: '#/components/schemas/RequestId'
      examples:
        - event: quoteAck
          rfqId: 840001234567
          rfqCycleId: 2
          clientQuoteId: 5d8f2ab0-09d0-4f11-8b4a-3f8ea4c4a5cb
          quoteId: 90011223344
          timestamp: 1739462400255

    QuoteNackEventPayload:
      type: object
      additionalProperties: false
      required: [event, rfqId, rfqCycleId, clientQuoteId, reason, timestamp]
      properties:
        event:
          type: string
          enum: [quoteNack]
          example: quoteNack
          description: The quote was rejected. The response includes a `reason`.
        rfqId:
          $ref: '#/components/schemas/RfqId'
        rfqCycleId:
          $ref: '#/components/schemas/RfqCycleId'
        clientQuoteId:
          $ref: '#/components/schemas/ClientQuoteId'
        reason:
          type: string
          enum: [unknownRfq, invalidPrice, invalidQuoteAmount, insufficientFunds, collectionMiss, quoteTooWide]
          description: |
            The reason for the rejection. Possible values:

            - `unknownRfq` — the `rfqId` or `rfqCycleId` does not match an active RFQ session or cycle.
            - `invalidPrice` — the value of `price` is malformed or outside the acceptable limits.
            - `invalidQuoteAmount` — the amount in the quote currency, derived from `price` and `amount`, is malformed or outside the acceptable limits.
            - `insufficientFunds` — you do not have enough balance to back the quote.
            - `collectionMiss` — the quote arrived after the collection window closed.
            - `quoteTooWide` — the price of the quote is beyond the maximum spread allowed from the reference price.
          examples:
            - invalidPrice
        timestamp:
          $ref: '#/components/schemas/TimestampMs'
        operatorId:
          $ref: '#/components/schemas/OperatorId'
        requestId:
          $ref: '#/components/schemas/RequestId'
      examples:
        - event: quoteNack
          rfqId: 840001234567
          rfqCycleId: 2
          clientQuoteId: 5d8f2ab0-09d0-4f11-8b4a-3f8ea4c4a5cb
          reason: invalidPrice
          timestamp: 1739462400255

    RfqTerminationEventPayload:
      type: object
      description: |
        The value of `quoteId` is included only when your quote is accepted (`makerResult: traded`). It is omitted for the `lost`, `noTrade`, `makerSettlementFailed`, and `takerSettlementFailed` outcomes.
      additionalProperties: false
      required: [event, rfqId, rfqCycleId, rfqType, base, quote, rfqStatus, makerResult, timestamp]
      properties:
        event:
          type: string
          enum: [rfqTermination]
          example: rfqTermination
          description: The final outcome of the RFQ session, and your result as a maker. The server delays delivery so that the winning maker has time to hedge, and other participants cannot infer the outcome from the timing.
        rfqId:
          $ref: '#/components/schemas/RfqId'
        rfqCycleId:
          $ref: '#/components/schemas/RfqCycleId'
        rfqType:
          $ref: '#/components/schemas/RfqType'
        base:
          $ref: '#/components/schemas/Asset'
        quote:
          $ref: '#/components/schemas/Asset'
        quoteId:
          $ref: '#/components/schemas/QuoteId'
        rfqStatus:
          type: string
          enum: [completed, expired, error]
          description: |
            The final status of the RFQ session. Possible values:

            - `completed` — the RFQ completed, and the taker accepted a quote.
            - `expired` — the RFQ ended without an accepted quote. The taker neither accepted nor refreshed within `requestedFirmMs + expiresAfterMs`.
            - `error` — the RFQ ended in an unexpected error state.
          x-enum-descriptions:
            completed: The RFQ ran to conclusion and the taker accepted a quote.
            expired: The RFQ ended without an accepted quote. The taker neither accepted nor refreshed within `requestedFirmMs + expiresAfterMs`.
            error: The RFQ ended in an unexpected error state.
          examples:
            - completed
        makerResult:
          type: string
          enum: [traded, lost, noTrade, makerSettlementFailed, takerSettlementFailed]
          description: |
            Your outcome for this RFQ session. Possible values:

            - `traded` — your quote won, and the trade settled successfully.
            - `lost` — another maker submitted a better quote.
            - `noTrade` — no trade took place. Either the RFQ expired, or no quotes arrived during the collection window.
            - `makerSettlementFailed` — your quote won, but the settlement on your side failed.
            - `takerSettlementFailed` — your quote won, but the settlement on the taker side failed.
          x-enum-descriptions:
            traded: Your quote won and the trade settled successfully.
            lost: Another maker submitted a better quote.
            noTrade: No trade occurred (the RFQ expired or no quotes were received).
            makerSettlementFailed: Your quote won, but the settlement on your side failed.
            takerSettlementFailed: Your quote won, but the settlement on the taker side failed.
          examples:
            - lost
        timestamp:
          $ref: '#/components/schemas/TimestampMs'
      examples:
        - event: rfqTermination
          rfqId: 840001234567
          rfqCycleId: 2
          rfqType: priceGuarantee
          base: BTC
          quote: EUR
          rfqStatus: completed
          makerResult: lost
          timestamp: 1739462405400

    RfqTradeEventPayload:
      type: object
      additionalProperties: false
      required:
        - event
        - rfqId
        - rfqCycleId
        - rfqType
        - clientQuoteId
        - quoteId
        - tradeId
        - base
        - quote
        - takerSide
        - price
        - quantity
        - makerFeeBps
        - feeQuantity
        - quoteQuantity
        - feeCurrency
        - settled
        - timestamp
      properties:
        event:
          type: string
          enum: [rfqTrade]
          example: rfqTrade
          description: Your quote won — it had the best price and earliest arrival time, and the taker accepted it. You are the winning maker.
        rfqId:
          $ref: '#/components/schemas/RfqId'
        rfqCycleId:
          $ref: '#/components/schemas/RfqCycleId'
        rfqType:
          $ref: '#/components/schemas/RfqType'
        clientQuoteId:
          $ref: '#/components/schemas/ClientQuoteId'
        quoteId:
          $ref: '#/components/schemas/QuoteId'
        tradeId:
          $ref: '#/components/schemas/TradeId'
        base:
          $ref: '#/components/schemas/Asset'
        quote:
          $ref: '#/components/schemas/Asset'
        takerSide:
          $ref: '#/components/schemas/Side'
        price:
          type: string
          description: The price per unit of the base asset in the quote currency, as you quoted it. Used for settlement.
          examples:
            - '41280.55'
        quantity:
          type: string
          description: The settled amount, denominated in the base asset.
          examples:
            - '0.25000000'
        operatorId:
          $ref: '#/components/schemas/OperatorId'
        makerFeeBps:
          $ref: '#/components/schemas/MakerFeeBps'
        feeQuantity:
          type: string
          description: The settled fee amount, denominated in `feeCurrency`. May be rounded.
          examples:
            - '8.25611200'
        quoteQuantity:
          type: string
          description: The settled amount, denominated in the quote asset. May be rounded.
          examples:
            - '10320.13750000'
        feeCurrency:
          type: string
          description: The asset in which the fee is denominated.
          example: EUR
        settled:
          type: boolean
          description: Indicates whether the trade has been settled. Always `true` for Price Guarantee RFQ types.
          examples:
            - true
        timestamp:
          $ref: '#/components/schemas/TimestampMs'
      examples:
        - event: rfqTrade
          rfqId: 840001234567
          rfqCycleId: 2
          rfqType: priceGuarantee
          clientQuoteId: 5d8f2ab0-09d0-4f11-8b4a-3f8ea4c4a5cb
          quoteId: 90011223344
          tradeId: 778899001
          base: BTC
          quote: EUR
          takerSide: BUY
          price: '41280.55'
          quantity: '0.25000000'
          operatorId: 12345
          makerFeeBps: '80.0'
          feeQuantity: '8.25611200'
          quoteQuantity: '10320.13750000'
          feeCurrency: EUR
          settled: true
          timestamp: 1739462405520

  messages:
    AuthenticateAction:
      name: AuthenticateAction
      title: authenticate
      payload:
        $ref: '#/components/schemas/AuthenticateActionPayload'

    AuthenticatedEvent:
      name: AuthenticatedEvent
      title: authenticated
      payload:
        $ref: '#/components/schemas/AuthenticatedEventPayload'

    SubscribeAction:
      name: SubscribeAction
      title: subscribe
      payload:
        $ref: '#/components/schemas/SubscribeActionPayload'

    UnsubscribeAction:
      name: UnsubscribeAction
      title: unsubscribe
      payload:
        $ref: '#/components/schemas/UnsubscribeActionPayload'

    NewFirmQuoteAction:
      name: NewFirmQuoteAction
      title: new firm quote
      payload:
        $ref: '#/components/schemas/NewFirmQuoteActionPayload'

    SubscribedEvent:
      name: SubscribedEvent
      title: subscribed
      payload:
        $ref: '#/components/schemas/SubscribedEventPayload'

    UnsubscribedEvent:
      name: UnsubscribedEvent
      title: unsubscribed
      payload:
        $ref: '#/components/schemas/UnsubscribedEventPayload'

    ErrorEvent:
      name: ErrorEvent
      title: error
      payload:
        $ref: '#/components/schemas/ErrorEventPayload'

    RfqRequestEvent:
      name: RfqRequestEvent
      title: rfqRequest
      payload:
        $ref: '#/components/schemas/RfqRequestEventPayload'

    QuoteAckEvent:
      name: QuoteAckEvent
      title: quoteAck
      payload:
        $ref: '#/components/schemas/QuoteAckEventPayload'

    QuoteNackEvent:
      name: QuoteNackEvent
      title: quoteNack
      payload:
        $ref: '#/components/schemas/QuoteNackEventPayload'

    RfqTerminationEvent:
      name: RfqTerminationEvent
      title: rfqTermination
      payload:
        $ref: '#/components/schemas/RfqTerminationEventPayload'

    RfqTradeEvent:
      name: RfqTradeEvent
      title: rfqTrade
      payload:
        $ref: '#/components/schemas/RfqTradeEventPayload'

  securitySchemes:
    hmacSha256:
      type: symmetricEncryption
      description: |
        In-band authentication over the WebSocket connection. After you connect, you send an `authenticate` message. The value of `signature` is the HMAC-SHA256 of the string `<timestamp>GET/rfq/v1`, computed with your API secret.
      x-authMechanism: hmac-sha256
      x-authLocation: in-band-websocket
      x-signatureAlgorithm: HMAC-SHA256
      x-signatureBase: '<timestamp>GET/rfq/v1'
