> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zuba.com/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Money amounts are always major-unit decimal strings (e.g. "1000.00"), never floats and never minor units, in every request, response, and webhook payload.
> Authentication is OAuth 2.0 client credentials: exchange the Client ID and Client Secret at the Token URL for a 24-hour JWT and cache it; do not request a token per call.
> Set a unique clientRef on every money-moving request; it is the idempotency key, and retries return the original resource.
> Quotes are single-use, intent-locked, and expire fast: always read expiresAt, consume the quote with the executor matching its intent, and re-quote on expiry instead of retrying.
> Prefer webhooks over polling for payout, order, application, and virtual-account status tracking.
> Use the sandbox (api.sandbox.zuba.com) with its deterministic magic values before touching production.

# Open a wallet

> Opens an on-chain deposit wallet on the requested network for your master account, or for the sub-account named in `Zuba-Account-Id`, whose deposits then settle into that sub-account's balance. Idempotent per owner, network and `clientRef`: if the wallet already exists it is returned with `201 → 200`, provided at least one asset on that network is still enabled for you; when none is, opening is refused and the existing wallet is read through `GET /v1/wallets` instead. Send any of the wallet's `assets` to its `address` on that network; the deposit is credited once it confirms on-chain, provided it meets the per-transfer minimum. A smaller transfer, or a transfer on a network other than the wallet's own, is not credited, does not appear in `GET /v1/deposits`, and cannot be recovered.



## OpenAPI

````yaml /openapi.json post /v1/wallets
openapi: 3.0.0
info:
  contact: {}
  description: >-
    Comprehensive payment platform API supporting fiat and crypto payments,
    currency conversion, and compliance management
  title: Zuba Payment Platform API
  version: '1.0'
servers: []
security: []
tags:
  - description: Manage M2M API keys and credentials
    name: API Keys
  - description: Per-country bank directories and bank-account enquiries
    name: Banks
  - description: Internal ledger accounts and transactions
    name: Ledger
  - description: Handle incoming payments and deposits
    name: Pay-ins
  - description: Manage payouts, beneficiaries, and SEPA transfers
    name: Payouts
  - description: Manage outbound webhook endpoints and deliveries
    name: Webhooks
paths:
  /v1/wallets:
    post:
      tags:
        - Wallets
      summary: Open a wallet
      description: >-
        Opens an on-chain deposit wallet on the requested network for your
        master account, or for the sub-account named in `Zuba-Account-Id`, whose
        deposits then settle into that sub-account's balance. Idempotent per
        owner, network and `clientRef`: if the wallet already exists it is
        returned with `201 → 200`, provided at least one asset on that network
        is still enabled for you; when none is, opening is refused and the
        existing wallet is read through `GET /v1/wallets` instead. Send any of
        the wallet's `assets` to its `address` on that network; the deposit is
        credited once it confirms on-chain, provided it meets the per-transfer
        minimum. A smaller transfer, or a transfer on a network other than the
        wallet's own, is not credited, does not appear in `GET /v1/deposits`,
        and cannot be recovered.
      operationId: WalletsController_create
      parameters:
        - description: >-
            Optional. Names an owned sub-account (UUID) to act on. Omit to act
            at the master (tenant) level. Naming an account this key does not
            own returns 403 not_account_owner.
          in: header
          name: Zuba-Account-Id
          required: false
          schema:
            format: uuid
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateWalletDto'
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WalletResponseDto'
          description: The owner already held a wallet on this network for this clientRef.
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WalletResponseDto'
          description: Wallet opened.
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationErrorResponseDto'
          description: >-
            Unsupported network, or a clientRef that is empty, over 100
            characters, begins or ends with whitespace, carries a line break or
            a character outside the single-byte range, or starts with the
            reserved prefix "pool-".
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericErrorResponseDto'
          description: Unauthorized - missing or invalid JWT token
        '403':
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/GenericErrorResponseDto'
                  - $ref: '#/components/schemas/PaymentsNotEnabledErrorResponseDto'
          description: >-
            Insufficient role, API key missing the create:deposits scope,
            not_account_owner (Zuba-Account-Id does not name an account you
            own), payments_not_enabled (the client is not payments-enabled), or
            METHOD_NOT_ENTITLED (no asset is enabled for you to deposit on the
            requested network, message carries the capability label).
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericErrorResponseDto'
          description: >-
            ACCOUNT_NOT_FOUND: the sub-account named by Zuba-Account-Id no
            longer exists (an id this client does not own is 403
            not_account_owner).
        '409':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProblemDetailsResponseDto'
          description: >-
            STATE_CONFLICT: the wallet for this owner, network and clientRef is
            inactive or archived and cannot be re-opened. Contact support.
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericErrorResponseDto'
          description: >-
            ACCOUNT_NOT_ACTIVE: the sub-account named by Zuba-Account-Id is
            owned but not active, so a wallet cannot be opened for it.
        '502':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericErrorResponseDto'
          description: Custody provider request failed
      security:
        - bearer: []
