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

# Withdraw from a Wallet

> Withdraws funds from the balance of a wallet of one of your customers, to an address of your choice.
See the [Crypto Wallets guide](/guides/wallets#withdraw-from-a-wallet) for the full flow.

- **Same network, same currency.** The withdrawal is made on the blockchain and in the currency of the
  wallet. `address` can be any valid address on that blockchain, except the address of the wallet itself.
- **Fees.** The commission of your plan (Starter $1 + 1%, Business $1 + 0.75%, Premium $1 + 0.5%) and the
  network fee of the blockchain are deducted from `amount`. After these fees, you must receive at least
  **$10**. Both are returned by [`GET /wallets/balance`](/api-reference/wallets/balance)
  (`withdrawal_commission` and `withdrawal_network_fee`).
- **Immediate debit.** `amount` is debited from the balance of the wallet as soon as the request is
  accepted. The transfer is sent automatically: the withdrawal is `processing`, then `completed`, and you
  receive the `wallet.withdrawal_completed` webhook when it has been sent on the blockchain.
- **Safe to retry.** With an `idempotency_key`, calling again with the same key on the same wallet returns
  the existing withdrawal with a `200` status: nothing is debited a second time. A new withdrawal answers `201`.
  The same key used again with a different `address` or `amount` is refused (`422`, `details.withdrawal_code`).

**Protect your API keys.** A withdrawal is made with your API key. API calls are only accepted from your
[allowed IP addresses](/getting-started/api-keys#allowed-ip-addresses) (required): keep this list limited to
your own servers, and keep your keys secret, on those servers only.

A blockchain transfer cannot be cancelled or reversed. Check the address and the blockchain before you call.


> [!WARNING]
>
> **Withdrawals are made with your API key.** API calls are only accepted from your [allowed IP addresses](/getting-started/api-keys#allowed-ip-addresses), which are required: keep this list limited to your own servers, and keep your keys secret, on those servers only. A key used from any other address is refused.

> [!NOTE]
>
> A blockchain transfer cannot be cancelled or reversed. Check that `address` is an address on the blockchain of the wallet before you call: funds sent to a wrong address are permanently lost.


## OpenAPI

````yaml POST /wallets/{code}/withdrawals
openapi: 3.1.0
info:
  title: KemyCard API
  version: '1.0'
  description: >
    KemyCard API allows you to issue virtual and physical cards, manage KYC/POA
    verification,

    create crypto wallets, virtual bank accounts, purchase gift cards and send
    payouts to bank accounts (SEPA Instant

    in EUR, ACH in USD to the United States).


    Access depends on your plan (see [Plans and
    Pricing](/getting-started/plans)). The free Découverte plan gives

    access to virtual cards with the KYC and POA endpoints and to payouts (SEPA
    and ACH), within monthly limits (25 cards

    created and 5,000 USD loaded on cards per calendar month, 5,000 USD of
    payouts per calendar month), 30 requests

    per minute per API key, 2 allowed IP addresses and 1 active webhook
    endpoint. Starter, Business and Premium give access to every product with no
    monthly limit,

    100 requests per minute per API key, 10 allowed IP addresses and 10 active
    webhook endpoints.


    Plan errors: `402 PLAN_UPGRADE_REQUIRED` (product not included in your
    plan), `403 PLAN_LIMIT_REACHED`

    (limit of your plan reached). While one of your ops balances is negative,
    every request other than `GET`

    returns `403 ACCOUNT_SUSPENDED_NEGATIVE_BALANCE`.
  contact:
    name: KemyCard API Support
    email: hi@kemycard.com
servers:
  - url: https://api.kemycard.com/v1
    description: Development (tests internes)
  - url: https://api.kemycard.com/v1
    description: Production
security:
  - BearerAuth: []
tags:
  - name: Customers
    description: Manage your customers
  - name: Card Products
    description: Browse the card product catalog
  - name: Cards
    description: Issue and manage cards
  - name: KYC
    description: Identity verification
  - name: POA
    description: Proof of address verification
  - name: Wallets
    description: Crypto wallets
  - name: Virtual Accounts
    description: >
      Virtual bank accounts in EUR, USD, BRL and MXN for your individual
      customers. Deposits are converted to USDC

      and sent, net of the KemyCard fee, to a USDC wallet on Solana of the
      customer or to an external Solana address
  - name: Gift Cards
    description: Gift card catalog and purchases
  - name: Payouts
    description: >
      Payouts to bank accounts: SEPA Instant in EUR (paid from your Payout SEPA
      balance) and ACH in USD to bank

      accounts in the United States (paid from your Ops Others balance)
  - name: Balance
    description: Operational balances and transaction history
  - name: Webhooks
    description: Webhook endpoints and delivery management
paths:
  /wallets/{code}/withdrawals:
    post:
      tags:
        - Wallets
      summary: Withdraw from a wallet
      description: >
        Withdraws funds from the balance of a wallet of one of your customers,
        to an address of your choice.

        See the [Crypto Wallets guide](/guides/wallets#withdraw-from-a-wallet)
        for the full flow.


        - **Same network, same currency.** The withdrawal is made on the
        blockchain and in the currency of the
          wallet. `address` can be any valid address on that blockchain, except the address of the wallet itself.
        - **Fees.** The commission of your plan (Starter $1 + 1%, Business $1 +
        0.75%, Premium $1 + 0.5%) and the
          network fee of the blockchain are deducted from `amount`. After these fees, you must receive at least
          **$10**. Both are returned by [`GET /wallets/balance`](/api-reference/wallets/balance)
          (`withdrawal_commission` and `withdrawal_network_fee`).
        - **Immediate debit.** `amount` is debited from the balance of the
        wallet as soon as the request is
          accepted. The transfer is sent automatically: the withdrawal is `processing`, then `completed`, and you
          receive the `wallet.withdrawal_completed` webhook when it has been sent on the blockchain.
        - **Safe to retry.** With an `idempotency_key`, calling again with the
        same key on the same wallet returns
          the existing withdrawal with a `200` status: nothing is debited a second time. A new withdrawal answers `201`.
          The same key used again with a different `address` or `amount` is refused (`422`, `details.withdrawal_code`).

        **Protect your API keys.** A withdrawal is made with your API key. API
        calls are only accepted from your

        [allowed IP addresses](/getting-started/api-keys#allowed-ip-addresses)
        (required): keep this list limited to

        your own servers, and keep your keys secret, on those servers only.


        A blockchain transfer cannot be cancelled or reversed. Check the address
        and the blockchain before you call.
      operationId: withdrawFromWallet
      parameters:
        - name: code
          in: path
          required: true
          schema:
            type: string
            format: uuid
          description: >-
            Code of the wallet to withdraw from: the `code` returned when the
            wallet is created (`POST /wallets`).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - address
                - amount
              properties:
                address:
                  type: string
                  description: >-
                    Destination address, on the blockchain of the wallet. It
                    cannot be the address of the wallet itself.
                  example: DESTINATION_SOLANA_ADDRESS
                amount:
                  type: number
                  description: >-
                    Amount debited from the balance of the wallet, in USD, fees
                    included. Must be greater than `0`.
                  example: 100
                idempotency_key:
                  type: string
                  maxLength: 64
                  description: >
                    Optional. Your own unique key for this withdrawal (1 to 64
                    characters), for example the id of the

                    request in your system. The same key on the same wallet
                    returns the existing withdrawal instead of

                    creating a new one.
                  example: payout-5521
      responses:
        '200':
          description: >
            A withdrawal with this `idempotency_key` already exists on this
            wallet. It is returned as is, with its

            current status, and nothing is debited.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WalletWithdrawalCreatedResponse'
              example:
                success: true
                data:
                  code: 7c2d9e41-58b3-4a0f-9d1e-3f6a2b8c4d10
                  wallet_code: 01a11628-4600-7e59-bd4a-01604c588373
                  customer_code: bf75d143-e2ff-4872-8c93-cc6157f834aa
                  idempotency_key: payout-5521
                  blockchain: solana
                  currency: USDC
                  amount: 100
                  commission: 1.5
                  network_fee: 0.5
                  total_fee: 2
                  net_amount: 98
                  to_address: DESTINATION_SOLANA_ADDRESS
                  status: completed
                  tx_id: BLOCKCHAIN_TRANSACTION_ID
                  requested_at: '2026-10-22T10:10:00+00:00'
                  wallet_balance: 245.25
        '201':
          description: >-
            Withdrawal accepted. The balance of the wallet has been debited and
            the transfer is being sent.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WalletWithdrawalCreatedResponse'
              example:
                success: true
                data:
                  code: 7c2d9e41-58b3-4a0f-9d1e-3f6a2b8c4d10
                  wallet_code: 01a11628-4600-7e59-bd4a-01604c588373
                  customer_code: bf75d143-e2ff-4872-8c93-cc6157f834aa
                  idempotency_key: payout-5521
                  blockchain: solana
                  currency: USDC
                  amount: 100
                  commission: 1.5
                  network_fee: 0.5
                  total_fee: 2
                  net_amount: 98
                  to_address: DESTINATION_SOLANA_ADDRESS
                  status: processing
                  tx_id: null
                  requested_at: '2026-10-22T10:10:00+00:00'
                  wallet_balance: 245.25
        '402':
          $ref: '#/components/responses/PlanUpgradeRequired'
        '403':
          $ref: '#/components/responses/AccountSuspended'
        '404':
          description: >-
            `RESOURCE_NOT_FOUND`: no wallet with this code among the wallets of
            your customers.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                success: false
                error:
                  code: RESOURCE_NOT_FOUND
                  message: Wallet not found.
        '422':
          description: >
            Validation error: missing field (`details.missing_fields`), `amount`
            not a positive number, invalid

            `idempotency_key`, `idempotency_key` already used on this wallet for
            a different address or amount

            (`details.withdrawal_code`), address not valid on the blockchain of
            the wallet, address of the wallet itself,

            amount too low after fees (`details`: `commission`, `network_fee`,
            `min_net_amount`), or insufficient

            wallet balance (`details`: `available`, `requested`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                insufficient:
                  summary: Insufficient wallet balance
                  value:
                    success: false
                    error:
                      code: VALIDATION_ERROR
                      message: Insufficient wallet balance.
                      details:
                        available: 45
                        requested: 100
                too_low:
                  summary: Amount too low after fees
                  value:
                    success: false
                    error:
                      code: VALIDATION_ERROR
                      message: >-
                        The amount is too low: after fees ($1.61) you must
                        receive at least $10.00.
                      details:
                        commission: 1.11
                        network_fee: 0.5
                        min_net_amount: 10
                address:
                  summary: Invalid address
                  value:
                    success: false
                    error:
                      code: VALIDATION_ERROR
                      message: >-
                        This is not a valid Solana address. Check the address
                        and the blockchain.
components:
  schemas:
    WalletWithdrawalCreatedResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        data:
          allOf:
            - $ref: '#/components/schemas/WalletWithdrawal'
            - type: object
              properties:
                wallet_balance:
                  type: number
                  description: Current balance of the wallet, in USD, after the debit
                  example: 245.25
        meta:
          $ref: '#/components/schemas/Meta'
    ErrorResponse:
      type: object
      properties:
        success:
          type: boolean
          example: false
        error:
          type: object
          properties:
            code:
              type: string
              description: >
                Error code, for example `AUTHENTICATION_REQUIRED`,
                `AUTHENTICATION_FAILED`, `ACCOUNT_RESTRICTED`,

                `IP_NOT_ALLOWED`, `PLAN_UPGRADE_REQUIRED`, `PLAN_LIMIT_REACHED`,
                `ACCOUNT_SUSPENDED_NEGATIVE_BALANCE`,

                `INSUFFICIENT_BALANCE`, `OPERATION_FAILED`, `FORBIDDEN`,
                `RESOURCE_NOT_FOUND`, `VALIDATION_ERROR`,

                `COUNTRY_NOT_SUPPORTED`, `RATE_LIMIT_EXCEEDED`,
                `INTERNAL_ERROR`, `wrong_api_host`. See [Error
                Handling](/guides/error-handling).
              example: VALIDATION_ERROR
            message:
              type: string
              example: Missing required fields.
            details:
              type: object
              nullable: true
        meta:
          $ref: '#/components/schemas/Meta'
    WalletWithdrawal:
      type: object
      properties:
        code:
          type: string
          format: uuid
          description: Withdrawal code
        wallet_code:
          type: string
          format: uuid
          nullable: true
          description: >-
            Wallet the funds were withdrawn from. `null` for a withdrawal of
            your former collection account (before October 22, 2026).
        customer_code:
          type: string
          format: uuid
          nullable: true
          description: >-
            Customer who owns the wallet. `null` for a withdrawal of your former
            collection account.
        idempotency_key:
          type: string
          nullable: true
          description: >-
            The `idempotency_key` you sent with the request, if any. `null` for
            a withdrawal of your former collection account.
        blockchain:
          type: string
          enum:
            - solana
            - base
            - ethereum
            - tron
        currency:
          type: string
          enum:
            - USDC
            - USDT
        amount:
          type: number
          description: Amount debited from the balance of the wallet
          example: 100
        commission:
          type: number
          description: Withdrawal commission
          example: 1.5
        network_fee:
          type: number
          description: Fixed network fee of the blockchain
          example: 0.5
        total_fee:
          type: number
          example: 2
        net_amount:
          type: number
          description: Amount sent to the destination address
          example: 98
        to_address:
          type: string
          description: Destination address
        status:
          type: string
          enum:
            - processing
            - completed
            - cancelled
          description: '`processing` until the transfer has been sent on the blockchain'
        tx_id:
          type: string
          nullable: true
          description: Blockchain transaction, once the transfer has been sent
        requested_at:
          type: string
          format: date-time
    Meta:
      type: object
      properties:
        request_id:
          type: string
          example: a4f8e2c1b3d97056
        mode:
          type: string
          enum:
            - test
            - live
          example: test
        timestamp:
          type: string
          format: date-time
  responses:
    PlanUpgradeRequired:
      description: The product is not included in your plan
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error:
              code: PLAN_UPGRADE_REQUIRED
              message: >-
                This product is not included in the Découverte plan. Upgrade to
                a paid plan (Starter, Business or Premium) to use "wallets".
              details:
                plan: decouverte
                product: wallets
    AccountSuspended:
      description: >-
        One of your ops balances is negative; every request other than `GET` is
        refused until it is topped up
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error:
              code: ACCOUNT_SUSPENDED_NEGATIVE_BALANCE
              message: >-
                Your account is suspended because one of your ops balances is
                negative. Top up the negative balance to restore access.
                Read-only requests (GET) remain available.
              details:
                negative_balance_since: '2026-10-15T08:00:00+00:00'
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: API key (sk_test_... or sk_live_...)

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.