openapi: 3.0.3
info:
  title: Kaito Core API
  version: 2.0.0
  description: >
    Core payment operations: Quotes, Payments, Payouts, and FX.


    **Rail Types:** `CRYPTO_CRYPTO` (on-chain), `FIAT_CRYPTO` (on-ramp),
    `CRYPTO_FIAT` (off-ramp), `FIAT_FIAT` (cross-border).


    **Typical Flow:** Get rates -> Create quote -> Execute payment/payout ->
    Track status.


    **Destination Types (Payments):** `handle`, `phone`, `address`.


    **Beneficiary Types (Payouts):** `bank_account`, `cash_pickup`,
    `mobile_money`.
  termsOfService: https://developer.kai2.io/terms
  contact:
    name: Kaito Developer Support
    url: https://developer.kai2.io/support
    email: support@kai2.io
  license:
    name: Apache 2.0
    url: https://www.apache.org/licenses/LICENSE-2.0
servers:
  - url: https://api.kai2.io
    description: Production
  - url: https://sandbox.api.kai2.io
    description: Sandbox
x-tagGroups:
  - name: Quotes & Execution
    tags:
      - Quotes
      - Execution Plans
  - name: Payments & Payouts
    tags:
      - Payments
      - Payouts
  - name: FX Operations
    tags:
      - FX Rates
      - FX Quotes
      - Corridors
tags:
  - name: Quotes
    description: Lock pricing and routing
  - name: Execution Plans
    description: Multi-step routing plans
  - name: Payments
    description: Execute payments (CRYPTO_CRYPTO, FIAT_CRYPTO)
  - name: Payouts
    description: Execute payouts/off-ramp (CRYPTO_FIAT, FIAT_FIAT)
  - name: FX Rates
    description: Indicative exchange rates
  - name: FX Quotes
    description: Firm FX quotes
  - name: Corridors
    description: Supported corridors