components:
  schemas:
    CreateWalletDto:
      properties:
        clientRef:
          description: >-
            Optional client reference. Omit for the owner's single default
            wallet on this network; pass distinct values (e.g. your end-customer
            id) to open distinct wallets. Must be 1 to 100 single-byte
            characters with no line break, must not begin or end with
            whitespace, and must not start with "pool-", a prefix reserved for
            platform-minted order-funding addresses.
          example: customer-1234
          maxLength: 100
          minLength: 1
          pattern: ^[\x21-\xff](?:[\x01-\x09\x0b\x0c\x0e-\xff]*[\x21-\xff])?$
          type: string
        network:
          description: >-
            Network to open the wallet on, as a CAIP-2 chain id (e.g. "eip155:1"
            for Ethereum mainnet).
          enum:
            - eip155:1
            - eip155:8453
            - eip155:4217
            - eip155:42431
            - solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp
            - tron:mainnet
            - solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1
          example: eip155:1
          type: string
      required:
        - network
      type: object
    WalletResponseDto:
      properties:
        accountId:
          description: >-
            The sub-account that owns the wallet; deposits to it settle into
            that sub-account's balance. Absent when the wallet belongs to your
            master account.
          format: uuid
          type: string
        address:
          description: >-
            On-chain address to send funds to. Deposits are credited only on the
            wallet's own network: an EVM address is syntactically valid on every
            EVM chain, but a transfer to it on another chain is not credited.
          example: '0x1234567890abcdef1234567890abcdef12345678'
          type: string
        assets:
          description: >-
            Stablecoins your account is credited for when they arrive at this
            address. Any other token, and any listed token sent on another
            network, is not credited. Empty when nothing on this network is
            currently offered to your account, and empty on a wallet whose
            status is not `active`, which credits nothing.
          example:
            - USDT
            - USDC
          items:
            type: string
          type: array
        clientRef:
          description: The client reference the wallet was opened with, if any.
          example: customer-1234
          type: string
        createdAt:
          description: When the wallet was opened, ISO-8601.
          example: '2026-09-09T12:00:00.000Z'
          type: string
        id:
          description: Wallet id.
          example: 9b2f4c1e-3d7a-4e8b-9f01-2c3d4e5f6a7b
          format: uuid
          type: string
        network:
          enum:
            - eip155:1
            - eip155:8453
            - eip155:4217
            - eip155:42431
            - solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp
            - tron:mainnet
            - solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1
          example: eip155:1
          type: string
        status:
          description: >-
            `active`: receives deposits. `inactive`: frozen; deposits are held
            for review and the wallet cannot be re-requested. Contact support.
          enum:
            - active
            - inactive
          example: active
          type: string
      required:
        - id
        - network
        - address
        - assets
        - status
        - createdAt
      type: object
    ValidationErrorResponseDto:
      properties:
        details:
          description: Array of detailed validation errors
          example:
            - field: accounts.0.data
              message: crAccount must be exactly 10 digits for Nigerian accounts
          items:
            $ref: '#/components/schemas/ValidationErrorDetailDto'
          type: array
        error:
          description: Error type identifier
          example: BAD_REQUEST
          type: string
        message:
          description: >-
            The `details` messages joined with `; `, so a client that reads only
            this field still sees every failing field
          example: crAccount must be exactly 10 digits for Nigerian accounts
          type: string
        path:
          description: Request path that generated the error
          example: /v1/resource
          type: string
        statusCode:
          description: HTTP status code
          example: 400
          type: number
        timestamp:
          description: ISO timestamp when the error occurred
          example: '2024-01-15T10:30:00.000Z'
          type: string
      required:
        - statusCode
        - message
        - error
        - timestamp
        - path
        - details
      type: object
    GenericErrorResponseDto:
      properties:
        error:
          description: Error type identifier
          example: BAD_REQUEST
          type: string
        message:
          description: Error message
          example: Bad Request
          type: string
        path:
          description: Request path that generated the error
          example: /v1/resource
          type: string
        statusCode:
          description: HTTP status code
          example: 400
          type: number
        timestamp:
          description: ISO timestamp when the error occurred
          example: '2024-01-15T10:30:00.000Z'
          type: string
      required:
        - statusCode
        - message
        - error
        - timestamp
        - path
      type: object
    PaymentsNotEnabledErrorResponseDto:
      properties:
        detail:
          description: Human-readable action required to enable payments
          example: >-
            Payments are not enabled. Complete merchant verification to activate
            payments.
          type: string
        error:
          description: Stable lowercase discriminator for new integrations
          example: payments_not_enabled
          type: string
        message:
          description: Stable legacy discriminator retained for v1 clients
          example: PAYMENTS_NOT_ENABLED
          type: string
        path:
          description: Request path that generated the error
          example: /v1/resource
          type: string
        statusCode:
          description: HTTP status code
          example: 400
          type: number
        timestamp:
          description: ISO timestamp when the error occurred
          example: '2024-01-15T10:30:00.000Z'
          type: string
      required:
        - statusCode
        - message
        - error
        - timestamp
        - path
        - detail
      type: object
    ProblemDetailsResponseDto:
      properties:
        category:
          description: Top-level failure category carrying the retry class
          example: BUSINESS_DECLINE
          type: string
        code:
          description: Stable machine-readable code the client branches on
          example: STATE_CONFLICT
          type: string
        detail:
          description: Explanation specific to this occurrence
          example: >-
            The wallet for this owner, network and clientRef is inactive or
            archived and cannot be re-opened. Contact support.
          type: string
        instance:
          description: URI reference identifying this occurrence
          example: /v1/wallets
          type: string
        request_id:
          description: Per-request correlation id, or null when absent
          example: req_01HZY7
          nullable: true
          type: string
        retryable:
          description: Whether the client may safely retry
          example: false
          type: boolean
        status:
          description: HTTP status code
          example: 409
          type: number
        title:
          description: Short summary of the problem type
          example: The request conflicts with the current state
          type: string
        type:
          description: Stable URI identifying the problem type
          example: https://errors.zuba.com/business-decline/state-conflict
          type: string
      required:
        - type
        - title
        - status
        - detail
        - code
        - category
        - request_id
      type: object
    ValidationErrorDetailDto:
      properties:
        code:
          description: >-
            Stable machine-readable code for client-side branching. Present on
            structural-validation failures of the recipient (e.g.
            MISSING_BENEFICIARY_NAME, INVALID_IBAN, BENEFICIARY_INCOMPLETE) and
            of the sender (SENDER_INFO_INCOMPLETE, SENDER_INFO_INVALID); absent
            on generic DTO validation errors.
          example: MISSING_BENEFICIARY_NAME
          type: string
        field:
          description: >-
            The field path that failed validation. A bank account format rule
            reports the account object it checked (e.g. accounts.0.data) and
            names each failing field in its message.
          example: accounts.0.data
          type: string
        message:
          description: Human-readable error message describing the validation failure
          example: crAccount must be exactly 10 digits for Nigerian accounts
          type: string
      required:
        - field
        - message
      type: object
  securitySchemes:
    bearer:
      bearerFormat: JWT
      description: Enter Auth0 JWT token
      scheme: bearer
      type: http

````