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

# Transférer vers un compte mobile money

> Verse le montant au bénéficiaire et prélève votre portefeuille du montant plus
la commission.

### Immobilisation

Dès l'acceptation, le montant **et** la commission sont *immobilisés* : ils
quittent votre solde disponible sans encore être débités.

- transfert **exécuté** → ils sont débités, `balance` diminue ;
- transfert **échoué** → l'immobilisation est levée, votre solde retrouve son
  niveau.

C'est ce mécanisme qui vous empêche d'engager deux fois le même solde pendant
qu'un transfert est en cours.

L'issue définitive arrive par notification (`cashout.succeeded` /
`cashout.failed`). Un transfert sans issue au bout de 6 heures passe en
`EXPIRED` et l'immobilisation est levée.

<Warning>
Cet endpoint exige une clé de production (`gk_live_`). Une clé de test est
refusée.
</Warning>


<Warning>
  Le montant **et** la commission sont immobilisés dès l'acceptation : ils quittent `available` sans encore être débités de `balance`. À l'exécution ils sont débités ; en cas d'échec l'immobilisation est levée. Détail des mouvements : [Portefeuille](/guichet/portefeuille#limmobilisation-etape-par-etape).

  Cet endpoint exige une clé de production (`gk_live_`) et l'en-tête `Idempotency-Key`.
</Warning>


## OpenAPI

````yaml POST /cashout
openapi: 3.1.0
info:
  title: Djonanko Guichet API
  version: 1.0.0
  description: >
    API d'agrégation mobile money de Djonanko. Elle permet à une entreprise

    partenaire d'**encaisser** (`cash-in`) et de **transférer** (`cash-out`) sur
    les

    réseaux mobile money d'Afrique de l'Ouest et du Centre, directement depuis
    ses

    propres serveurs.


    Contrairement à l'API Djonanko Pay, le Guichet ne passe **ni par un lien de

    paiement ni par une page hébergée** : vous appelez l'API, le client est
    sollicité

    sur son téléphone, et vous recevez l'issue par notification signée.


    ### Ce qu'il faut retenir avant de commencer


    - **Authentification** : `x-api-key` + `x-api-secret` sur chaque appel.

    - **Montants entiers** : le XOF, le XAF et le GNF n'ont pas de sous-unité.
      `5000` vaut 5 000 FCFA. Aucune décimale n'est acceptée.
    - **Idempotence obligatoire** : l'en-tête `Idempotency-Key` est exigé sur
      `POST /cashin` et `POST /cashout`.
    - **Un portefeuille unique** par compte : les encaissements le créditent,
    les
      transferts le débitent.
    - **Notifications signées** : vérifiez l'en-tête `Djonanko-Signature` avant
    de
      traiter.

    Toutes les réponses sont en JSON. Chaque réponse porte un en-tête

    `x-request-id` à citer dans vos demandes de support.
  contact:
    name: Support Djonanko
    url: https://www.djonanko.ci/#contact
servers:
  - url: https://guichet.apidjonanko.tech/v1
    description: Production
security:
  - ApiKey: []
    ApiSecret: []
tags:
  - name: Encaissement
    description: Débiter un compte mobile money vers votre portefeuille.
  - name: Transfert
    description: Créditer un compte mobile money depuis votre portefeuille.
  - name: Opérations
    description: Consulter l'état et l'historique de vos opérations.
  - name: Portefeuille
    description: Solde et relevé des mouvements.
  - name: Compte
    description: Création de compte, profil, clés d'API.
  - name: Sécurité
    description: Adresses IP autorisées.
  - name: Notifications
    description: Configuration, supervision et rejeu des notifications sortantes.
paths:
  /cashout:
    post:
      tags:
        - Transfert
      summary: Transférer vers un compte mobile money
      description: >
        Verse le montant au bénéficiaire et prélève votre portefeuille du
        montant plus

        la commission.


        ### Immobilisation


        Dès l'acceptation, le montant **et** la commission sont *immobilisés* :
        ils

        quittent votre solde disponible sans encore être débités.


        - transfert **exécuté** → ils sont débités, `balance` diminue ;

        - transfert **échoué** → l'immobilisation est levée, votre solde
        retrouve son
          niveau.

        C'est ce mécanisme qui vous empêche d'engager deux fois le même solde
        pendant

        qu'un transfert est en cours.


        L'issue définitive arrive par notification (`cashout.succeeded` /

        `cashout.failed`). Un transfert sans issue au bout de 6 heures passe en

        `EXPIRED` et l'immobilisation est levée.


        <Warning>

        Cet endpoint exige une clé de production (`gk_live_`). Une clé de test
        est

        refusée.

        </Warning>
      operationId: createCashout
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
        - $ref: '#/components/parameters/RequestId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - amount
                - country
                - operator
                - beneficiaryPhone
                - beneficiaryName
              properties:
                amount:
                  type: integer
                  minimum: 1
                  description: Montant à verser au bénéficiaire, en unités entières.
                  example: 25000
                country:
                  $ref: '#/components/schemas/Country'
                operator:
                  $ref: '#/components/schemas/Operator'
                beneficiaryPhone:
                  type: string
                  maxLength: 24
                  description: Numéro mobile money du bénéficiaire.
                  example: '0501020304'
                beneficiaryName:
                  type: string
                  maxLength: 160
                  description: >
                    Nom du bénéficiaire. Exigé par les opérateurs et repris sur
                    votre relevé.
                  example: Koffi Yao
                externalReference:
                  type: string
                  maxLength: 120
                  description: >
                    Votre identifiant d'opération. Unique sur votre compte :
                    c'est votre garde-fou contre le double décaissement.
                  example: PAIE-2026-03-0042
                description:
                  type: string
                  maxLength: 200
                  example: Salaire mars 2026
                callbackUrl:
                  type: string
                  format: uri
                  description: >-
                    URL de notification propre à cette opération. HTTPS
                    obligatoire.
                metadata:
                  type: object
                  additionalProperties: true
            examples:
              salaire:
                summary: Transfert Wave
                value:
                  amount: 25000
                  country: CI
                  operator: WAVE
                  beneficiaryPhone: '0501020304'
                  beneficiaryName: Koffi Yao
                  externalReference: PAIE-2026-03-0042
                  description: Salaire mars 2026
      responses:
        '200':
          description: Rejeu idempotent — la réponse initiale est renvoyée.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OperationEnvelope'
        '201':
          description: Transfert accepté et immobilisation posée.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OperationEnvelope'
              example:
                operation:
                  reference: GUI-CO-20261001-4F7K2M9Q
                  type: CASHOUT
                  status: PENDING
                  amount: 25000
                  fees: 500
                  netAmount: 25500
                  currency: XOF
                  country: CI
                  operator: WAVE
                  counterparty:
                    phoneNumber: '+2250501020304'
                    name: Koffi Yao
                  externalReference: PAIE-2026-03-0042
                  description: Salaire mars 2026
                  payerActionUrl: null
                  requiresPayerAction: false
                  failure: null
                  metadata: null
                  createdAt: '2026-10-01T11:01:50.000Z'
                  updatedAt: '2026-10-01T11:01:52.000Z'
                  completedAt: null
                  expiresAt: '2026-10-01T17:01:50.000Z'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '403':
          $ref: '#/components/responses/Forbidden'
        '409':
          $ref: '#/components/responses/Conflict'
        '422':
          $ref: '#/components/responses/Unprocessable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '503':
          $ref: '#/components/responses/Unavailable'
