openapi: 3.1.0
info:
  title: Otim Platform API
  version: v0
  description: API for managing accounts, entities, transfers, counterparties, and IBANs on the Otim platform.
servers:
  - url: https://api.otim.com/v0
security:
  - bearerAuth: []
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: API key prefixed with `sk_`.
  schemas:
    PaginatedAccounts:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Account'
        hasMore:
          type: boolean
        nextCursor:
          type: string
          nullable: true
    PaginatedEntities:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Entity'
        hasMore:
          type: boolean
        nextCursor:
          type: string
          nullable: true
    PaginatedTransfers:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Transfer'
        hasMore:
          type: boolean
        nextCursor:
          type: string
          nullable: true
    PaginatedCounterparties:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Counterparty'
        hasMore:
          type: boolean
        nextCursor:
          type: string
          nullable: true
    PaginatedIbans:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Iban'
        hasMore:
          type: boolean
        nextCursor:
          type: string
          nullable: true
    PlatformSettings:
      type: object
      properties:
        autoEarnEnabled:
          type: boolean
          description: When enabled, new Accounts are automatically configured to earn yield on idle balances.
          example: true
        autoEarnVault:
          type: string
          nullable: true
          description: The vault used for auto-earn. When auto-earn is enabled, idle balances in new Accounts are deposited into this vault.
          enum: [aave_usdc, morpho_usdc, sky_usds]
          example: "aave_usdc"
        defaultChain:
          type: string
          description: The default chain used when creating new Accounts.
          example: "base"
        webhookUrl:
          type: string
          nullable: true
          description: URL to receive webhook notifications for events on your Platform.
          example: "https://yourapp.com/webhooks/otim"
        updatedAt:
          type: string
          format: date-time
          example: "2025-01-15T12:00:00Z"
    UpdatePlatformSettingsRequest:
      type: object
      properties:
        autoEarnEnabled:
          type: boolean
          description: Enable or disable auto-earn for new Accounts.
        autoEarnVault:
          type: string
          description: The vault to use for auto-earn. Required when enabling auto-earn.
          enum: [aave_usdc, morpho_usdc, sky_usds]
        defaultChain:
          type: string
          description: Set the default chain for new Accounts.
          enum: [ethereum, base, arbitrum, optimism, polygon]
        webhookUrl:
          type: string
          nullable: true
          description: URL to receive webhook notifications. Set to `null` to disable.
    Account:
      type: object
      properties:
        id:
          type: string
          example: "acc_01JA1B2C3D4E5F6G7H8J9K0L"
        entityId:
          type: string
          example: "ent_01JA1B2C3D4E5F6G7H8J9K0L"
        name:
          type: string
          example: "Treasury"
        type:
          type: string
          enum: [wallet, bank]
          example: "wallet"
        chain:
          type: string
          nullable: true
          example: "base"
        availableBalance:
          type: string
          example: "1000000"
        pendingBalance:
          type: string
          example: "0"
        lockedBalance:
          type: string
          example: "0"
        holdingBalance:
          type: string
          example: "0"
        currency:
          type: string
          example: "USDC"
        status:
          type: string
          enum: [active, inactive]
          example: "active"
        autoEarn:
          type: boolean
          description: Whether this Account is earning yield on idle balances.
          example: true
        metadata:
          type: object
          nullable: true
        createdAt:
          type: string
          format: date-time
          example: "2025-01-15T12:00:00Z"
        updatedAt:
          type: string
          format: date-time
          example: "2025-01-15T12:00:00Z"
    CreateAccountRequest:
      type: object
      required: [entityId]
      properties:
        entityId:
          type: string
          description: The ID of the Entity to create the Account for.
        name:
          type: string
          description: A display name for the Account.
        metadata:
          type: object
          nullable: true
          description: Arbitrary key-value pairs to attach to the Account.
    CreateAccountResponse:
      type: object
      properties:
        id:
          type: string
          example: "acc_01JA1B2C3D4E5F6G7H8J9K0L"
        entityId:
          type: string
        name:
          type: string
          nullable: true
        type:
          type: string
          example: "wallet"
        chain:
          type: string
          example: "base"
        status:
          type: string
          example: "active"
        autoEarn:
          type: boolean
          description: Automatically set based on your Platform Settings.
          example: true
        availableBalance:
          type: string
          example: "0"
        currency:
          type: string
          example: "USDC"
        createdAt:
          type: string
          format: date-time
    Entity:
      type: object
      properties:
        id:
          type: string
          example: "ent_01JA1B2C3D4E5F6G7H8J9K0L"
        email:
          type: string
          format: email
          example: "alice@example.com"
        type:
          type: string
          enum: [individual, business]
          example: "individual"
        status:
          type: string
          enum: [active, inactive]
          example: "active"
        kycStatus:
          type: string
          enum: [not_started, pending, incomplete, under_review, approved, rejected]
          example: "approved"
        tosStatus:
          type: string
          enum: [not_started, pending, approved]
          example: "approved"
        kycLink:
          type: string
          nullable: true
          description: Link for the Entity to complete identity verification.
          example: "https://verify.otim.com/kyc/abc123"
        tosLink:
          type: string
          nullable: true
          description: Link for the Entity to accept terms of service.
          example: "https://verify.otim.com/tos/abc123"
        createdAt:
          type: string
          format: date-time
          example: "2025-01-15T12:00:00Z"
    CreateEntityRequest:
      type: object
      required: [email, type]
      properties:
        email:
          type: string
          format: email
          description: Email address for the Entity.
        type:
          type: string
          enum: [individual, business]
          description: The type of Entity.
        fullName:
          type: string
          description: Full name of the individual. Required when type is `individual`.
        businessName:
          type: string
          description: Name of the business. Required when type is `business`.
    CreateEntityResponse:
      type: object
      properties:
        id:
          type: string
          example: "ent_01JA1B2C3D4E5F6G7H8J9K0L"
        email:
          type: string
          format: email
        type:
          type: string
          enum: [individual, business]
        kycStatus:
          type: string
          example: "not_started"
        tosStatus:
          type: string
          example: "not_started"
        kycLink:
          type: string
          description: Share this link with the Entity to begin identity verification.
          example: "https://verify.otim.com/kyc/abc123"
        tosLink:
          type: string
          description: Share this link with the Entity to accept terms of service.
          example: "https://verify.otim.com/tos/abc123"
        createdAt:
          type: string
          format: date-time
    Transfer:
      type: object
      properties:
        id:
          type: string
          example: "txfr_01JA1B2C3D4E5F6G7H8J9K0L"
        sourceAccountId:
          type: string
        destinationAccountId:
          type: string
          nullable: true
        counterpartyId:
          type: string
          nullable: true
        amount:
          type: string
          example: "100.50"
        currency:
          type: string
          example: "USDC"
        type:
          type: string
          enum: [book, wire, on_chain]
          example: "book"
        status:
          type: string
          enum: [pending, processing, completed, failed, cancelled]
          example: "completed"
        direction:
          type: string
          enum: [outgoing, incoming]
          example: "outgoing"
        description:
          type: string
          nullable: true
          example: "Payment to vendor"
        createdAt:
          type: string
          format: date-time
          example: "2025-01-15T12:00:00Z"
    CreateTransferRequest:
      type: object
      required: [sourceAccountId, amount]
      properties:
        sourceAccountId:
          type: string
          description: The ID of the Account to transfer from.
        destinationAccountId:
          type: string
          description: The ID of the destination Account. Use this for book transfers between Accounts on the same Platform.
        counterpartyId:
          type: string
          description: The ID of the Counterparty to send funds to. Use this for transfers to external wallets or bank accounts.
        amount:
          type: string
          description: The amount to transfer (e.g., `100.50`).
        currency:
          type: string
          description: The currency to transfer. Defaults to `USDC`.
          default: USDC
        description:
          type: string
          description: Optional description for the transfer.
    CreateTransferResponse:
      type: object
      properties:
        id:
          type: string
          example: "txfr_01JA1B2C3D4E5F6G7H8J9K0L"
        status:
          type: string
          example: "pending"
        type:
          type: string
          example: "book"
        createdAt:
          type: string
          format: date-time
    Counterparty:
      type: object
      properties:
        id:
          type: string
          example: "cpty_01JA1B2C3D4E5F6G7H8J9K0L"
        entityId:
          type: string
          example: "ent_01JA1B2C3D4E5F6G7H8J9K0L"
        name:
          type: string
          example: "Acme Corp"
        type:
          type: string
          enum: [wallet, bank_account]
          example: "bank_account"
        bankName:
          type: string
          nullable: true
          example: "Chase"
        accountNumber:
          type: string
          nullable: true
          example: "****6789"
        routingNumber:
          type: string
          nullable: true
          example: "021000021"
        walletAddress:
          type: string
          nullable: true
          example: "0x1234567890abcdef1234567890abcdef12345678"
        chain:
          type: string
          nullable: true
          example: "base"
        createdAt:
          type: string
          format: date-time
          example: "2025-01-15T12:00:00Z"
    CreateCounterpartyRequest:
      type: object
      required: [entityId, name, type]
      properties:
        entityId:
          type: string
          description: The ID of the Entity this Counterparty belongs to.
        name:
          type: string
          description: A display name for the Counterparty.
        type:
          type: string
          enum: [wallet, bank_account]
          description: The type of Counterparty.
        bankName:
          type: string
          description: Name of the bank. Required when type is `bank_account`.
        accountNumber:
          type: string
          description: Bank account number. Required when type is `bank_account`.
        routingNumber:
          type: string
          description: Bank routing number. Required when type is `bank_account`.
        walletAddress:
          type: string
          description: Wallet address. Required when type is `wallet`.
        chain:
          type: string
          description: Chain for the wallet. Required when type is `wallet`.
          enum: [ethereum, base, arbitrum, optimism, polygon]
    Iban:
      type: object
      properties:
        id:
          type: string
          example: "iban_01JA1B2C3D4E5F6G7H8J9K0L"
        entityId:
          type: string
          example: "ent_01JA1B2C3D4E5F6G7H8J9K0L"
        accountId:
          type: string
          example: "acc_01JA1B2C3D4E5F6G7H8J9K0L"
        iban:
          type: string
          example: "GB29 NWBK 6016 1331 9268 19"
        bic:
          type: string
          example: "NWBKGB2L"
        bankName:
          type: string
          example: "Otim Financial Services"
        currency:
          type: string
          description: The fiat currency this IBAN accepts.
          example: "EUR"
        status:
          type: string
          enum: [active, inactive]
          example: "active"
        createdAt:
          type: string
          format: date-time
          example: "2025-01-15T12:00:00Z"
    CreateIbanRequest:
      type: object
      required: [entityId, accountId, currency]
      properties:
        entityId:
          type: string
          description: The ID of the verified Entity to issue the IBAN for.
        accountId:
          type: string
          description: The ID of the Account that will receive funds deposited to this IBAN.
        currency:
          type: string
          description: The fiat currency for the IBAN.
          enum: [USD, EUR, GBP, JPY, CAD, AUD, CHF]
    UpdateAccountRequest:
      type: object
      properties:
        name:
          type: string
          description: Update the display name for the Account.
        metadata:
          type: object
          nullable: true
          description: Replace the metadata attached to the Account. Set to `null` to clear.
    UpdateCounterpartyRequest:
      type: object
      properties:
        name:
          type: string
          description: Update the display name for the Counterparty.
    Error:
      type: object
      properties:
        error:
          type: string
        code:
          type: string
          description: A machine-readable error code.
        details:
          type: object
          nullable: true
          description: Additional context about the error.