paths:
  /v1/quotes:
    post:
      summary: Create quote
      tags:
        - Quotes
      description: |
        Creates a quote for a specific railType and corridor.
        Use quotes to lock pricing and routing for a limited time window.
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/QuoteCreateRequest'
      responses:
        '201':
          description: Quote created
          headers:
            X-Trace-Id:
              schema:
                $ref: '#/components/schemas/TraceId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Quote'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /v1/quotes/{quoteId}:
    get:
      summary: Get quote by ID
      tags:
        - Quotes
      parameters:
        - name: quoteId
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Quote details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Quote'
        '404':
          $ref: '#/components/responses/NotFound'
  /v1/execution-plans:
    post:
      summary: Create execution plan from quote
      tags:
        - Execution Plans
      description: Generates a multi-step routing plan from an existing quote.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ExecutionPlanCreateRequest'
      responses:
        '201':
          description: Execution plan created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExecutionPlan'
        '400':
          $ref: '#/components/responses/BadRequest'
  /v1/execution-plans/{planId}:
    get:
      summary: Get execution plan by ID
      tags:
        - Execution Plans
      parameters:
        - name: planId
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Execution plan details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExecutionPlan'
        '404':
          $ref: '#/components/responses/NotFound'
  /v1/payments:
    post:
      summary: Create payment
      tags:
        - Payments
      description: |
        Creates a payment for `CRYPTO_CRYPTO` or `FIAT_CRYPTO` flows.
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PaymentCreateRequest'
      responses:
        '201':
          description: Payment created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Payment'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
    get:
      summary: List payments
      tags:
        - Payments
      parameters:
        - in: query
          name: status
          schema:
            $ref: '#/components/schemas/PaymentStatus'
        - in: query
          name: railType
          schema:
            $ref: '#/components/schemas/RailType'
        - in: query
          name: createdAfter
          schema:
            type: string
            format: date-time
        - in: query
          name: createdBefore
          schema:
            type: string
            format: date-time
        - in: query
          name: limit
          schema:
            type: integer
            default: 50
        - in: query
          name: cursor
          schema:
            type: string
      responses:
        '200':
          description: Payments list
          content:
            application/json:
              schema:
                type: object
                properties:
                  items:
                    type: array
                    items:
                      $ref: '#/components/schemas/Payment'
                  pagination:
                    $ref: '#/components/schemas/Pagination'
  /v1/payments/{paymentId}:
    get:
      summary: Get payment by ID
      tags:
        - Payments
      parameters:
        - name: paymentId
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Payment details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Payment'
        '404':
          $ref: '#/components/responses/NotFound'
  /v1/payouts:
    post:
      summary: Create payout (off-ramp)
      tags:
        - Payouts
      description: |
        Creates a payout for `CRYPTO_FIAT` or `FIAT_FIAT` flows.
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PayoutCreateRequest'
      responses:
        '201':
          description: Payout created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Payout'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
    get:
      summary: List payouts
      tags:
        - Payouts
      parameters:
        - in: query
          name: status
          schema:
            $ref: '#/components/schemas/PayoutStatus'
        - in: query
          name: railType
          schema:
            type: string
            enum:
              - FIAT_FIAT
              - CRYPTO_FIAT
        - in: query
          name: createdAfter
          schema:
            type: string
            format: date-time
        - in: query
          name: createdBefore
          schema:
            type: string
            format: date-time
        - in: query
          name: limit
          schema:
            type: integer
            default: 50
        - in: query
          name: cursor
          schema:
            type: string
      responses:
        '200':
          description: Payouts list
          content:
            application/json:
              schema:
                type: object
                properties:
                  items:
                    type: array
                    items:
                      $ref: '#/components/schemas/Payout'
                  pagination:
                    $ref: '#/components/schemas/Pagination'
  /v1/payouts/{payoutId}:
    get:
      summary: Get payout by ID
      tags:
        - Payouts
      parameters:
        - name: payoutId
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Payout details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Payout'
        '404':
          $ref: '#/components/responses/NotFound'
  /v1/rates:
    get:
      summary: Get indicative rates
      tags:
        - FX Rates
      description: Returns real-time indicative rates. For firm rates, use FX quotes.
      parameters:
        - in: query
          name: pairs
          schema:
            type: string
            description: Comma-separated currency pairs (e.g., USD-GTQ,USD-MXN)
            example: USD-GTQ,USD-MXN
      responses:
        '200':
          description: Current rates
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RatesResponse'
  /v1/fx-quotes:
    post:
      summary: Create FX quote
      tags:
        - FX Quotes
      description: Creates a firm FX quote locked for a short time window.
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/FXQuoteCreateRequest'
      responses:
        '201':
          description: FX Quote created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FXQuote'
        '400':
          $ref: '#/components/responses/BadRequest'
  /v1/fx-quotes/{quoteId}:
    get:
      summary: Get FX quote by ID
      tags:
        - FX Quotes
      parameters:
        - name: quoteId
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: FX Quote details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FXQuote'
        '404':
          $ref: '#/components/responses/NotFound'
  /v1/corridors:
    get:
      summary: List supported corridors
      tags:
        - Corridors
      description: Returns all supported currency corridors and their constraints.
      parameters:
        - in: query
          name: sourceCountry
          schema:
            type: string
        - in: query
          name: destinationCountry
          schema:
            type: string
        - in: query
          name: railType
          schema:
            $ref: '#/components/schemas/RailType'
      responses:
        '200':
          description: Supported corridors
          content:
            application/json:
              schema:
                type: object
                properties:
                  items:
                    type: array
                    items:
                      $ref: '#/components/schemas/SupportedCorridor'