components:
  parameters:
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: true
      description: >
        Clé unique de votre côté, propre à cette intention d'opération. Un
        second appel portant la même clé et le même corps renvoie la réponse
        initiale sans rien réexécuter. 120 caractères maximum, conservée 24
        heures.
      schema:
        type: string
        maxLength: 120
        example: cmd-184-tentative-1
    RequestId:
      name: x-request-id
      in: header
      required: false
      description: >
        Identifiant de corrélation de votre choix. Repris tel quel dans la
        réponse et dans nos journaux. À défaut, nous en générons un.
      schema:
        type: string
        maxLength: 200
  schemas:
    Country:
      type: string
      description: Pays, en ISO 3166-1 alpha-2.
      enum:
        - CI
        - BF
        - ML
        - SN
        - TG
        - BJ
        - NE
        - CM
        - GN
      example: CI
    Operator:
      type: string
      description: >
        Opérateur mobile money. Tous ne sont pas disponibles dans tous les pays
        — voir le guide « Pays et opérateurs ».
      enum:
        - ORANGE
        - MTN
        - MOOV
        - WAVE
        - DJAMO
      example: ORANGE
    OperationEnvelope:
      type: object
      properties:
        operation:
          $ref: '#/components/schemas/Operation'
    Operation:
      type: object
      description: >
        Représentation d'une opération. C'est la forme renvoyée par les
        endpoints de création, de consultation, et dans le corps des
        notifications.
      properties:
        reference:
          type: string
          description: >
            Référence Djonanko de l'opération. C'est l'identifiant à conserver
            et à citer. Préfixée `GUI-CI-` pour un encaissement, `GUI-CO-` pour
            un transfert.
          example: GUI-CI-20261001-7K2M9QX4
        type:
          $ref: '#/components/schemas/OperationType'
        status:
          $ref: '#/components/schemas/OperationStatus'
        amount:
          type: integer
          description: Montant demandé, en unités entières.
          example: 5000
        fees:
          type: integer
          description: Commission Djonanko, figée à la création de l'opération.
          example: 100
        netAmount:
          type: integer
          description: >
            Impact sur votre portefeuille. Sur un encaissement, ce qui vous est
            crédité (`amount − fees`). Sur un transfert, ce qui vous est prélevé
            (`amount + fees`).
          example: 4900
        currency:
          $ref: '#/components/schemas/Currency'
        country:
          $ref: '#/components/schemas/Country'
        operator:
          $ref: '#/components/schemas/Operator'
        counterparty:
          $ref: '#/components/schemas/Counterparty'
        externalReference:
          type:
            - string
            - 'null'
          description: Votre propre référence, telle que vous l'avez transmise.
          example: CMD-2026-00184
        description:
          type:
            - string
            - 'null'
          example: Commande 184
        payerActionUrl:
          type:
            - string
            - 'null'
          description: >
            URL sur laquelle envoyer le payeur. Renseignée uniquement quand
            l'opérateur exige une redirection. `null` sur un transfert.
          example: https://pay.example.com/s/abc123
        requiresPayerAction:
          type: boolean
          description: >
            `true` si l'encaissement attend une action du payeur sur
            `payerActionUrl`.
          example: true
        failure:
          type:
            - object
            - 'null'
          description: Renseigné uniquement si l'opération a échoué.
          properties:
            code:
              $ref: '#/components/schemas/OperationFailureCode'
            message:
              type: string
              example: Le solde du compte mobile money du payeur est insuffisant.
        metadata:
          type:
            - object
            - 'null'
          description: Vos données libres, restituées telles quelles.
          additionalProperties: true
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
        completedAt:
          type:
            - string
            - 'null'
          format: date-time
          description: Horodatage du passage à un état définitif.
        expiresAt:
          type:
            - string
            - 'null'
          format: date-time
          description: >
            Au-delà, une opération sans issue passe en `EXPIRED`. 30 minutes
            pour un encaissement, 6 heures pour un transfert.
    Error:
      type: object
      description: Forme de toutes les réponses d'erreur.
      properties:
        success:
          type: boolean
          enum:
            - false
        error:
          type: object
          properties:
            code:
              type: string
              description: >
                Code stable. **Branchez votre logique dessus**, jamais sur
                `message`, qui peut être reformulé.
              example: INSUFFICIENT_BALANCE
            message:
              type: string
              example: Le solde disponible de votre portefeuille est insuffisant.
            details:
              type:
                - object
                - 'null'
              description: Contexte complémentaire, variable selon le code.
              additionalProperties: true
        requestId:
          type: string
          description: Également renvoyé dans l'en-tête `x-request-id`.
          example: 9f1c2b7e-4a5d-4c8f-b0a1-e2d3c4b5a697
        timestamp:
          type: string
          format: date-time
    OperationType:
      type: string
      enum:
        - CASHIN
        - CASHOUT
    OperationStatus:
      type: string
      description: >
        État d'une opération.


        - `CREATED` — enregistrée, pas encore soumise

        - `PENDING` — soumise, en attente d'issue

        - `AWAITING_PAYER` — encaissement : le payeur doit agir

        - `SUCCEEDED` — aboutie *(définitif)*

        - `FAILED` — refusée *(définitif)*

        - `EXPIRED` — aucune issue dans le délai *(définitif)*

        - `CANCELLED` — annulée avant exécution *(définitif)*

        - `REVERSED` — contre-passée *(définitif)*


        Une opération réussie ne repasse jamais en échec. Le seul mouvement
        possible

        depuis `SUCCEEDED` est `REVERSED`.
      enum:
        - CREATED
        - PENDING
        - AWAITING_PAYER
        - SUCCEEDED
        - FAILED
        - EXPIRED
        - CANCELLED
        - REVERSED
    Currency:
      type: string
      description: >
        Devise. Aucune n'a de sous-unité : les montants sont toujours des
        entiers.
      enum:
        - XOF
        - XAF
        - GNF
      example: XOF
    Counterparty:
      type: object
      description: Le payeur sur un encaissement, le bénéficiaire sur un transfert.
      properties:
        phoneNumber:
          type: string
          description: Numéro normalisé au format E.164.
          example: '+2250701020304'
        name:
          type:
            - string
            - 'null'
          example: Aya Koné
    OperationFailureCode:
      type: string
      description: >
        Cause de l'échec d'une opération.


        - `OPERATOR_INSUFFICIENT_FUNDS` — solde mobile money insuffisant

        - `OPERATOR_ACCOUNT_UNKNOWN` — compte inconnu ou inactif

        - `OPERATOR_ACCOUNT_LIMIT_REACHED` — plafond du compte atteint

        - `PAYER_CANCELLED` — le payeur a refusé

        - `OPERATOR_TIMEOUT` — l'opérateur n'a pas répondu

        - `OPERATOR_REFUSED` — refus sans motif précis

        - `UPSTREAM_UNAVAILABLE` — indisponibilité temporaire

        - `SETTLEMENT_ACCOUNT_UNAVAILABLE` — indisponibilité temporaire côté
        Djonanko

        - `INTERNAL_ERROR` — erreur interne
      enum:
        - OPERATOR_INSUFFICIENT_FUNDS
        - OPERATOR_ACCOUNT_UNKNOWN
        - OPERATOR_ACCOUNT_LIMIT_REACHED
        - PAYER_CANCELLED
        - OPERATOR_TIMEOUT
        - OPERATOR_REFUSED
        - UPSTREAM_UNAVAILABLE
        - SETTLEMENT_ACCOUNT_UNAVAILABLE
        - INTERNAL_ERROR
  responses:
    BadRequest:
      description: Requête invalide (`VALIDATION_ERROR`, `IDEMPOTENCY_KEY_REQUIRED`).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            success: false
            error:
              code: VALIDATION_ERROR
              message: La requête est invalide.
              details:
                fields:
                  - amount must be an integer number
            requestId: 9f1c2b7e-4a5d-4c8f-b0a1-e2d3c4b5a697
            timestamp: '2026-10-01T10:12:04.000Z'
    Unauthorized:
      description: Identifiants absents ou invalides.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            success: false
            error:
              code: INVALID_CREDENTIALS
              message: Identifiants API invalides.
            requestId: 9f1c2b7e-4a5d-4c8f-b0a1-e2d3c4b5a697
            timestamp: '2026-10-01T10:12:04.000Z'
    PaymentRequired:
      description: Solde disponible insuffisant.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            success: false
            error:
              code: INSUFFICIENT_BALANCE
              message: Le solde disponible de votre portefeuille est insuffisant.
              details:
                available: 12000
                required: 25500
                currency: XOF
            requestId: 9f1c2b7e-4a5d-4c8f-b0a1-e2d3c4b5a697
            timestamp: '2026-10-01T10:12:04.000Z'
    Forbidden:
      description: >
        Compte non activé ou suspendu (`ACCOUNT_SUSPENDED`), adresse IP non
        déclarée (`IP_NOT_ALLOWED`), portefeuille gelé (`WALLET_FROZEN`).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Conflict:
      description: >
        Clé d'idempotence réutilisée avec un corps différent
        (`IDEMPOTENCY_KEY_REUSED`), requête identique en cours
        (`IDEMPOTENT_REQUEST_IN_FLIGHT`), ou référence externe déjà prise
        (`DUPLICATE_EXTERNAL_REFERENCE`).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unprocessable:
      description: >
        Montant hors bornes, couple pays / opérateur indisponible, ou numéro
        invalide.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    TooManyRequests:
      description: Débit dépassé.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unavailable:
      description: >
        Indisponibilité temporaire. **Réessayez avec la même clé d'idempotence**
        : l'opération n'a peut-être pas été enregistrée.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    ApiKey:
      type: apiKey
      in: header
      name: x-api-key
      description: Votre clé publique, préfixée `gk_live_` (ou `gk_test_`).
    ApiSecret:
      type: apiKey
      in: header
      name: x-api-secret
      description: >
        Votre secret, préfixé `gs_live_` (ou `gs_test_`). Affiché une seule
        fois, à l'émission de la clé. Il ne doit jamais quitter vos serveurs.

````

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