paths:
  /platform/settings:
    get:
      operationId: getPlatformSettings
      summary: Get Platform Settings
      description: Returns the current settings for your Platform, including auto-earn configuration, default chain, and webhook URL.
      tags: []
      responses:
        '200':
          description: Platform settings.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlatformSettings'
        '401':
          description: Unauthorized.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
    patch:
      operationId: updatePlatformSettings
      summary: Update Platform Settings
      description: Updates your Platform settings. Any fields not included in the request body will remain unchanged.
      tags: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdatePlatformSettingsRequest'
      responses:
        '200':
          description: Updated platform settings.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlatformSettings'
        '400':
          description: Validation error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /accounts/{id}:
    get:
      operationId: getAccount
      summary: Get Account
      description: Returns the details of a single Account by ID, including current balances and auto-earn status.
      tags: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
          description: The ID of the Account.
      responses:
        '200':
          description: Account details.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Account'
        '401':
          description: Unauthorized.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Account not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
    patch:
      operationId: updateAccount
      summary: Update Account
      description: Updates an Account's display name or metadata. Only the fields included in the request body will be changed.
      tags: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
          description: The ID of the Account.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateAccountRequest'
      responses:
        '200':
          description: Updated Account.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Account'
        '400':
          description: Validation error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Account not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /accounts:
    post:
      operationId: createAccount
      summary: Create Account
      description: Creates a new Account under an existing Entity. The Account is automatically provisioned on your Platform's default chain. If auto-earn is enabled in your Platform Settings, the Account will be configured to earn yield on idle balances.
      tags: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateAccountRequest'
      responses:
        '201':
          description: Account created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateAccountResponse'
        '400':
          description: Validation error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
    get:
      operationId: listAccounts
      summary: List Accounts
      description: Returns a paginated list of Accounts on your Platform.
      tags: []
      parameters:
        - name: entityId
          in: query
          schema:
            type: string
          description: Filter Accounts by Entity ID.
        - name: cursor
          in: query
          schema:
            type: string
          description: Pagination cursor from a previous response.
        - name: limit
          in: query
          schema:
            type: integer
            default: 50
            maximum: 100
          description: Number of items to return.
      responses:
        '200':
          description: A paginated list of Accounts.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedAccounts'
        '401':
          description: Unauthorized.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /entities:
    post:
      operationId: createEntity
      summary: Create Entity
      description: Creates a new Entity and initiates the verification flow. The response includes links that the Entity can use to complete identity verification (KYC for individuals, KYB for businesses) and accept the terms of service.
      tags: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateEntityRequest'
      responses:
        '201':
          description: Entity created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateEntityResponse'
        '400':
          description: Validation error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
    get:
      operationId: listEntities
      summary: List Entities
      description: Returns a paginated list of Entities on your Platform.
      tags: []
      parameters:
        - name: cursor
          in: query
          schema:
            type: string
          description: Pagination cursor from a previous response.
        - name: limit
          in: query
          schema:
            type: integer
            default: 50
            maximum: 100
          description: Number of items to return.
      responses:
        '200':
          description: A paginated list of Entities.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedEntities'
        '401':
          description: Unauthorized.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /entities/{id}:
    get:
      operationId: getEntity
      summary: Get Entity
      description: Returns the details of a single Entity, including their current verification status. Use this endpoint to check whether an Entity has completed KYC/KYB and is eligible for fiat capabilities like IBANs.
      tags: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
          description: The ID of the Entity.
      responses:
        '200':
          description: Entity details.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Entity'
        '401':
          description: Unauthorized.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Entity not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /counterparties/{id}:
    get:
      operationId: getCounterparty
      summary: Get Counterparty
      description: Returns the details of a single Counterparty by ID.
      tags: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
          description: The ID of the Counterparty.
      responses:
        '200':
          description: Counterparty details.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Counterparty'
        '401':
          description: Unauthorized.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Counterparty not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
    patch:
      operationId: updateCounterparty
      summary: Update Counterparty
      description: Updates a Counterparty's display name.
      tags: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
          description: The ID of the Counterparty.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateCounterpartyRequest'
      responses:
        '200':
          description: Updated Counterparty.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Counterparty'
        '400':
          description: Validation error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Counterparty not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
    delete:
      operationId: deleteCounterparty
      summary: Delete Counterparty
      description: Permanently deletes a Counterparty. This cannot be undone. Any pending transfers to this Counterparty will fail.
      tags: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
          description: The ID of the Counterparty.
      responses:
        '204':
          description: Counterparty deleted.
        '401':
          description: Unauthorized.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Counterparty not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /counterparties:
    post:
      operationId: createCounterparty
      summary: Create Counterparty
      description: Creates a new Counterparty under an existing Entity. A Counterparty represents an external party that funds can be sent to or received from. Counterparties can be either wallet addresses or bank accounts.
      tags: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateCounterpartyRequest'
      responses:
        '201':
          description: Counterparty created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Counterparty'
        '400':
          description: Validation error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
    get:
      operationId: listCounterparties
      summary: List Counterparties
      description: Returns a paginated list of Counterparties on your Platform.
      tags: []
      parameters:
        - name: entityId
          in: query
          schema:
            type: string
          description: Filter Counterparties by Entity ID.
        - name: cursor
          in: query
          schema:
            type: string
          description: Pagination cursor from a previous response.
        - name: limit
          in: query
          schema:
            type: integer
            default: 50
            maximum: 100
          description: Number of items to return.
      responses:
        '200':
          description: A paginated list of Counterparties.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedCounterparties'
        '401':
          description: Unauthorized.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /ibans/{id}:
    get:
      operationId: getIban
      summary: Get IBAN
      description: Returns the details of a single IBAN by ID.
      tags: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
          description: The ID of the IBAN.
      responses:
        '200':
          description: IBAN details.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Iban'
        '401':
          description: Unauthorized.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: IBAN not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
    delete:
      operationId: deleteIban
      summary: Delete IBAN
      description: Deactivates and deletes an IBAN. Any future deposits to this IBAN will be rejected. This cannot be undone.
      tags: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
          description: The ID of the IBAN.
      responses:
        '204':
          description: IBAN deleted.
        '401':
          description: Unauthorized.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: IBAN not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /ibans:
    post:
      operationId: createIban
      summary: Create IBAN
      description: Issues a new IBAN for a verified Entity. The IBAN is linked to an Account, and any fiat deposited to it will be automatically converted and routed into that Account. The Entity must have completed verification (KYC/KYB) before an IBAN can be issued.
      tags: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateIbanRequest'
      responses:
        '201':
          description: IBAN created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Iban'
        '400':
          description: Validation error (e.g., Entity not verified).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
    get:
      operationId: listIbans
      summary: List IBANs
      description: Returns a paginated list of IBANs on your Platform.
      tags: []
      parameters:
        - name: entityId
          in: query
          schema:
            type: string
          description: Filter IBANs by Entity ID.
        - name: accountId
          in: query
          schema:
            type: string
          description: Filter IBANs by Account ID.
        - name: cursor
          in: query
          schema:
            type: string
          description: Pagination cursor from a previous response.
        - name: limit
          in: query
          schema:
            type: integer
            default: 50
            maximum: 100
          description: Number of items to return.
      responses:
        '200':
          description: A paginated list of IBANs.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedIbans'
        '401':
          description: Unauthorized.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /transfers:
    post:
      operationId: createTransfer
      summary: Create Transfer
      description: Creates a transfer from an Account. You can send funds to another Account on your Platform (book transfer) or to an external Counterparty (on-chain or wire transfer). Provide either `destinationAccountId` or `counterpartyId`, but not both.
      tags: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateTransferRequest'
      responses:
        '201':
          description: Transfer created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateTransferResponse'
        '400':
          description: Validation error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
    get:
      operationId: listTransfers
      summary: List Transfers
      description: Returns a paginated list of transfers on your Platform.
      tags: []
      parameters:
        - name: accountId
          in: query
          schema:
            type: string
          description: Filter transfers by Account ID.
        - name: cursor
          in: query
          schema:
            type: string
          description: Pagination cursor from a previous response.
        - name: limit
          in: query
          schema:
            type: integer
            default: 50
            maximum: 100
          description: Number of items to return.
      responses:
        '200':
          description: A paginated list of transfers.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedTransfers'
        '401':
          description: Unauthorized.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /transfers/{id}:
    get:
      operationId: getTransfer
      summary: Get Transfer
      description: Returns the details of a single transfer by ID.
      tags: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
          description: The ID of the transfer.
      responses:
        '200':
          description: Transfer details.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Transfer'
        '401':
          description: Unauthorized.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Transfer not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