components:
  securitySchemes:
    oAuth2:
      type: oauth2
      flows:
        clientCredentials:
          tokenUrl: https://auth.kai2.io/oauth2/token
          scopes:
            quotes:write: Create quotes
            quotes:read: Read quotes
            payments:write: Create payments and payouts
            payments:read: Read payments and payouts
            fx:read: Get rates and corridors
            fx:write: Create FX quotes
      description: OAuth2 client credentials. All requests must also be made over mTLS.
  parameters:
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: false
      schema:
        type: string
      description: A unique key to make POST requests idempotent.
  responses:
    BadRequest:
      description: Bad Request
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    Unauthorized:
      description: Access token is missing or invalid.
    NotFound:
      description: The requested resource does not exist.
  schemas:
    TraceId:
      type: string
      description: Correlation id for troubleshooting
      example: trc_01JH8K5P3V9M2K5Q7W6J3Z1A9B
    Pagination:
      type: object
      properties:
        nextCursor:
          type: string
          nullable: true
          example: cursor_abc123
    ErrorResponse:
      type: object
      required:
        - error
        - traceId
      properties:
        traceId:
          $ref: '#/components/schemas/TraceId'
        error:
          type: object
          properties:
            code:
              type: string
              example: INVALID_REQUEST
            message:
              type: string
              example: Missing required field
            details:
              type: object
              additionalProperties: true
    RailType:
      type: string
      enum:
        - FIAT_FIAT
        - FIAT_CRYPTO
        - CRYPTO_FIAT
        - CRYPTO_CRYPTO
      example: CRYPTO_CRYPTO
    Network:
      type: string
      enum:
        - ethereum
        - polygon
        - solana
        - bitcoin
      example: polygon
    Money:
      type: object
      required:
        - amount
        - currency
      properties:
        amount:
          type: string
          example: '1000.00'
        currency:
          type: string
          example: USD
    FeeType:
      type: string
      enum:
        - network
        - provider
        - kaito
        - partner
    Fee:
      type: object
      required:
        - type
        - amount
      properties:
        type:
          $ref: '#/components/schemas/FeeType'
        amount:
          $ref: '#/components/schemas/Money'
        description:
          type: string
          nullable: true
    QuoteCreateRequest:
      type: object
      required:
        - railType
        - sender
        - receiver
        - corridor
      properties:
        railType:
          $ref: '#/components/schemas/RailType'
        sender:
          $ref: '#/components/schemas/Money'
        receiver:
          type: object
          required:
            - currency
          properties:
            currency:
              type: string
              example: GTQ
        corridor:
          type: string
          example: US-GT
        rails:
          type: array
          items:
            type: string
            enum:
              - CRYPTO
              - BANK
              - CASH
        preferences:
          type: object
          additionalProperties: true
    Quote:
      type: object
      required:
        - quoteId
        - railType
        - corridor
        - sender
        - receiver
        - rate
        - fees
        - expiresAt
        - createdAt
      properties:
        quoteId:
          type: string
          example: qt_01JH...
        railType:
          $ref: '#/components/schemas/RailType'
        corridor:
          type: string
        sender:
          $ref: '#/components/schemas/Money'
        receiver:
          $ref: '#/components/schemas/Money'
        rate:
          type: string
          example: '37.7310'
        fees:
          type: array
          items:
            $ref: '#/components/schemas/Fee'
        expiresAt:
          type: string
          format: date-time
        createdAt:
          type: string
          format: date-time
    ExecutionPlanCreateRequest:
      type: object
      required:
        - quoteId
      properties:
        quoteId:
          type: string
        mode:
          type: string
          enum:
            - best_price
            - fastest
            - safest
          default: best_price
    ExecutionStep:
      type: object
      properties:
        step:
          type: integer
        provider:
          type: string
        action:
          type: string
        status:
          type: string
          enum:
            - planned
            - running
            - completed
            - failed
    ExecutionPlan:
      type: object
      required:
        - planId
        - quoteId
        - status
        - steps
        - createdAt
      properties:
        planId:
          type: string
          example: pln_01JH...
        quoteId:
          type: string
        status:
          type: string
          enum:
            - planned
            - executing
            - completed
            - failed
        steps:
          type: array
          items:
            $ref: '#/components/schemas/ExecutionStep'
        createdAt:
          type: string
          format: date-time
    Destination:
      type: object
      required:
        - type
        - value
      properties:
        type:
          type: string
          enum:
            - handle
            - phone
            - address
        value:
          type: string
          example: '@recipient'
    PaymentStatus:
      type: string
      enum:
        - created
        - pending
        - succeeded
        - failed
        - cancelled
    PaymentCreateRequest:
      type: object
      required:
        - railType
        - amount
        - currency
        - destination
      properties:
        railType:
          $ref: '#/components/schemas/RailType'
        amount:
          type: number
          example: 25.5
        currency:
          type: string
          example: USDT
        destination:
          $ref: '#/components/schemas/Destination'
        network:
          $ref: '#/components/schemas/Network'
        quoteId:
          type: string
          nullable: true
        metadata:
          type: object
          additionalProperties: true
    Payment:
      type: object
      required:
        - paymentId
        - status
        - createdAt
        - railType
        - amount
        - currency
        - destination
      properties:
        paymentId:
          type: string
          example: pay_01JH...
        status:
          $ref: '#/components/schemas/PaymentStatus'
        createdAt:
          type: string
          format: date-time
        railType:
          $ref: '#/components/schemas/RailType'
        amount:
          type: number
        currency:
          type: string
        destination:
          $ref: '#/components/schemas/Destination'
        network:
          $ref: '#/components/schemas/Network'
        quoteId:
          type: string
          nullable: true
        providerRef:
          type: string
          nullable: true
        txHash:
          type: string
          nullable: true
    BeneficiaryType:
      type: string
      enum:
        - bank_account
        - cash_pickup
        - mobile_money
    Beneficiary:
      type: object
      required:
        - type
        - value
      properties:
        type:
          $ref: '#/components/schemas/BeneficiaryType'
        value:
          type: object
          additionalProperties: true
          example:
            bankCode: BANK_X
            accountNumber: '1234567890'
            name: Recipient
    PayoutStatus:
      type: string
      enum:
        - created
        - pending
        - completed
        - failed
        - cancelled
    PayoutCreateRequest:
      type: object
      required:
        - railType
        - amount
        - currency
        - beneficiary
      properties:
        railType:
          type: string
          enum:
            - FIAT_FIAT
            - CRYPTO_FIAT
          example: CRYPTO_FIAT
        amount:
          type: number
          example: 1000
        currency:
          type: string
          example: GTQ
        beneficiary:
          $ref: '#/components/schemas/Beneficiary'
        quoteId:
          type: string
          nullable: true
        metadata:
          type: object
          additionalProperties: true
    Payout:
      type: object
      required:
        - payoutId
        - status
        - createdAt
        - railType
        - amount
        - currency
      properties:
        payoutId:
          type: string
          example: pyo_01JH...
        status:
          $ref: '#/components/schemas/PayoutStatus'
        createdAt:
          type: string
          format: date-time
        railType:
          type: string
          enum:
            - FIAT_FIAT
            - CRYPTO_FIAT
        amount:
          type: number
        currency:
          type: string
        providerRef:
          type: string
          nullable: true
    CurrencyPair:
      type: object
      required:
        - base
        - quote
      properties:
        base:
          type: string
          example: USD
        quote:
          type: string
          example: GTQ
    Rate:
      type: object
      required:
        - pair
        - bid
        - ask
        - mid
        - timestamp
      properties:
        pair:
          $ref: '#/components/schemas/CurrencyPair'
        bid:
          type: string
          example: '7.7200'
        ask:
          type: string
          example: '7.7400'
        mid:
          type: string
          example: '7.7300'
        spread:
          type: string
          nullable: true
        timestamp:
          type: string
          format: date-time
        source:
          type: string
          nullable: true
    RatesResponse:
      type: object
      required:
        - rates
        - asOf
      properties:
        rates:
          type: array
          items:
            $ref: '#/components/schemas/Rate'
        asOf:
          type: string
          format: date-time
    FXQuoteCreateRequest:
      type: object
      required:
        - baseCurrency
        - quoteCurrency
        - amount
        - side
      properties:
        baseCurrency:
          type: string
          example: USD
        quoteCurrency:
          type: string
          example: GTQ
        amount:
          type: number
          example: 1000
        side:
          type: string
          enum:
            - buy
            - sell
        lockDuration:
          type: integer
          nullable: true
          example: 60
    FXQuote:
      type: object
      required:
        - quoteId
        - baseCurrency
        - quoteCurrency
        - amount
        - side
        - rate
        - convertedAmount
        - expiresAt
        - createdAt
      properties:
        quoteId:
          type: string
          example: fxq_01JH...
        baseCurrency:
          type: string
        quoteCurrency:
          type: string
        amount:
          type: number
        side:
          type: string
          enum:
            - buy
            - sell
        rate:
          type: string
          example: '7.7310'
        convertedAmount:
          type: number
          example: 7731
        fees:
          type: array
          items:
            type: object
            properties:
              type:
                type: string
              amount:
                type: number
              currency:
                type: string
        expiresAt:
          type: string
          format: date-time
        createdAt:
          type: string
          format: date-time
    SupportedCorridor:
      type: object
      required:
        - corridor
        - sourceCurrency
        - destinationCurrency
        - railTypes
      properties:
        corridor:
          type: string
          example: US-GT
        sourceCurrency:
          type: string
          example: USD
        destinationCurrency:
          type: string
          example: GTQ
        sourceCountry:
          type: string
          example: US
        destinationCountry:
          type: string
          example: GT
        railTypes:
          type: array
          items:
            $ref: '#/components/schemas/RailType'
        minAmount:
          type: number
          example: 1
        maxAmount:
          type: number
          example: 50000
        estimatedDelivery:
          type: string
          example: 1-2 business days
security:
  - oAuth2: []
