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

# Virer entre deux soldes

> Déplace un montant entre deux de vos soldes mobile money du même pays et de la même devise, par exemple de MTN vers Orange au Cameroun, pour qu'un retrait puisse partir vers l'un ou l'autre. Immédiat et sans frais. Un solde carte ne peut pas y prendre part. Le solde débité doit couvrir le montant, retraits déjà validés déduits.

Utile quand vos clients paient surtout par un opérateur et que vous voulez retirer vers un autre : le montant passe d’un solde à l’autre tout de suite, sans frais. Les deux soldes doivent être du même pays et de la même devise.


## OpenAPI

````yaml POST /api/v1/wallet_transfers
openapi: 3.1.0
info:
  title: API Mercy Pay
  version: 1.0.0
  description: >-
    Encaissez par mobile money et par carte, facturez en récurrent et versez vos
    fonds. Les montants sont des entiers en unités mineures. Chaque réponse
    porte un en-tête `Request-Id`.
servers:
  - url: https://mercy-pay.com
    description: >-
      Production. La clé choisit l'environnement : `mp_sandbox_…` ou
      `mp_live_…`.
security:
  - bearerAuth: []
tags:
  - name: Compte
  - name: Sessions de paiement
  - name: Paiements
  - name: Remboursements
    description: Rendre un paiement au client, en entier.
  - name: Liens de paiement
  - name: Plans
  - name: Abonnements
  - name: Clients
  - name: Factures
  - name: Espace client
  - name: Soldes
  - name: Retraits
  - name: État des opérateurs
  - name: Événements
    description: Tout ce qui s'est passé sur le compte, envoyé ou non à un endpoint.
  - name: Endpoints de webhook
    description: Les URL de votre serveur qui reçoivent les événements.
paths:
  /api/v1/wallet_transfers:
    post:
      tags:
        - Soldes
      summary: Virer entre deux soldes
      description: >-
        Déplace un montant entre deux de vos soldes mobile money du même pays et
        de la même devise, par exemple de MTN vers Orange au Cameroun, pour
        qu'un retrait puisse partir vers l'un ou l'autre. Immédiat et sans
        frais. Un solde carte ne peut pas y prendre part. Le solde débité doit
        couvrir le montant, retraits déjà validés déduits.
      operationId: createWalletTransfer
      parameters:
        - $ref: '#/components/parameters/IdempotencyKeyRequired'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - from_wallet
                - to_wallet
                - amount
              properties:
                from_wallet:
                  type: string
                  description: >-
                    Le solde à débiter (`wal_…`), voir [Lister les
                    soldes](/api/wallets/list)
                to_wallet:
                  type: string
                  description: Le solde à créditer (`wal_…`)
                amount:
                  type: integer
                  minimum: 1
                  description: En unités mineures
            example:
              from_wallet: wal_5e0c8a7b3d1f4a2e9c648b7f0d2e1a93
              to_wallet: wal_0b76919140c74c4c99d52f5c1734b743
              amount: 25000
      responses:
        '201':
          description: Le virement fait
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/WalletTransfer'
        '400':
          $ref: '#/components/responses/IdempotencyMissing'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          description: Solde insuffisant ou opérateur invalide
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  type: invalid_request_error
                  code: validation_failed
                  message: Solde disponible insuffisant pour ce montant.
                  param: amount
                  doc_url: >-
                    https://docs.mercy-pay.com/developers/errors#validation_failed
                  request_id: req_01jc8x4m2v7t9qk3n5w6y8z0ab
        '429':
          $ref: '#/components/responses/RateLimited'
components:
  parameters:
    IdempotencyKeyRequired:
      name: Idempotency-Key
      in: header
      required: true
      schema:
        type: string
        maxLength: 255
      description: >-
        Obligatoire ici. Une clé unique par opération : la rejouer pendant 24
        heures renvoie la même réponse sans rien créer de plus. Voir
        [Idempotence](/developers/idempotency).
  schemas:
    WalletTransfer:
      type: object
      properties:
        id:
          type: string
          description: Identifiant du virement (`wtr_…`)
        object:
          type: string
          enum:
            - wallet_transfer
        livemode:
          type: boolean
        created:
          type: string
          format: date-time
        from_wallet:
          type: string
          description: Le solde débité (`wal_…`)
        to_wallet:
          type: string
          description: Le solde crédité (`wal_…`)
        amount:
          type: integer
        currency:
          type: string
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            type:
              type: string
              enum:
                - authentication_error
                - invalid_request_error
                - idempotency_error
                - payment_error
                - rate_limit_error
                - api_error
            code:
              type: string
              description: Code stable, à tester dans votre code
            message:
              type: string
              description: Explication en français, pour un humain
            param:
              type:
                - string
                - 'null'
              description: Le premier champ en cause
            doc_url:
              type: string
              description: Explication de ce code
            request_id:
              type: string
              description: >-
                Identifiant de la requête (`req_…`), aussi dans l'en-tête
                `Request-Id`
            errors:
              type: object
              additionalProperties:
                type: array
                items:
                  type: string
              description: Détail par champ refusé, sur une erreur `422`
      required:
        - error
  responses:
    IdempotencyMissing:
      description: '`Idempotency-Key` absent'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              type: idempotency_error
              code: idempotency_key_missing
              message: L'en-tête Idempotency-Key est obligatoire.
              param: null
              doc_url: >-
                https://docs.mercy-pay.com/developers/errors#idempotency_key_missing
              request_id: req_01jc8x4m2v7t9qk3n5w6y8z0ab
    Unauthorized:
      description: Clé absente, invalide ou révoquée
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              type: authentication_error
              code: api_key_invalid
              message: Clé API invalide.
              param: null
              doc_url: https://docs.mercy-pay.com/developers/errors#api_key_invalid
              request_id: req_01jc8x4m2v7t9qk3n5w6y8z0ab
    Forbidden:
      description: Compte suspendu, ou clé live avant l'approbation du KYC
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              type: authentication_error
              code: live_mode_requires_kyc
              message: Le mode live demande un KYC approuvé.
              param: null
              doc_url: >-
                https://docs.mercy-pay.com/developers/errors#live_mode_requires_kyc
              request_id: req_01jc8x4m2v7t9qk3n5w6y8z0ab
    RateLimited:
      description: Plus de 60 requêtes par minute avec cette clé
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              type: rate_limit_error
              code: rate_limited
              message: Trop de requêtes.
              param: null
              doc_url: https://docs.mercy-pay.com/developers/errors#rate_limited
              request_id: req_01jc8x4m2v7t9qk3n5w6y8z0ab
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        Votre clé API. Utilisez une clé sandbox (`mp_sandbox_…`) pour essayer :
        aucun argent réel ne bouge.

````

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