openapi: 3.1.0
info:
  title: Quub Exchange - Escrow API
  version: 2.0.0
  license:
    name: Proprietary
    url: https://quub.exchange/license
  description: "Escrow account management and milestone-based fund release.


    **Escrow Types:**

    - Two-party escrow (buyer/seller)

    - Three-party escrow (with agent)

    - Multi-party escrow (multiple beneficiaries)

    - Milestone escrow (conditional release)


    **Release Conditions:**

    - Manual approval

    - Milestone completion

    - Time-based

    - Multi-signature

    - Smart contract triggered

    "
servers:
  - url: https://api.quub.exchange/v1
    description: Production API
tags:
  - name: Escrow Accounts
    description: Escrow account management
  - name: Deposits
    description: Deposit funds into escrow
  - name: Release
    description: Release funds from escrow
  - name: Disputes
    description: Dispute resolution
paths:
  /orgs/{orgId}/escrow/accounts:
    get:
      operationId: listEscrowAccounts
      summary: List escrow accounts
      tags:
        - Escrow Accounts
      security:
        - oauth2:
            - read:escrow
        - apiKey: []
      parameters:
        - $ref: ./common/components.yaml#/components/parameters/orgId
        - $ref: ./common/components.yaml#/components/parameters/orgIdHeader
        - $ref: ./common/pagination.yaml#/components/parameters/cursor
        - $ref: ./common/pagination.yaml#/components/parameters/limit
      responses:
        "400":
          $ref: ./common/responses.yaml#/components/responses/BadRequest
        "401":
          $ref: ./common/responses.yaml#/components/responses/Unauthorized
        "500":
          $ref: ./common/responses.yaml#/components/responses/InternalServerError
        "200":
          description: List of escrow accounts
          content:
            application/json:
              schema:
                allOf:
                  - $ref: ./common/pagination.yaml#/components/schemas/PageResponse
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: "#/components/schemas/EscrowAccount"
        "403":
          $ref: ./common/responses.yaml#/components/responses/Forbidden
    post:
      operationId: createEscrowAccount
      summary: Create escrow account
      tags:
        - Escrow Accounts
      security:
        - oauth2:
            - write:escrow
        - apiKey: []
      parameters:
        - $ref: ./common/components.yaml#/components/parameters/orgId
        - $ref: ./common/components.yaml#/components/parameters/orgIdHeader
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateEscrowRequest"
      responses:
        "400":
          $ref: ./common/responses.yaml#/components/responses/BadRequest
        "401":
          $ref: ./common/responses.yaml#/components/responses/Unauthorized
        "500":
          $ref: ./common/responses.yaml#/components/responses/InternalServerError
        "201":
          description: Escrow account created successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/EscrowAccount"
        "403":
          $ref: ./common/responses.yaml#/components/responses/Forbidden
  /orgs/{orgId}/escrow/accounts/{escrowId}:
    get:
      operationId: getEscrowAccount
      summary: Get escrow account details
      tags:
        - Escrow Accounts
      security:
        - oauth2:
            - read:escrow
        - apiKey: []
      parameters:
        - $ref: ./common/components.yaml#/components/parameters/orgId
        - $ref: ./common/components.yaml#/components/parameters/orgIdHeader
        - name: escrowId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "400":
          $ref: ./common/responses.yaml#/components/responses/BadRequest
        "401":
          $ref: ./common/responses.yaml#/components/responses/Unauthorized
        "500":
          $ref: ./common/responses.yaml#/components/responses/InternalServerError
        "200":
          description: Escrow account details
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/EscrowAccount"
        "403":
          $ref: ./common/responses.yaml#/components/responses/Forbidden
  /orgs/{orgId}/escrow/accounts/{escrowId}/deposit:
    post:
      operationId: depositToEscrow
      summary: Deposit funds into escrow
      tags:
        - Deposits
      security:
        - oauth2:
            - write:escrow
        - apiKey: []
      parameters:
        - $ref: ./common/components.yaml#/components/parameters/orgId
        - $ref: ./common/components.yaml#/components/parameters/orgIdHeader
        - name: escrowId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - amount
                - currency
              properties:
                amount:
                  type: string
                currency:
                  type: string
      responses:
        "400":
          $ref: ./common/responses.yaml#/components/responses/BadRequest
        "401":
          $ref: ./common/responses.yaml#/components/responses/Unauthorized
        "500":
          $ref: ./common/responses.yaml#/components/responses/InternalServerError
        "201":
          description: Deposit to escrow successful
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/EscrowAccount"
        "403":
          $ref: ./common/responses.yaml#/components/responses/Forbidden
  /orgs/{orgId}/escrow/accounts/{escrowId}/deposit-crypto:
    post:
      operationId: depositCryptoToEscrow
      summary: Deposit crypto funds to escrow
      tags:
        - Deposits
      security:
        - oauth2:
            - write:escrow
        - apiKey: []
      parameters:
        - $ref: ./common/components.yaml#/components/parameters/orgId
        - $ref: ./common/components.yaml#/components/parameters/orgIdHeader
        - name: escrowId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - walletId
                - amount
                - txHash
              properties:
                walletId:
                  type: string
                  format: uuid
                  description: Source wallet ID from chain service
                amount:
                  type: string
                  description: Amount to deposit in base units
                tokenAddress:
                  type: string
                  description: ERC-20 token contract address (if applicable)
                txHash:
                  type: string
                  description: Blockchain transaction hash
      responses:
        "400":
          $ref: ./common/responses.yaml#/components/responses/BadRequest
        "401":
          $ref: ./common/responses.yaml#/components/responses/Unauthorized
        "500":
          $ref: ./common/responses.yaml#/components/responses/InternalServerError
        "201":
          description: Crypto deposit to escrow successful
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/EscrowAccount"
        "403":
          $ref: ./common/responses.yaml#/components/responses/Forbidden
  /orgs/{orgId}/escrow/accounts/{escrowId}/release:
    post:
      operationId: releaseFromEscrow
      summary: Release funds from escrow
      tags:
        - Release
      security:
        - oauth2:
            - write:escrow
        - apiKey: []
      parameters:
        - $ref: ./common/components.yaml#/components/parameters/orgId
        - $ref: ./common/components.yaml#/components/parameters/orgIdHeader
        - name: escrowId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - amount
                - beneficiary
              properties:
                amount:
                  type: string
                beneficiary:
                  type: string
                  format: uuid
                reason:
                  type: string
      responses:
        "400":
          $ref: ./common/responses.yaml#/components/responses/BadRequest
        "401":
          $ref: ./common/responses.yaml#/components/responses/Unauthorized
        "500":
          $ref: ./common/responses.yaml#/components/responses/InternalServerError
        "201":
          description: Release from escrow successful
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/EscrowAccount"
        "403":
          $ref: ./common/responses.yaml#/components/responses/Forbidden
  /orgs/{orgId}/escrow/accounts/{escrowId}/release-crypto:
    post:
      operationId: releaseCryptoFromEscrow
      summary: Release crypto funds from escrow
      tags:
        - Release
      security:
        - oauth2:
            - write:escrow
        - apiKey: []
      parameters:
        - $ref: ./common/components.yaml#/components/parameters/orgId
        - $ref: ./common/components.yaml#/components/parameters/orgIdHeader
        - name: escrowId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - beneficiaryWalletId
                - amount
                - txHash
              properties:
                beneficiaryWalletId:
                  type: string
                  format: uuid
                  description: Destination wallet ID from chain service
                amount:
                  type: string
                  description: Amount to release in base units
                tokenAddress:
                  type: string
                  description: ERC-20 token contract address (if applicable)
                reason:
                  type: string
                txHash:
                  type: string
                  description: Blockchain transaction hash
      responses:
        "400":
          $ref: ./common/responses.yaml#/components/responses/BadRequest
        "401":
          $ref: ./common/responses.yaml#/components/responses/Unauthorized
        "500":
          $ref: ./common/responses.yaml#/components/responses/InternalServerError
        "201":
          description: Crypto release from escrow successful
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/EscrowAccount"
        "403":
          $ref: ./common/responses.yaml#/components/responses/Forbidden
  /orgs/{orgId}/escrow/accounts/{escrowId}/milestones:
    get:
      operationId: listMilestones
      summary: List milestones
      tags:
        - Release
      security:
        - oauth2:
            - read:escrow
        - apiKey: []
      parameters:
        - $ref: ./common/components.yaml#/components/parameters/orgId
        - $ref: ./common/components.yaml#/components/parameters/orgIdHeader
        - $ref: ./common/pagination.yaml#/components/parameters/cursor
        - $ref: ./common/pagination.yaml#/components/parameters/limit
        - name: escrowId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "400":
          $ref: ./common/responses.yaml#/components/responses/BadRequest
        "401":
          $ref: ./common/responses.yaml#/components/responses/Unauthorized
        "404":
          $ref: ./common/responses.yaml#/components/responses/NotFound
        "500":
          $ref: ./common/responses.yaml#/components/responses/InternalServerError
        "200":
          description: List of milestones
          content:
            application/json:
              schema:
                allOf:
                  - $ref: ./common/pagination.yaml#/components/schemas/PageResponse
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: "#/components/schemas/Milestone"
        "403":
          $ref: ./common/responses.yaml#/components/responses/Forbidden
  /orgs/{orgId}/escrow/accounts/{escrowId}/disputes:
    post:
      operationId: openDispute
      summary: Open dispute
      tags:
        - Disputes
      security:
        - oauth2:
            - write:escrow
        - apiKey: []
      parameters:
        - $ref: ./common/components.yaml#/components/parameters/orgId
        - $ref: ./common/components.yaml#/components/parameters/orgIdHeader
        - name: escrowId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - reason
              properties:
                reason:
                  type: string
                evidence:
                  type: array
                  items:
                    type: string
      responses:
        "400":
          $ref: ./common/responses.yaml#/components/responses/BadRequest
        "401":
          $ref: ./common/responses.yaml#/components/responses/Unauthorized
        "403":
          $ref: ./common/responses.yaml#/components/responses/Forbidden
        "409":
          $ref: ./common/responses.yaml#/components/responses/Conflict
        "422":
          $ref: ./common/responses.yaml#/components/responses/ValidationError
        "429":
          $ref: ./common/responses.yaml#/components/responses/TooManyRequests
        "500":
          $ref: ./common/responses.yaml#/components/responses/InternalServerError
        "201":
          description: Dispute opened successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/EscrowAccount"
components:
  securitySchemes:
    bearerAuth:
      $ref: ./common/components.yaml#/components/securitySchemes/bearerAuth
    oauth2:
      $ref: ./common/components.yaml#/components/securitySchemes/oauth2
    apiKey:
      $ref: ./common/components.yaml#/components/securitySchemes/apiKey
  schemas:
    EscrowAccount:
      type: object
      properties:
        id:
          type: string
          format: uuid
        orgId:
          type: string
          format: uuid
        escrowType:
          type: string
          enum:
            - TWO_PARTY
            - THREE_PARTY
            - MULTI_PARTY
            - MILESTONE
        accountType:
          type: string
          enum:
            - FIAT
            - CRYPTO
          description: Type of escrow account (fiat or cryptocurrency)
        balance:
          type: string
        currency:
          type: string
        # Crypto-specific fields
        walletId:
          type: string
          format: uuid
          description: Associated wallet ID for crypto escrow (from chain service)
        chainId:
          type: string
          description: Blockchain identifier (e.g., ethereum, polygon, solana)
        contractAddress:
          type: string
          description: Smart contract address for crypto escrow
        tokenAddress:
          type: string
          description: ERC-20 token contract address (if applicable)
        status:
          type: string
          enum:
            - PENDING
            - ACTIVE
            - RELEASED
            - DISPUTED
            - CLOSED
        parties:
          type: array
          items:
            type: object
            properties:
              accountId:
                type: string
                format: uuid
              role:
                type: string
                enum:
                  - DEPOSITOR
                  - BENEFICIARY
                  - AGENT
        releaseConditions:
          type: object
        createdAt:
          type: string
          format: date-time
    CreateEscrowRequest:
      type: object
      required:
        - escrowType
        - currency
      properties:
        escrowType:
          type: string
          enum:
            - TWO_PARTY
            - THREE_PARTY
            - MULTI_PARTY
            - MILESTONE
        currency:
          type: string
        parties:
          type: array
          items:
            type: object
            properties:
              accountId:
                type: string
                format: uuid
              role:
                type: string
                enum:
                  - DEPOSITOR
                  - BENEFICIARY
                  - AGENT
    Milestone:
      type: object
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
        description:
          type: string
        releaseAmount:
          type: string
        status:
          type: string
          enum:
            - PENDING
            - COMPLETED
            - FAILED
        dueDate:
          type: string
          format: date
        completedAt:
          type: string
          format: date-time
