Skip to main content

API Documentation

Complete reference for Chari Money's Banking-as-a-Service API. Integrate financial services into your applications with our robust and secure endpoints.

Getting Started

Version 2.3 · Last updated July 29, 2026

Welcome to the official documentation for Chari Money's Banking-as-a-Service (BAAS) API. This RESTful API empowers fintechs, platforms, and developers to integrate a complete financial infrastructure into their applications: account opening with KYC verification, wallet-to-wallet transactions, card deposits (3D Secure), bank wire transfers via RIB, multi-channel merchant payments (phone, QR Code, card), beneficiary management, retail agents, and real-time webhooks. All endpoints follow a preview/execute model with asynchronous webhook confirmation.

Authentication Headers

Include the following headers with all API requests:

HeaderTypeRequiredDescription
Chari-Api-KeystringRequiredAPI key for authentication. Provided by Chari for each environment (sandbox / production).
C-Request-IdstringOptionalUnique ID per request for tracing. Echoed back in the response. Recommended format: UUID v4. Ex: 69906411-0aa24a89-ab2005ca-9d18dc15

Test Credit Card (Sandbox)

PAN

Click to copy

CVV

Click to copy

Expiry

Click to copy — API: 2608 (or any future date)

3DS Code

Click to copy

New

LLM & AI Pack

Complete pack optimized for LLMs and AI assistants: Markdown documentation, JSON Schemas, Mermaid diagrams, OpenAPI 3.0 spec, cURL examples and validation rules. Ideal for RAG, code generation and integration with Cursor, Copilot or Claude.

OpenAPI 3.0JSON SchemaMermaidMarkdowncURL
Download .zip

Interactive Reference (Swagger UI)

Browse the 114 operations and their schemas in Swagger UI, hosted on this site and generated from the production API.

Open the reference

OpenAPI Specification (Swagger)

OpenAPI 3.0 specification of the partner API, generated from the production API: 114 partner operations, full schemas, ready for Swagger UI, Postman or client generation.

Download OpenAPI

Postman Collection

Download the full Postman collection to test all API endpoints.

Download

Changelog

v1.8

2025-11-05

Initial documentation. Full API v1.8 coverage.

v1.8.1

2025-12-01

Added merchant-kyc-upload endpoint. Enriched reference tables (docTypes, customerStatuses, accountLevels). Detailed error codes with endpoint mapping. autoActivate parameter on confirm. Fixed confirm route.

v1.9

2026-04-14

Added Simulation (Sandbox) section. New Operation Types: 10=RECHARGE, 25=BILL_PAYMENT; renamed 5→MOBILE_PAYMENT, 24→CARD_PAYMENT. Transaction Status standardized: OPEN/COMPLETED/FAILED/CANCELED. Webhooks simplified: added payment.received, removed operation.created/operation.updated/customer.kyc/bank-transfer.failed. CashIn/CashOut reference format is now numeric (e.g. 1122334455).

v2.0

2026-06-04

Upgraded to v2.0 documentation (Preliminary Release). Added the "Card Management" section (beta): programs, applications, cards, card actions, usage control, transactions and card enums. The card section is preliminary and will be enriched with the missing endpoints — it may contain errors.

v2.1

2026-06-19

Added three new modules: Telco Top-up (catalog + recharge), Vouchers (catalog, brands, purchase preview/confirm) and Bill Payment (Fatourati network: creditors, receivables, dynamic form, unpaid items, confirmation, + webhooks). Added the dedicated Fatourati CashIn endpoint and operation type 23 = VOUCHER.

v2.2

2026-06-24

Documented the KYB documents required to create a merchant wallet, by professional client type (legal entity, individual professional, foundation / association) — added as notes on the "Merchant KYC Upload" endpoint.

v2.3

2026-07-29

Aligned with the production API, keeping the partner scope unchanged. New: merchant card payment lifecycle (capture, authorization reversal, refund), QR-by-reference payment status, agent-side tokenized cards, and extensions for bills (favorites, history, receipts, preview, reference status), telco (customer top-up, history, catalog, export) and vouchers (local catalog, products). Realigned routes: /api/fatourati/* → /api/bills/*, B2B top-up moved, card transactions via /api/card-transactions, card payment preview, principal agent by code (path), account upgrade now PUT. Card actions split into 5 dedicated endpoints. Removed endpoints deleted (C-Request-Id lookup, card program by Id). Parameters of 19 sheets realigned with production. Downloadable OpenAPI specification and Postman collection, regenerated from the production API; LLM pack v2.3.

O

Overview — M-Wallet in Morocco

What is an M-Wallet?

An M-Wallet (Mobile Wallet) is a regulated electronic money account that allows individuals and merchants to perform financial transactions using a mobile number as an identifier. It is part of the Bank Al-Maghrib (BAM) national framework for financial inclusion and digital payments. Each wallet is linked to a verified user identity (KYC) and stored under our Payment Institution license (CHARI MONEY) supervised by Bank Al-Maghrib.

Core Principles

Unique Wallet ID

The user's MSISDN (Mobile Number) serves as the wallet identifier.

Interoperable Network

All M-Wallets can exchange money between different providers through the national switch.

KYC Levels

Account permissions and limits depend on the user's verification (CIN, selfie, proof of address, etc.).

Real-Time Operations

Transfers, cash-in/out, merchant payments, and bill payments are executed instantly with confirmation.

Account Types

TypeOwnerDescriptionOperations
Consumer (Particulier)IndividualsPersonal wallet linked to one mobile number and national ID.Cash-in/out, P2P transfers, merchant payments, other payment services.
Merchant (Commerçant)Small business, shop, or service providerBusiness wallet linked to a merchant account or store.Receive payments, transfer to bank, refund customer, other payment services.
Agent RetailAuthorized agent network/partnerUsed by distribution agents to facilitate cash-in/out for users.Load/unload customer wallets.
Agent PrincipalPartner / EDPDedicated wallet for enterprises with higher limits and integration solutions.Mass payouts, salary disbursements, collections, multiple other operations.

Account Levels

LevelKYC RequirementBalance Limit
Level 1Name + valid phone + CIN number1,000 MAD
Level 2Full KYC (CIN + selfie or document scan)4,000 MAD
Level 3Verified ID (KYC), Interview, Digital customer record20,000 MAD
Level 4Full KYC, Interview, Digital customer record, Proof of income, Proof of address100,000 MAD
MerchantFull KYB + Business registration (IF/RC)Negotiated
G

Glossary

TermDefinition
M-WalletA regulated electronic money account linked to a mobile number, allowing users to perform financial transactions such as transfers, payments, and cash operations.
WalletA user account within the system that stores electronic money and is associated with a unique identifier (MSISDN).
MSISDNMobile phone number used as the primary identifier of a wallet.
KYC (Know Your Customer)Verification process used to identify and validate a user's identity according to regulatory requirements.
KYC LevelRegulatory level assigned to a wallet based on verification status, defining transaction and balance limits.
OperationA high-level business action initiated by a user or partner (e.g., cash-in, transfer, payment).
TransactionA financial movement (debit, credit, fees, adjustment) generated as part of an operation.
Operation TypeCategory of business action (e.g., CASHIN, TRANSFER, PAYMENT).
Transaction TypeType of financial movement associated with an operation (e.g., debit, credit, fees).
Operation StatusCurrent lifecycle state of an operation (e.g., OPEN, COMPLETED, FAILED).
Transaction StatusProcessing state of a transaction (e.g., COMPLETED, FAILED).
ReferenceA unique identifier generated for a pending operation (e.g., cash-in/out), used to complete the transaction through an external network.
Agent / NetworkAuthorized third-party entity or distribution channel used to execute cash-in and cash-out operations.
API KeySecure token used to authenticate partner requests to the BAAS API.
WebhookAutomated HTTP callback sent by the system to notify partners about operation or transaction updates.
I

Integration Guides

Step-by-step journeys per use case, composed from the endpoints documented below: from sandbox onboarding to the full merchant payment lifecycle.

Getting started in sandbox: access, activations, first calls

Everything to obtain and verify BEFORE integrating: API key, modules enabled for your account, test float. Following this guide avoids the most common false blockers (404 on a non-enabled module, empty catalogs, wallets not found).

Prerequisites

  • A contact with the Chari team (the technical integration form is provided when your file is opened).
  1. 1
    Get sandbox access

    Fill in the “Get sandbox access” form at the very bottom of this page (direct link: #sandbox-access). You receive in return: your sandbox API key (shared through a one-time secure link) and an invitation to the Partner Back Office. The sandbox base URL is https://sandbox.charimoney.com; the production URL is communicated after your tests are validated.

  2. 2
    Validate the key: first call

    Every request carries the Chari-Api-Key header (required) and ideally a unique C-Request-Id (UUID v4) for tracing. Test your key with a call that has no precondition:

    bash
    curl -X 'GET' \
      'https://sandbox.charimoney.com/api/customers/status?phoneNumber=+2126xxxxxxxx' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID'
    Response
    json
    {
      "data": {
        "status": 0,
        "message": "Not exists"
      }
    }
  3. 3
    Have the required modules enabled

    Some modules are enabled by the Chari team for your partner account, on request: telco top-up, bill payment, vouchers (catalog provisioned in sandbox), card gateway, and the webhook key (X-Api-Key) to receive notifications. Your API key scopes also delimit the reachable endpoints. Request the activations matching your use cases as soon as the account is opened — the symptoms of a non-enabled module are listed below.

    Erreur métierTelco top-up: service not enabled for your account — request operator activation.
    200/204 videEmpty voucher catalog: brands must be provisioned in sandbox by Chari.
    403missing scopes — the endpoint requires a scope your key does not carry (e.g. operations:admin-read on GET /api/operations/all).
  4. 4
    Request test float

    To execute debit operations (transfers, bill payments, top-ups, vouchers), your principal agent must be funded. Give your Chari contact your principal agent code (and partner id) to credit a test float in sandbox.

  5. 5
    Use the test card (3D Secure)

    Card deposits and payments in sandbox use the test card documented at the top of this page: PAN 4918914107195005, CVV 123, expiry 08/26 (or any future date), 3DS code 555.

  6. 6
    Tool up your integration

    Download from this page the OpenAPI specification (generated from production), the Postman collection (114 ready-made requests, {{host}} and {{apiKey}} variables) and the LLM pack if you work with AI assistants. They are strictly aligned with this documentation.

  7. 7
    Prepare the move to production

    Once your sandbox tests are validated: provide the list of your public IPs or domains for whitelisting, then receive your production API key and the live base URL. Keys are per-environment — never reuse the sandbox key in production.

Create and activate a customer wallet end to end

The full journey of a customer M-Wallet: check the number status, register the customer (walletType), confirm the OTP (with or without autoActivate), create the PIN, verify login, then read the balance and profile. Each step lists the documented typical error codes (e.g. 20005 user not found, 26005 invalid PIN format).

Prerequisites

  • A valid sandbox API key and the Chari-Api-Key + C-Request-Id headers on every request (see the "Getting started in sandbox" guide).
  • A Moroccan test number in +212********* format not yet registered (status 0 expected at step 1).
  1. 1
    Check the number status

    Before any registration, query the number status with Chari. The response returns a status from 0 to 5: 0 Not exists (the number does not exist with ChariMoney), 1 Not confirmed (OTP not entered), 2 Confirmed (registered with Switch), 3 Active (PIN created), 4 Locked temporary (max attempts exceeded), 5 Locked. For a new customer, expect 0:

    bash
    curl -X 'GET' \
      'https://sandbox.charimoney.com/api/customers/status?phoneNumber=+2126xxxxxxxx' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID'
    Response
    json
    {
      "data": {
        "status": 0,
        "message": "Not exists"
      }
    }
    20005The specified user could not be found.
  2. 2
    Register the customer (walletType)

    Start the registration with the phone number, first and last name (minimum 2 letters, latin characters only), the cin (minimum 5 characters) and the walletType: "P" for an individual, "C" for a merchant. An OTP is sent to the customer via SMS and the API responds 202. Optional: closeLoopOnly set to true enrolls the customer in CloseLoop mode only — in that case the OTP is sent directly by CHARI.

    bash
    curl --location 'https://sandbox.charimoney.com/api/customers/register' \
      --header 'Chari-Api-Key: YOUR_API_KEY' \
      --header 'C-Request-Id: YOUR_REQUEST_ID' \
      --header 'Content-Type: application/json' \
      --data '{
        "phoneNumber": "+2126xxxxxxxx",
        "firstName": "Mohammed",
        "lastName": "Chairi",
        "cin": "K000000",
        "walletType": "P"
      }'
    Response
    json
    {
      "data": true
    }
    20000The phone number format is invalid (expected: +212*********).
    20006The initial parameters provided are incorrect or invalid.
    20008Registration is temporarily locked due to security or policy restrictions.
    20009The request is pending confirmation. Please wait for further processing.
  3. 3
    Confirm the OTP (autoActivate)

    Confirm the registration by submitting the OTP code received via SMS (format xxx-xxx). The optional autoActivate field (default: false) decides what follows: if false, the user must complete activation by setting a PIN (next step); if true, the wallet is activated automatically, without requiring a PIN. Do not send walletType here: the wallet type is set at registration. If the customer did not receive the code, resend it via POST /api/customers/confirm/resend-otp.

    bash
    curl --location 'https://sandbox.charimoney.com/api/customers/confirm' \
      --header 'Chari-Api-Key: YOUR_API_KEY' \
      --header 'C-Request-Id: YOUR_REQUEST_ID' \
      --header 'Content-Type: application/json' \
      --data '{
        "phoneNumber": "+2126xxxxxxxx",
        "code": "365-768"
      }'
    Response
    json
    {
      "data": true
    }
    20000The phone number format is invalid.
    20017There is no pending request associated with the provided phone number — redo the Register step.
  4. 4
    Create the PIN to activate the wallet

    If you did not use autoActivate, set the customer's PIN (4 digits required) to finalize activation. Once the PIN is created, the number status (step 1) becomes 3: Active — registered with Switch and active with ChariMoney.

    bash
    curl -X 'POST' \
      'https://sandbox.charimoney.com/api/customers/pin' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID' \
      -H 'Content-Type: application/json' \
      -d '{
        "phoneNumber": "+2126xxxxxxxx",
        "pin": "0000"
      }'
    Response
    json
    {
      "data": true
    }
    26004A PIN has already been set for this wallet — use Update PIN or Reset PIN.
    26005The provided PIN does not meet the required format (must be a 4-digit number).
  5. 5
    Verify login with the PIN

    Authenticate the customer with their PIN to validate the activation. The response indicates logged (true if authentication succeeded) and remainingAttempts (number of remaining attempts before account lockout).

    bash
    curl -X 'POST' \
      'https://sandbox.charimoney.com/api/customers/login' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID' \
      -H 'Content-Type: application/json' \
      -d '{
        "phoneNumber": "+2126xxxxxxxx",
        "pin": "0000"
      }'
    Response
    json
    {
      "data": {
        "logged": true,
        "remainingAttempts": 5
      }
    }
    20005The specified user could not be found — check the number and the status (step 1).
    26001The entered PIN is incorrect — watch remainingAttempts to avoid lockout.
  6. 6
    Read the wallet balance

    The activated wallet is queried by phone number: the response returns the current balance of the registered customer's wallet.

    bash
    curl -X 'GET' \
      'https://sandbox.charimoney.com/api/customers/balance?phoneNumber=+2126xxxxxxxx' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID'
    Response
    json
    {
      "data": {
        "balance": 174.0
      }
    }
    20005The specified user could not be found.
  7. 7
    Retrieve the full customer profile

    To go further, retrieve the customer's detailed profile: identity, balance, rib associated with the wallet, accountLevel (KYC level 1 to 4 — see the "Account Levels" table), customerStatus (same values as the status in step 1) and associated partner information.

    bash
    curl -X 'GET' \
      'https://sandbox.charimoney.com/api/customers/info?phoneNumber=+2126xxxxxxxx' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID'
    Response
    json
    {
      "data": {
        "id": 72,
        "fullName": "Mohammed Chairi",
        "firstName": "Mohammed",
        "lastName": "Chairi",
        "phoneNumber": "+2126xxxxxxxx",
        "balance": 78,
        "accountType": 2,
        "rib": "82764000001000000000xxxx",
        "accountLevel": 1,
        "customerStatus": 3,
        "partnerId": 1
      }
    }
    20005The specified user could not be found.

Card deposit with 3D Secure: from preview to webhook

Credit a customer's wallet from a payment card: fee preview, execution with the sandbox test card, 3D Secure authentication, cashin.card.authorized webhook notification — then the agent and tokenized-card variants.

Prerequisites

  • An active sandbox API key (see the "Getting started in sandbox" guide).
  • A customer registered in sandbox: the deposit credits the wallet tied to their phone number.
  • To receive notifications: an HTTPS endpoint and the X-Api-Key webhook key you provide to Chari.
  1. 1
    Preview the deposit

    Before any debit, check the feasibility of the deposit and get the fees (feesAmount) with the preview endpoint. The customer's phone number goes in the query string (format +212*********), the amount in the body:

    bash
    curl -X 'POST' \
      'https://sandbox.charimoney.com/api/operations/cashin/card/preview?phoneNumber=+2126xxxxxxxx' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID' \
      -H 'Content-Type: application/json' \
      -d '{ "amount": 100 }'
    Response
    json
    {
      "data": {
        "type": 1,
        "operation": {
          "phoneNumber": "+2126xxxxxxxx",
          "amount": 100,
          "method": 2,
          "acceptedBy": 0,
          "description": ""
        },
        "feesAmount": 0,
        "checkedAt": "2025-04-12T12:55:39.213Z",
        "openLoop": false
      }
    }
    401Authentication credentials (API KEY) not authorized — check the Chari-Api-Key header.
    10001Missing Parameters — a required parameter is missing (e.g. phoneNumber in the query or amount in the body).
  2. 2
    Execute with the sandbox test card

    Execute the deposit with the sandbox test card: PAN 4918914107195005, CVV 123, expiry 08/26 (or any future date) — i.e. "2608" in the YYMM format expected by expiryDate. keepAlive: true saves (tokenizes) the card for the last step; 3D Secure is enabled by default. The response tells you whether a 3DS redirect is required (redirect) and provides redirectionURL:

    bash
    curl -X 'POST' \
      'https://sandbox.charimoney.com/api/operations/cashin/card?phoneNumber=+2126xxxxxxxx' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID' \
      -H 'Content-Type: application/json' \
      -d '{
        "firstName": "Mohammed",
        "lastName": "Chairi",
        "cvv": "123",
        "amount": 100,
        "pan": "4918914107195005",
        "expiryDate": "2608",
        "keepAlive": true,
        "cardName": "my_test_card"
      }'
    Response
    json
    {
      "data": {
        "redirect": true,
        "amount": 100,
        "transactionTrackId": "80832126-848",
        "orderId": "edc5608819",
        "transactionReferenceId": "2003",
        "redirectionURL": "https://staging-api.charipay.ma/...",
        "acceptURL": null,
        "declineURL": null
      }
    }
  3. 3
    Complete the 3D Secure authentication

    If redirect = true, open redirectionURL in a browser and enter the test card's 3DS code: 555. After authentication, the user is redirected to acceptURL or declineURL; the redirect URL contains RESPONSE_CODE (0 = success, any other value = failure) and REASON_CODE (human-readable reason for the result, e.g. SUCCESS, DECLINED). Validate RESPONSE_CODE and REASON_CODE to determine the next action in your application.

  4. 4
    Receive the cashin.card.authorized webhook

    When the CashIn by card is accepted, Chari notifies your endpoint with the cashin.card.authorized event (JSON POST, C-Webhook-Id and X-Api-Key headers). The CRequestId field echoes the tracking identifier received from the partner, OperationType 1 = CASHIN, OperationStatus 2 = Completed, Method = Card, and the GatewayTrackId / GatewayOrderId / GatewayReferenceId fields identify the transaction on the gateway side. Reply 200 OK within 5 seconds (empty body) — any non-2xx code triggers a retry (1m, 5m, 30m, 60m, then every 6h up to 72h total).

    Response
    json
    {
      "data": {
        "WebhookId": 12346,
        "CRequestId": "7b8c9f1a-15da-4e1c-8c3b-3a2bd0ed5e6f",
        "OperationId": 563210,
        "OperationType": 1,
        "OperationStatus": 2,
        "CreatedAt": "2025-11-05T09:41:00Z",
        "ExecutedAt": "2025-11-05T09:41:18Z",
        "Amount": 10000.00,
        "FeeAmount": 150.00,
        "CustomData": "ref12345",
        "PrimaryAccountNumber": "+212711111111",
        "Method": "Card",
        "GatewayTrackId": "83c1d1c7",
        "GatewayOrderId": "20251105_00045",
        "GatewayReferenceId": "6f92b0aa"
      }
    }
  5. 5
    Verify the operation

    Using the OperationId from the webhook, fetch the operation details: operationType 1 = CASHIN and transactionStatus 2 = COMPLETED (see the "Types & References" table). totalAmount is the amount after fees and commissions are applied.

    bash
    curl -X 'GET' \
      'https://sandbox.charimoney.com/api/operations/123?phoneNumber=%2B2126XXXXXXXX' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID'
    Response
    json
    {
      "data": {
        "operationId": 1525,
        "transactionId": 2710,
        "transactionReference": "T0101-25062515-1110",
        "amount": 30,
        "operationType": 1,
        "transactionDate": "2025-06-25T16:42:41.982Z",
        "sens": 1,
        "transactionStatus": 2,
        "feesAmount": 0,
        "totalAmount": 30,
        "sender": "+2126XXXXXXXX",
        "receiver": "+2126XXXXXXXX"
      }
    }
  6. 6
    Agent variant: credit an agent's wallet

    The same flow exists on the agent side: the /api/operations/cashin/card/agent/preview and /api/operations/cashin/card/agent endpoints take the code query parameter (code of the agent whose wallet is credited) instead of phoneNumber. The execution body is identical (same test card) and the 3D Secure flow is the same:

    bash
    curl -X 'POST' \
      'https://sandbox.charimoney.com/api/operations/cashin/card/agent/preview?code=21011' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID' \
      -H 'Content-Type: application/json' \
      -d '{ "amount": 100 }'
    Response
    json
    {
      "data": {
        "type": 1,
        "operation": {
          "code": "21011",
          "phoneNumber": "+2126xxxxxxxx",
          "amount": 100,
          "method": 2
        },
        "feesAmount": 0,
        "checkedAt": "2025-04-12T12:55:39.213Z",
        "openLoop": false
      }
    }
  7. 7
    Replay the deposit with the tokenized card

    If keepAlive was true at execution time, the card is saved (tokenized). Fetch its customerBankCardId via GET /api/customers/tokenized/cards?phoneNumber=…, then replay a deposit with only the CVV and the amount — the PAN is no longer transmitted:

    bash
    curl -X 'POST' \
      'https://sandbox.charimoney.com/api/operations/cashin/card/123?phoneNumber=+2126xxxxxxxx' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID' \
      -H 'Content-Type: application/json' \
      -d '{ "cvv": "123", "amount": 200 }'
    Response
    json
    {
      "data": {
        "redirect": true,
        "amount": 200,
        "transactionTrackId": "80832126-848",
        "orderId": "edc5608819",
        "transactionReferenceId": "2003",
        "redirectionURL": "https://staging-api.charipay.ma/...",
        "acceptURL": null,
        "declineURL": null
      }
    }

Merchant card payment: from preview to refund

The full card payment lifecycle (Card to Wallet): check feasibility, collect with 3D Secure, choose between automatic capture and the authorization → capture/reversal flow, refund, then reuse a tokenized card. Every step relies on the orderId and transactionTrackId identifiers returned by the payment.

Prerequisites

  • A valid sandbox API key and the card gateway enabled for your account (see the "Getting started in sandbox" guide).
  • The phone number of the collecting merchant wallet, in +212********* format.
  • The sandbox test card: PAN 4918914107195005, CVV 123, expiry 08/26, 3DS code 555.
  1. 1
    Preview the payment (fees, feasibility)

    Before collecting, check the feasibility of the card payment to the merchant. The merchant's phone number goes in the query string, the amount in the body. The response returns the operation type, the fees (feesAmount) and the check timestamp.

    bash
    curl -X 'POST' \
      'https://sandbox.charimoney.com/api/operations/merchant/payment/card/preview?phoneNumber=+2126xxxxxxxx' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID' \
      -H 'Content-Type: application/json' \
      -d '{ "amount": 250 }'
    Response
    json
    {
      "data": {
        "type": 5,
        "operation": {
          "phoneNumber": "+2126xxxxxxxx",
          "amount": 250,
          "method": 2
        },
        "feesAmount": 0,
        "checkedAt": "2025-04-12T12:55:39.213Z",
        "openLoop": false
      }
    }
    401API key not authorized — check the Chari-Api-Key header.
    10001Missing Parameters — a required parameter is missing (e.g. amount in the body).
    20005The specified user could not be found — check the merchant's phone number (+212********* format).
  2. 2
    First collection: execute with autoCapture

    Execute the payment with the test card (expiryDate in YYMM format: 2608). With autoCapture = true, the payment is captured automatically. keepAlive = true tokenizes the card for later reuse (step 7). 3DS flow: the response provides redirectionURL to open (redirect = true); enter the 3DS code 555 there. Keep orderId and transactionTrackId — the whole rest of the lifecycle depends on them.

    bash
    curl -X 'POST' \
      'https://sandbox.charimoney.com/api/operations/merchant/payment/card?phoneNumber=+2126xxxxxxxx' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID' \
      -H 'Content-Type: application/json' \
      -d '{
        "firstName": "John",
        "lastName": "Doe",
        "cvv": "123",
        "amount": 250,
        "pan": "4918914107195005",
        "expiryDate": "2608",
        "keepAlive": true,
        "3dSecure": true,
        "autoCapture": true,
        "notificationUrl": "https://merchant.example.com/webhook",
        "acceptUrl": "https://merchant.example.com/success",
        "declineUrl": "https://merchant.example.com/failure",
        "externalReference": "ORDER-1001"
      }'
    Response
    json
    {
      "data": {
        "redirect": true,
        "responseCode": 0,
        "amount": 250,
        "transactionTrackId": "600789381213",
        "orderId": "CH473bbe51d546",
        "transactionReferenceId": "5852",
        "redirectionURL": "https://staging-api.charipay.ma:443/chari-frontend/home_card3?ORDER_ID=CH473bbe51d546&REFERENCE_ID=5852&TRACK_ID=600789381213",
        "gateway": "CHARIPAY",
        "operationId": null,
        "feesAmount": null
      }
    }
  3. 3
    Validate the 3D Secure return

    After 3D Secure authentication, the user is redirected to acceptUrl or declineUrl depending on the outcome. The return URL includes RESPONSE_CODE (0 = success, any other = failure), REASON_CODE (human-readable reason: SUCCESS, DECLINED…) and OPERATION (e.g. PAYMENT): validate them upon receiving the redirect. The notificationUrl is also notified when the transaction ends (success/failure), and the payment.card.authorized webhook event signals an accepted card payment.

  4. 4
    Two-step payment: authorize then capture

    To decouple authorization and debit, execute the payment (step 2) with autoCapture = false: the funds are authorized without being debited. Then finalize with the capture, targeting the transaction via the orderId and transactionTrackId returned by the payment. Typical flow: card payment with AutoCapture = false → authorization → capture (this endpoint) or cancellation (reverse). Required scope: operations:merchant-payment.

    bash
    curl -X 'POST' \
      'https://sandbox.charimoney.com/api/operations/merchant/payment/card/capture' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID' \
      -H 'Content-Type: application/json' \
      -d '{
        "phoneNumber": "+2126xxxxxxxx",
        "amount": 250,
        "orderId": "CH473bbe51d546",
        "transactionTrackId": "600789381213",
        "skipGatewayCall": false
      }'
    Response
    json
    {
      "data": {
        "phoneNumber": "+2126xxxxxxxx",
        "operationId": 5231,
        "refundAmount": 250,
        "orderId": "CH473bbe51d546",
        "transactionTrackId": "600789381213"
      }
    }
  5. 5
    Cancel an uncaptured authorization (reverse)

    If the order is abandoned before capture, reverse the authorization: the authorized funds are released without being debited. The request body is identical to the capture one — target the transaction via orderId and transactionTrackId. A reversal applies to an uncaptured authorization; for an already captured payment, use the Refund endpoint (next step).

    bash
    curl -X 'POST' \
      'https://sandbox.charimoney.com/api/operations/merchant/payment/card/reverse' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID' \
      -H 'Content-Type: application/json' \
      -d '{
        "phoneNumber": "+2126xxxxxxxx",
        "amount": 250,
        "orderId": "CH473bbe51d546",
        "transactionTrackId": "600789381213",
        "skipGatewayCall": false
      }'
    Response
    json
    {
      "data": {
        "phoneNumber": "+2126xxxxxxxx",
        "operationId": 5231,
        "refundAmount": 250,
        "orderId": "CH473bbe51d546",
        "transactionTrackId": "600789381213"
      }
    }
  6. 6
    Refund a captured payment (full or partial)

    An already captured payment is refunded through the Refund endpoint, identified by operationId. A RefundAmount lower than the captured amount performs a partial refund. Mind the scope: operations:refund, different from the operations:merchant-payment scope of the other card endpoints.

    bash
    curl -X 'POST' \
      'https://sandbox.charimoney.com/api/operations/merchant/payment/card/refund' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID' \
      -H 'Content-Type: application/json' \
      -d '{
        "phoneNumber": "+2126xxxxxxxx",
        "operationId": 5231,
        "refundAmount": 100,
        "orderId": "CH473bbe51d546",
        "transactionTrackId": "600789381213"
      }'
    Response
    json
    {
      "data": {
        "phoneNumber": "+2126xxxxxxxx",
        "operationId": 5231,
        "refundAmount": 100,
        "orderId": "CH473bbe51d546",
        "transactionTrackId": "600789381213"
      }
    }
  7. 7
    Collect again with the tokenized card

    The card tokenized at step 2 (keepAlive = true) is reused via its cardId in the path: only the CVV is required in the body, along with the amount. The response has the same structure as the regular card payment — same 3DS flow handling (redirectionURL, RESPONSE_CODE / REASON_CODE / OPERATION return), same orderId and transactionTrackId for the rest of the lifecycle.

    bash
    curl -X 'POST' \
      'https://sandbox.charimoney.com/api/operations/merchant/payment/tokenized/card/277?phoneNumber=+2126xxxxxxxx' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID' \
      -H 'Content-Type: application/json' \
      -d '{ "cvv": "123", "amount": 188 }'
    Response
    json
    {
      "data": {
        "redirect": true,
        "responseCode": 0,
        "amount": 188,
        "transactionTrackId": "600789381214",
        "orderId": "CH8f2a1b9e4d7c",
        "transactionReferenceId": "5853",
        "redirectionURL": "https://staging-api.charipay.ma:443/chari-frontend/home_card3?ORDER_ID=CH8f2a1b9e4d7c&REFERENCE_ID=5853&TRACK_ID=600789381214",
        "gateway": "CHARIPAY",
        "operationId": null,
        "feesAmount": null
      }
    }
  8. 8
    Going further: merchant QR Code status

    If your merchants also collect by QR Code, check the status of a merchant QR Code by its reference: the response returns the QR content (qrContent, encoded payload to display/scan) and its reference (qrCodeReference). For card transactions, tracking by orderId remains the ChariPay Status endpoint from step 3.

    bash
    curl -X 'GET' \
      'https://sandbox.charimoney.com/api/operations/merchant/qrcode/status?reference=1122334455' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID'
    Response
    json
    {
      "data": {
        "qrContent": "00020101021126xxxxxx",
        "qrCodeReference": "1122334455"
      }
    }

Cash-in / cash-out by reference: from request to execution

The reference flow in three phases: your application creates a CashIn or CashOut request that generates a unique reference with limited validity; the customer shares it with an agent; the agent looks it up then executes the operation. This guide walks the full journey in sandbox, including the simulated network execution and the Fatourati variant.

Prerequisites

  • A valid sandbox API key (see the "Getting started in sandbox" guide).
  • For the execution step: the code of the agent performing the operation.
  • To receive notifications: your webhook endpoint and the X-Api-Key you provided to Chari.
  1. 1
    Create the CashIn request

    The CashIn request generates a unique reference with limited validity; that reference is then used by an agent to execute the operation. The body carries two required fields: PhoneNumber (the customer's number) and Amount (the CashIn amount). The response comes back with operationStatus 1 (open) — possible values are 1 = open, 2 = completed, 3 = failed, 4 = canceled, and operationType is 1 for CashIn, 2 for CashOut.

    bash
    curl -X 'POST' \
      'https://sandbox.charimoney.com/api/operations/cashin/request' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID' \
      -H 'Content-Type: application/json' \
      -d '{
        "PhoneNumber": "+2126xxxxxxxx",
        "amount": 10
      }'
    Response
    json
    {
      "data": {
        "createdAt": "2025-05-15T23:55:55.082Z",
        "closedAt": null,
        "reference": "1122334455",
        "phoneNumber": "+2126xxxxxxxx",
        "operationType": 1,
        "operationStatus": 1,
        "amount": 10
      }
    }
    10001Missing Parameters — a required body field (PhoneNumber, Amount) is missing.
    401Authentication credentials (API KEY) not authorized — check the Chari-Api-Key header.
  2. 2
    Look up the request by its reference

    The customer shares the reference with the agent. Before executing, the agent (or your back office) can retrieve the request details — amount, status — through the same route in GET, with the reference as a query parameter. Until the operation is executed, executedAt stays null and status is 1 (open).

    bash
    curl -X 'GET' \
      'https://sandbox.charimoney.com/api/operations/cashin/request?reference=1122334455' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID'
    Response
    json
    {
      "data": {
        "reference": "1122334455",
        "createdAt": "2025-05-15T23:55:55.082Z",
        "executedAt": null,
        "phoneNumber": "+2126xxxxxxxx",
        "amount": 10,
        "partner": "ChariMoney",
        "status": 1,
        "type": 1
      }
    }
  3. 3
    Execute the CashIn on the agent side

    The agent executes the operation using the reference generated for the customer: the body carries code (the code of the agent performing the operation) and reference. This is the step that materializes the cash deposit.

    bash
    curl -X 'POST' \
      'https://sandbox.charimoney.com/api/operations/cashin/agent' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID' \
      -H 'Content-Type: application/json' \
      -d '{
        "code": "123",
        "reference": "1122334455"
      }'
    Response
    json
    {
      "data": {
        "createdAt": "2025-05-15T23:55:55.0821309Z",
        "closedAt": null,
        "reference": "1122334455",
        "phoneNumber": "+2126xxxxxxxx",
        "operationType": 1,
        "operationStatus": 1,
        "amount": 10
      }
    }
  4. 4
    Run the symmetric CashOut

    Cash withdrawal follows exactly the same three-phase scheme on the cashout routes: POST /api/operations/cashout/request (PhoneNumber + Amount) generates the reference, GET /api/operations/cashout/request?reference=... looks it up, and POST /api/operations/cashout/agent (code + reference) executes it. In the responses, operationType is 2 (CashOut).

    bash
    curl -X 'POST' \
      'https://sandbox.charimoney.com/api/operations/cashout/request' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID' \
      -H 'Content-Type: application/json' \
      -d '{
        "PhoneNumber": "+2126xxxxxxxx",
        "amount": 100
      }'
    Response
    json
    {
      "data": {
        "createdAt": "2025-05-15T23:56:55.082Z",
        "closedAt": null,
        "reference": "1122334456",
        "phoneNumber": "+2126xxxxxxxx",
        "operationType": 2,
        "operationStatus": 1,
        "amount": 100
      }
    }
  5. 5
    Simulate the network execution in sandbox

    The network endpoints execute a CashIn or CashOut by reference from a network entity (network agent step). In sandbox, call them yourself to complete your test flows without a real agent network: the body carries reference (required) and entity (optional), and the optional withContext query parameter returns the result with its context if it exists (false by default). The symmetric route POST /api/network/operations/cashout executes the CashOut.

    bash
    curl -X 'POST' \
      'https://sandbox.charimoney.com/api/network/operations/cashin' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID' \
      -H 'Content-Type: application/json' \
      -d '{
        "reference": "1122334455",
        "entity": "AGENCY"
      }'
    Response
    json
    {
      "data": {
        "reference": "1122334455",
        "entity": "AGENCY",
        "createdAt": "2025-05-15T23:55:55.082Z",
        "executedAt": "2025-05-15T23:57:07.000Z",
        "phoneNumber": "+2126xxxxxxxx",
        "amount": 10,
        "description": "CashIn by reference",
        "partner": "PARTNER_NAME"
      }
    }
  6. 6
    Receive the confirmation via webhook

    The execution triggers the webhook event cashin.network.executed (CashIn by reference executed) or cashout.network.executed (CashOut by reference executed) towards your HTTPS endpoint. The JSON body carries the common fields (OperationId, OperationType, OperationStatus, Amount, CreatedAt, ExecutedAt...) plus, for these network operations, Reference and NetworkName. Respond 200 OK within 5 seconds; any non-2xx code triggers a retry (1m, 5m, 30m, 60m, then every 6h up to 72h total).

  7. 7
    Fatourati variant: the dedicated CashIn request

    Fatourati is a special provider with its own reference generation flow (FATREF- prefix): use the dedicated route POST /api/operations/fatourati/cashin/request instead of the standard cashin endpoint — reference generation behavior and expiry rules may differ. For a principal agent, replace phoneNumber by the Agent Code (PhoneNumber => Code); Description and FeesPercent are optional.

    bash
    curl -X 'POST' \
      'https://sandbox.charimoney.com/api/operations/fatourati/cashin/request' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID' \
      -H 'Content-Type: application/json' \
      -d '{
        "code": "1880375",
        "Amount": 100,
        "FeesPercent": 1,
        "Description": "Test it"
      }'
    Response
    json
    {
      "data": {
        "reference": "FATREF-E6C8ECC690AC",
        "createdAt": "2026-06-11T00:42:09.654Z",
        "executedAt": null,
        "phoneNumber": null,
        "code": "1880375",
        "amount": 100,
        "description": "Test it",
        "status": 1,
        "type": 1
      }
    }

Fatourati bill payment: from creditor to receipt

Collect a Fatourati bill (RADEEMA, LYDEC, IAM, TGR…) end to end: list creditors, list receivables, build the dynamic identification form, retrieve unpaid items, confirm the payment, then track the transaction (status, receipt, webhooks). Single-creditor model; partial payment supported.

Prerequisites

  • A valid sandbox API key (Chari-Api-Key + C-Request-Id headers) — see the "Getting started in sandbox" guide.
  • The Bill Payment module enabled for your partner account by the Chari team.
  • An existing Chari Money end user (phoneNumber in international format) and test float for debit operations.
  1. 1
    List Fatourati creditors

    Fetch the list of active creditors accessible to your account (filtered by your contract and Fatourati configuration). Keep each biller's codeCreancier (4 digits, ≥ 1000). codeRetour: 000 = ACCEPTE (success), 908 = Fatourati technical error. Since the response is relatively stable, caching for a few hours on the partner side is acceptable.

    bash
    curl -X 'GET' \
      'https://sandbox.charimoney.com/api/bills/creanciers' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID'
    Response
    json
    {
      "codeRetour": "000",
      "msg": "ACCEPTE",
      "nbreCreancier": 9,
      "listeCreanciers": [
        {
          "codeCreancier": "1002",
          "nomCreancier": "RADEEMA",
          "descriptionCreancier": "Régie autonome de Marrakech",
          "logoPath": "https://cdn.charimoney.com/logos/radeema.png",
          "siteWeb": "https://www.radeema.ma"
        },
        {
          "codeCreancier": "1008",
          "nomCreancier": "LYDEC",
          "descriptionCreancier": "Lyonnaise des eaux de Casablanca",
          "logoPath": "https://cdn.charimoney.com/logos/lydec.png",
          "siteWeb": "https://www.lydec.ma"
        }
      ]
    }
    401Authentication credentials (API KEY) not authorized — check the Chari-Api-Key header.
  2. 2
    List the chosen creditor's receivables

    A creditor may expose several receivables (a receivable corresponds to a service type: bill, top-up, tax…). List them with the creancierId obtained in step 1. codeCreance is always 2 positions (e.g., 01). codeRetour: 000 = ACCEPTE, 104 = creditor non-existent or inactive, 908 = technical error.

    bash
    curl -X 'GET' \
      'https://sandbox.charimoney.com/api/bills/creances?creancierId=1002' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID'
    Response
    json
    {
      "codeRetour": "000",
      "msg": "ACCEPTE",
      "nbreCreance": 2,
      "listeCreance": [
        { "codeCreance": "01", "nomCreance": "Factures Eau et Electricité" },
        { "codeCreance": "02", "nomCreance": "Frais de raccordement" }
      ]
    }
  3. 3
    Build the dynamic identification form

    For the (creditor, receivable) pair, fetch the schema of the fields to display: label, type, format, size, constraints. You MUST build your input screen from this response (no hardcoded form) to stay compatible with new creditors added to the Fatourati network. typeChamp: text, select, password, libelle — a libelle field is static text (not editable) and must NEVER be sent in creancierVals. contrainte: 0 = optional, 1 = required. If refTxFatourati equals 1 (default), the next step is /impayes.

    bash
    curl -X 'GET' \
      'https://sandbox.charimoney.com/api/bills/form?creancierId=1008&creanceId=01' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID'
    Response
    json
    {
      "codeRetour": "000",
      "msg": "ACCEPTE",
      "nbreParams": 2,
      "creancierParams": [
        {
          "libelle": "Contract number",
          "nomChamp": "numeroProduit",
          "typeChamp": "text",
          "formatChamp": "2",
          "tailleMin": 8,
          "tailleMax": 12,
          "contrainte": "1"
        },
        {
          "libelle": "To find your number, check your latest bill in the top right.",
          "nomChamp": "",
          "typeChamp": "libelle",
          "formatChamp": "1",
          "tailleMin": 0,
          "tailleMax": 0,
          "contrainte": "0"
        }
      ],
      "refTxFatourati": "1"
    }
  4. 4
    Retrieve the customer's unpaid items

    Submit the entered identification: the body carries creancierVals, an array of { nomChamp, valChamp } objects — note the property is named valChamp (not valeurChamp as in the /form and /impayes responses), and typeChamp=libelle fields must not be included. This call opens the transaction (EN_ATTENTE state) and returns a refTxFatourati (12 digits) to keep for /confirm; the association stays valid for 7 calendar days (Fatourati timeout). impayesParams lists the articles (typeArticle: 0 = receivable, 1 = fee, 2 = mandatory, 3 = stamp fee); technical globalParams with an empty libelle (contrPaiement, isConfTO, isAnnul, rejoue) must never be shown to the customer. Key codes: 107 = no bill to pay, 109 = required field missing.

    bash
    curl -X 'POST' \
      'https://sandbox.charimoney.com/api/bills/impayes?phoneNumber=%2B212670770743&creancierId=1008&creanceId=01' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID' \
      -H 'Content-Type: application/json' \
      -d '{
      "creancierVals": [
        { "nomChamp": "numeroProduit", "valChamp": "16422270229" }
      ]
    }'
    Response
    json
    {
      "codeRetour": "000",
      "msg": "ACCEPTE",
      "refTxFatourati": "100003141347",
      "codeDevise": "504",
      "nbreCreances": 2,
      "montantTotalTTC": "150.50",
      "globalParams": [
        { "libelle": "Customer name", "nomChamp": "nomClient", "valeurChamp": "ALERGE DE LAREDO" },
        { "libelle": "", "nomChamp": "contrPaiement", "valeurChamp": "1" }
      ],
      "impayesParams": [
        {
          "idArticle": "1005533319",
          "description": "Water bill July 2026",
          "dateFacture": "26/07/2026",
          "prixTTC": "120.16",
          "typeArticle": 0
        },
        {
          "idArticle": "1005533320",
          "description": "Water bill August 2026",
          "dateFacture": "26/08/2026",
          "prixTTC": "30.34",
          "typeArticle": 0
        }
      ]
    }
    10001Missing Parameters — a required parameter is missing (phoneNumber, creancierId, creanceId or the creancierVals array).
  5. 5
    Confirm the payment (after preview)

    Let the user select their articles (totalPayment: true = all unpaid items, false = partial selection), then confirm. The body carries creancierId, creanceId, the refTxFatourati from step 4, listeArticleSelectionnes ({ idArticle, prixTTC, typeArticle, dateFacture, description } objects taken from impayesParams), creancierVals ({ nomChamp, valChamp }) and globalParams. You can first validate this same body without executing the payment via POST /api/bills/preview (body identical to /confirm). codeRetour 000 = CONFIRME (effective settlement on the creditor's side); 301 = already processed (treat as success, show the receipt). refReglement must appear on the receipt; numCRC / texteCRC (params) must be displayed on the receipt if present.

    bash
    curl -X 'POST' \
      'https://sandbox.charimoney.com/api/bills/confirm?phoneNumber=%2B212670770743' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID' \
      -H 'Content-Type: application/json' \
      -d '{
      "creancierId": "1008",
      "creanceId": "01",
      "refTxFatourati": "100003141347",
      "totalPayment": false,
      "listeArticleSelectionnes": [
        { "idArticle": "1005533320", "prixTTC": "30.34", "typeArticle": 0, "dateFacture": "26/08/2026", "description": "Water bill August 2026" }
      ],
      "creancierVals": [
        { "nomChamp": "numeroProduit", "valChamp": "16422270229" }
      ],
      "globalParams": [
        { "libelle": "", "nomChamp": "contrPaiement", "valeurChamp": "1" }
      ]
    }'
    Response
    json
    {
      "codeRetour": "000",
      "msg": "ACCEPTE",
      "refTxFatourati": "100003141347",
      "codeAutorisation": "A1B2C3",
      "refReglement": "REGL20260512000183",
      "montantTotalTTC": "30.34",
      "codeDevise": "504",
      "params": [
        { "nomChamp": "numCRC", "valeurChamp": "0801007777" },
        { "nomChamp": "texteCRC", "valeurChamp": "For any complaint, contact LYDEC customer service." }
      ]
    }
    20005The specified user could not be found — phoneNumber must match an existing Chari Money user, otherwise the transaction is rejected before any call to Fatourati.
  6. 6
    Track the transaction and deliver the receipt

    GET /api/bills/reference/status returns the status of a Fatourati cash-in from its reference: execution flag, status, amount, timestamps and chariOperationId (204 No Content if no transaction matches; response at the root, without a { "data": … } envelope). This Chari operation identifier is usable with GET /api/bills/bill-receipt/{operationId}?phoneNumber=… to download the receipt — the 200 response contains the receipt file (binary content), not a JSON body, and the receipt must mention the refReglement returned by /confirm. The customer's paginated payment history is available via GET /api/bills/history.

    bash
    curl -X 'GET' \
      'https://sandbox.charimoney.com/api/bills/reference/status?reference=1000031413470' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID'
    Response
    json
    {
      "fatouratiReference": "1000031413470",
      "executed": true,
      "status": "CONFIRME",
      "created_at": "2026-07-12T10:15:23Z",
      "amount": 150.50,
      "executed_at": "2026-07-12T10:16:05Z",
      "chariOperationId": 2181
    }
  7. 7
    Listen to the payment.* webhooks

    Asynchronous behavior (digital channel): on /confirm, codes 908/909/910 are NOT definitive failures — the transaction stays in AUTORISE state and its final resolution is notified by webhook. The module events are: payment.confirmed (CONFIRME state), payment.cancelled (ANNULE), payment.refunded (REMBOURSE) and payment.failed (FAILED). Notifications arrive as signed POSTs with the X-Api-Key header (the secret key you provide to Chari); reply 200 OK within 5 seconds — any non-2xx code triggers a retry (1m, 5m, 30m, 60m, then every 6h up to 72h total).

B2B phone top-up: catalog, recharge, customer variant

Top up a Moroccan mobile number from your principal agent account in two calls: offer catalog then recharge execution. The guide then covers the "customer" variant (customer wallet debited, with a prior preview) and the recharge history. Supported operators: Maroc Telecom (IAM), Orange and Inwi.

Prerequisites

  • A valid sandbox API key (see the "Getting started in sandbox" guide).
  • The telco service enabled for your partner account by the Chari team.
  • Your principal agent code (the account debited for the B2B recharge), funded with test float.
  1. 1
    Check that the telco service is enabled

    Telco top-up is a module enabled by the Chari team for your partner account, on request. You will also need your principal agent code: it is the account that will be debited by the B2B recharge, provided by Chari after activation of your partner account. If the service is not enabled, your telco calls fail with a business error indicating the service is not enabled for your account — in that case, request operator activation (see the "Getting started in sandbox" guide).

  2. 2
    Retrieve the offer catalog (B2B)

    The B2B catalog returns the list of recharge products available for a given phone number, amount and operator (1 = Maroc Telecom, 2 = Orange, 3 = Inwi). Each product carries a unique productCode to use when requesting the top-up, and an enabled availability flag.

    bash
    curl -X 'POST' \
      'https://sandbox.charimoney.com/api/services/telco/catalog/b2b' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID' \
      -H 'Content-Type: application/json' \
      -d '{
      "recipientPhoneNumber": "+21266123123",
      "amount": 10,
      "operator": 2
    }'
    Response
    json
    {
      "data": [
        { "productCode": 3, "description": "Pass Internet sur mobile", "arDescription": "عرض الإنترنت", "enabled": true },
        { "productCode": 1, "description": "Pass Appels vers le national", "arDescription": "روشارج المكالمات", "enabled": true },
        { "productCode": 0, "description": "Recharge Dirhams", "arDescription": "روشارج الدراهم", "enabled": true }
      ]
    }
  3. 3
    Execute the B2B recharge

    Initiate the recharge with the productCode chosen from the catalog. The code field is your principal agent code — the account that will be debited. rechargeType is 0 for a Classic recharge (Dirhams) and 1 for a Product recharge (a catalog pass). The response carries operationType = 10 (RECHARGE, see the "Types & References" table).

    bash
    curl -X 'POST' \
      'https://sandbox.charimoney.com/api/operations/service/telco/recharge/b2b' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID' \
      -H 'Content-Type: application/json' \
      -d '{
      "recipientPhoneNumber": "+21266123123",
      "amount": 10,
      "operator": 2,
      "rechargeType": 1,
      "productCode": 3,
      "code": "12003"
    }'
    Response
    json
    {
      "data": {
        "operationType": 10,
        "Amount": 10,
        "feesAmount": 0,
        "checkedAt": "2025-04-12T12:31:59.31347Z",
        "openLoop": false
      }
    }
  4. 4
    Customer variant: preview the recharge

    If the recharge is paid from a customer's wallet (rather than your principal agent account), use the "customer" variant. Call the preview first to check feasibility, amount and fees before execution: customerPhoneNumber is the debited wallet, recipientPhoneNumber the topped-up number. The response returns feesAmount and totalAmount (amount + fees).

    bash
    curl -X 'POST' \
      'https://sandbox.charimoney.com/api/operations/service/telco/recharge/preview' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID' \
      -H 'Content-Type: application/json' \
      -d '{
      "customerPhoneNumber": "+2126xxxxxxxx",
      "recipientPhoneNumber": "+2127xxxxxxxx",
      "amount": 100.00,
      "operator": 2,
      "rechargeType": 0
    }'
    Response
    json
    {
      "data": {
        "type": 10,
        "operation": {
          "customerPhoneNumber": "+2126xxxxxxxx",
          "recipientPhoneNumber": "+2127xxxxxxxx",
          "amount": 100.00,
          "operator": 2,
          "rechargeType": 0
        },
        "feesAmount": 0,
        "totalAmount": 100.00,
        "checkedAt": "2026-07-12T10:22:05.118Z",
        "openLoop": false
      }
    }
  5. 5
    Customer variant: execute the recharge

    Once the preview is validated, execute the recharge with the same body: the customer's wallet (customerPhoneNumber) is debited — unlike the /b2b variant which debits the principal agent account. For a Product-type recharge, add the productCode returned by the catalog.

    bash
    curl -X 'POST' \
      'https://sandbox.charimoney.com/api/operations/service/telco/recharge' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID' \
      -H 'Content-Type: application/json' \
      -d '{
      "customerPhoneNumber": "+2126xxxxxxxx",
      "recipientPhoneNumber": "+2127xxxxxxxx",
      "amount": 100.00,
      "operator": 2,
      "rechargeType": 0
    }'
    Response
    json
    {
      "data": {
        "operationType": 10,
        "amount": 100.00,
        "feesAmount": 0,
        "totalAmount": 100.00,
        "reason": null,
        "recipientPhoneNumber": "+2127xxxxxxxx",
        "checkedAt": "2026-07-12T10:24:31.204Z"
      }
    }
  6. 6
    Look up a customer's recharge history

    Retrieve the list of a customer's recharge operations with pagination (pageSize/pageNumber) and a status filter. The status parameter (swagger enum: 0 to 4) is repeatable to filter on multiple statuses, e.g. status=2&status=3. The response is a list of operations, with no pagination envelope.

    bash
    curl -X 'GET' \
      'https://sandbox.charimoney.com/api/operations/service/telco/recharge?phoneNumber=%2B2126xxxxxxxx&pageSize=20&pageNumber=1&status=2' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID'
    Response
    json
    {
      "data": [
        {
          "telcoRechargeOperationId": 3151,
          "customerId": 1200,
          "createdAt": "2026-07-10T09:15:24.512Z",
          "completedAt": "2026-07-10T09:15:31.240Z",
          "operatorId": 2,
          "amount": 50.00,
          "product": "Recharge Dirhams",
          "type": 0,
          "status": 2,
          "destinationPhoneNumber": "+2127xxxxxxxx"
        }
      ]
    }
  7. 7
    Handle errors

    Errors follow standard HTTP codes; a 400 Bad Request carries a Chari-specific error code in the body ({ "errorCode": ..., "errorDescription": "..." }). Include a unique C-Request-Id (UUID v4) in every request: it is echoed back in the response and eases tracing with support.

    401 UnauthorizedAuthentication credentials (API KEY) not authorized — check the Chari-Api-Key header and the environment (keys are per-environment).
    10001Missing Parameters — a required body field is missing (e.g. code, productCode or rechargeType on the B2B recharge).

Selling vouchers: brands, articles, preview, code

The full journey for selling a digital voucher (gift card, game top-up…): browse brands, pick an article, preview the amount and fees, then confirm the purchase to obtain the code to hand to the beneficiary. The purchase flow follows a preview/confirm model; the operation type is 23 (VOUCHER).

Prerequisites

  • A valid sandbox API key (see the "Getting started in sandbox" guide).
  • The vouchers module enabled for your account, with a catalog provisioned in sandbox by Chari — otherwise the brand and article lists come back empty.
  • A principal agent funded with test float to execute debit operations.
  1. 1
    Check the catalog provisioning

    Voucher brands must be provisioned in sandbox by Chari for your account: an empty catalog is not an integration bug but a non-provisioned module — ask your Chari contact for activation. Likewise, the purchase confirmation is a debit operation: your principal agent must be funded with test float. Both points are detailed in the sandbox onboarding guide.

  2. 2
    List available brands

    Fetch the paginated list of voucher brands (page starts at 1, take defaults to 10). The customer's phoneNumber is required, in the format +212*********. Note the id of the chosen brand. There is no brandId filter on this endpoint: for a specific brand, use GET /api/vouchers/brands/{id}.

    bash
    curl -X 'GET' \
      'https://sandbox.charimoney.com/api/vouchers/brands?phoneNumber=%2B2126xxxxxxxx&page=1&take=10' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID'
    Response
    json
    {
      "data": {
        "collection": [
          {
            "id": 14,
            "name": "Razer",
            "description": "Step 1: From the payment ....",
            "image": "string",
            "expirationDelay": "none"
          }
        ],
        "count": 3
      }
    }
  3. 3
    Retrieve a brand's articles

    Fetch the article catalog of the chosen brand via its brandId. Each article exposes its price and, above all, the two identifiers required by the rest of the flow: providerSkuId (the article identifier at the provider) and providerId (the provider identifier). Keep them for the preview and the confirmation.

    bash
    curl -X 'GET' \
      'https://sandbox.charimoney.com/api/vouchers/articles?phoneNumber=%2B2126xxxxxxxx&brandId=14&page=1&take=10' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID'
    Response
    json
    {
      "data": {
        "collection": [
          {
            "providerSkuId": "string",
            "productName": "string",
            "imageUrl": "string",
            "price": 0,
            "description": "string",
            "providerId": 0,
            "brandId": 0
          }
        ],
        "count": 3
      }
    }
  4. 4
    Preview the purchase

    Check the feasibility of the purchase before any execution. The body carries five required fields: customerPhoneNumber, destinationPhoneNumber, beneficiaryName (free text), providerSkuId and providerId. The response returns type 23 (VOUCHER, see the "Types & References" table), feesAmount (the fees) and totalAmount (the total amount incl. tax) — show them to the customer before confirming.

    bash
    curl -X 'POST' \
      'https://sandbox.charimoney.com/api/operations/voucher/preview' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID' \
      -H 'Content-Type: application/json' \
      -d '{
      "customerPhoneNumber": "+2126xxxxxxxx",
      "providerSkuId": "1212AAABBBccc",
      "destinationPhoneNumber": "+2126xxxxxxxx",
      "beneficiaryName": "abdennour",
      "providerId": 2
    }'
    Response
    json
    {
      "data": {
        "type": 23,
        "operation": {
          "customerPhoneNumber": "+2126xxxxxxxx",
          "amount": 2.16,
          "reason": "",
          "beneficiaryId": null,
          "recipientPhoneNumber": "+2126xxxxxxxx"
        },
        "feesAmount": 0.15,
        "totalAmount": 2.16,
        "checkedAt": "2026-03-31T14:52:07",
        "openLoop": false
      }
    }
  5. 5
    Confirm and hand over the voucher code

    Execute the purchase with the same body as the preview. This response carries the deliverable: operation.code holds the voucher code to share with the beneficiary, along with voucherName (name of the purchased voucher), description and cashBack (optional cashback amount). Store the code securely and hand it to the beneficiary.

    bash
    curl -X 'POST' \
      'https://sandbox.charimoney.com/api/operations/voucher/confirm' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID' \
      -H 'Content-Type: application/json' \
      -d '{
      "customerPhoneNumber": "+2126xxxxxxxx",
      "providerSkuId": "1212AAABBBccc",
      "destinationPhoneNumber": "+2126xxxxxxxx",
      "beneficiaryName": "abdennour",
      "providerId": 2
    }'
    Response
    json
    {
      "data": {
        "type": 23,
        "operation": {
          "operationType": 23,
          "voucherName": "Soho 101 Okey 92000 Gold Coin",
          "amount": 2.16,
          "cashBack": 0.14,
          "totalAmount": 1.96,
          "reason": null,
          "recipientPhoneNumber": "+2126xxxxxxxx",
          "checkedAt": "2026-03-31T14:53:50.6078466Z",
          "urlActivateCard": null,
          "destinationPhoneNumber": "+2126xxxxxxxx",
          "beneficiaryName": "abdennour",
          "code": "01X01X01X",
          "description": "80000 Gold Coin"
        },
        "feesAmount": 0.15,
        "totalAmount": 2.16,
        "checkedAt": "2026-03-31T14:52:07",
        "openLoop": false
      }
    }
  6. 6
    Go further: the local catalog (SKU)

    Alongside the brands/articles flow above, the API exposes a local voucher catalog, filterable by brandId and keyword. The skuId of the returned vouchers feeds a second, distinct purchase flow: POST /api/operations/service/voucher/preview (which returns the completed voucher object, notably amount) then POST /api/operations/service/voucher (operation:voucher scope). Note: the swagger does not document the 200 response schema of the list, and this "service" flow must not be confused with /api/operations/voucher/preview used in the previous steps.

    bash
    curl -X 'GET' \
      'https://sandbox.charimoney.com/api/vouchers?phoneNumber=%2B2126xxxxxxxx&page=1&take=20&brandId=14' \
      -H 'Chari-Api-Key: YOUR_API_KEY' \
      -H 'C-Request-Id: YOUR_REQUEST_ID'
  7. 7
    Handle errors

    API errors follow standard HTTP codes, complemented by Chari-specific error codes for business errors, returned as 400 in the format { "errorCode": …, "errorDescription": "…" }. The most frequent cases on this flow are listed below; the full table is in the "Error Codes" section.

    401Authentication credentials (API KEY) not authorized — check the Chari-Api-Key header.
    10001Missing Parameters — one of the five required body fields (customerPhoneNumber, destinationPhoneNumber, beneficiaryName, providerSkuId, providerId) is missing.
    422The server is unable to process the request.
C

Customer Registration

Full customer lifecycle management: status check, registration, OTP confirmation, PIN management, balance and info retrieval, and unregistration.

GET{host}/api/customers/status

Check Status with Chari

Retrieve the current registration status of a customer with Chari only.

ParameterTypeInRequiredDescription
PhoneNumberstringqueryRequiredThe customer's phone number. Format: +212*********

Notes

  • 0 : Not exists — The number does not exist with ChariMoney.
  • 1 : Not confirmed — The number exists with ChariMoney but is not yet enrolled with Switch (OTP not entered).
  • 2 : Confirmed — The number exists and is registered with Switch.
  • 3 : Active — Registered with Switch and active with ChariMoney (PIN created).
  • 4 : Locked temporary — The number is temporarily blocked (max attempts exceeded).
  • 5 : Locked — The number is blocked.
GET{host}/api/customers/default

Check Default Wallet (Switch)

Retrieve whether Chari is the default wallet for the customer.

ParameterTypeInRequiredDescription
phoneNumberstringqueryRequiredThe customer's phone number. Format: +212*********

Notes

  • true : Chari is the default wallet for the customer.
  • false : Chari is NOT the default wallet for the customer.
POST{host}/api/customers/register202

Register

Initiate a new customer registration process. An OTP will be sent via SMS.

ParameterTypeInRequiredDescription
phoneNumberstringbodyRequiredThe customer's phone number. Format: +212*********
firstNamestringbodyRequiredMinimum 2 letters (latin characters only)
lastNamestringbodyRequiredMinimum 2 letters (latin characters only)
cinstringbodyRequiredMinimum 5 characters
walletTypestringbodyRequired"P": Particular (Particulier) / "C": Merchant (Commerçant)
closeLoopOnlybooleanbodyOptionalIf true, enroll the customer in CloseLoop mode only. In that case, the OTP is sent directly by CHARI.
POST{host}/api/customers/confirm200

Confirm

Confirm a registration using OTP as a verification method.

ParameterTypeInRequiredDescription
phoneNumberstringbodyRequiredThe customer's phone number. Format: +212*********
codestringbodyRequiredThe received OTP code with format: xxx-xxx
autoActivatebooleanbodyOptionalDefault value: false. Indicates whether the wallet should be activated automatically after OTP validation. If false, the user must complete activation by setting or entering a PIN. If true, the wallet is activated automatically, without requiring a PIN.

Notes

  • The wallet type ("P" individual / "C" merchant) is set at registration (Register): walletType is not sent at confirmation.
POST{host}/api/customers/confirm/resend-otp

Resend OTP

Resend the One-Time Password for registration or confirmation.

ParameterTypeInRequiredDescription
phoneNumberstringqueryRequiredThe customer's phone number. Format: +212*********
POST{host}/api/customers/login

Login with PIN

Authenticate an existing customer using their PIN.

ParameterTypeInRequiredDescription
phoneNumberstringbodyRequiredThe customer's phone number. Format: +212*********
pinstringbodyRequiredPIN of the customer.

Notes

  • logged : true if authentication succeeded, false otherwise.
  • remainingAttempts : number of remaining attempts before account lockout.
POST{host}/api/customers/pin

Create PIN

Set up a secure PIN for a registered customer.

ParameterTypeInRequiredDescription
phoneNumberstringbodyRequiredThe customer's phone number. Format: +212*********
pinstringbodyRequiredPIN of the customer. (4 numbers required)
PATCH{host}/api/customers/pin

Update PIN

Change an existing PIN for security or user preference.

ParameterTypeInRequiredDescription
phoneNumberstringbodyRequiredThe customer's phone number. Format: +212*********
oldPinstringbodyRequiredExisting PIN of the customer.
newPinstringbodyRequiredNew PIN of the customer.
POST{host}/api/customers/pin/reset

Reset PIN

Reset customer PIN after OTP validation.

ParameterTypeInRequiredDescription
phoneNumberstringbodyRequiredThe customer's phone number. Format: +212*********
otpstringbodyRequiredOTP code received via SMS.
pinstringbodyRequiredNew PIN of the customer (4 digits).
GET{host}/api/customers/balance

Get Customer Balance

Retrieve the balance of a registered customer.

ParameterTypeInRequiredDescription
phoneNumberstringqueryRequiredThe customer's phone number. Format: +212*********
GET{host}/api/customers/info

Get Customer Info

Retrieve detailed profile data for a registered customer.

ParameterTypeInRequiredDescription
phoneNumberstringqueryRequiredThe customer's phone number. Format: +212*********

Notes

  • accountLevel : account level (1 = basic, 2-4 = higher KYC levels).
  • customerStatus : customer status (see "Check Status with Chari" endpoint).
  • rib : Bank Account Identifier (RIB) associated with the wallet.
PUT{host}/api/customers/unregister

Unregister

Deactivate or remove a customer from the platform.

ParameterTypeInRequiredDescription
PhoneNumberstringbodyRequiredThe customer's phone number. Format: +212*********
ReasonintbodyRequiredClosure reason code (see notes).

Notes

  • 1 : Closure at the initiative of the EDP — Unspecified reason
  • 2 : Closure at the initiative of the EDP — Suspicion of fraud
  • 3 : Closure at the initiative of the client — Contract closure
  • 4 : Closure at the initiative of the client — Lost or stolen phone
  • 5 : Closure at the initiative of the client — Unspecified reason
K

KYC

Mobile KYC flow (iOS/Android) powered by ShareID. Your app launches the ShareID SDK for document scan and selfie capture; ShareID performs quality, authenticity, and face-to-document matching.

Integration Flow

  1. 1Your app calls /api/kyc/shareid/auth to obtain a short-lived KYC token.
  2. 2The app opens the ShareID SDK with that token.
  3. 3The user scans their ID and completes a guided selfie.
  4. 4ShareID runs the checks.
  5. 5Once the ShareID verification is complete, your app requests the account upgrade via PUT /api/customers/upgrade/request (see "Confirmation").
  6. 6A callback is sent to our API with status and documents.
GET{host}/api/kyc/shareid/auth

Authentication

Obtain a short-lived KYC token to launch ShareID SDK.

ParameterTypeInRequiredDescription
PhoneNumberstringqueryRequiredThe customer's phone number. Format: +212*********

Notes

  • baseUrl : Base URL of the ShareID SDK to use.
  • applicant_id : unique identifier of the KYC request.
  • token : temporary JWT token for SDK-side authentication.
PUT{host}/api/customers/upgrade/request

Confirmation

Signal the KYC flow has finished on-device and request account upgrade.

ParameterTypeInRequiredDescription
PhoneNumberstringqueryRequiredThe customer's phone number. Format: +212*********
AccountLevelintqueryRequiredThe account level to upgrade to (2, 3, or 4).
POST{host}/api/customers/merchant/kyc/request

Merchant KYC Upload

Upload merchant KYC documents to request an account upgrade (multipart/form-data).

ParameterTypeInRequiredDescription
phoneNumberstringqueryOptionalMerchant phone number. Format: +212*********
kycDocumentsmultipart formformRequiredArray of KYC document objects. Multiple documents can be sent in a single request by repeating the indexed fields (e.g. kycDocuments[0], kycDocuments[1], ...).
kycDocuments[n].docTypeintformRequiredDocument type (see Document Types table).
kycDocuments[n].docFrontfileformRequiredFront image of the document. Accepted formats: PNG, JPG/JPEG, PDF.
kycDocuments[n].docBackfileformOptionalBack image (required for IdentityCard, DrivingLicense, ResidencePermit).

Notes

  • KYB — the documents required to create a merchant (professional) wallet depend on the client's legal status. In all three cases the contract signatory's national ID or passport (DocType 1 or 3) and a bank-account proof — RIB / bank-account certificate, or a void cheque / cheque specimen — are required. Upload each document with its matching DocType from the Document Types table.
  • Legal entity (company / organization): signatory's national ID / passport; company articles of association / statutes; minutes of the latest General Assembly confirming signing authority (required only if the manager / legal representative is not listed as the sole signatory in the statutes); Commercial Register certificate (DocType 8) less than 90 days old; Professional Tax registration certificate (Patente); bank-account proof (RIB or void cheque).
  • Individual professional (auto-entrepreneur / freelancer / sole proprietor): signatory's national ID / passport; auto-entrepreneur card / professional registration document; Professional Tax registration certificate (Patente); bank-account proof (RIB or void cheque); Commercial Register certificate (DocType 8) less than 90 days old and company statutes, if applicable.
  • Foundation / association: signatory's national ID / passport; minutes of the latest General Assembly confirming signing authority (required only if the authorized representative is not clearly named in the statutes); list of authorized representatives / board members; association / foundation statute; bank-account proof (RIB or void cheque).
O

Operations

All financial operations: card deposits, wallet-to-wallet transfers, bank transfers, merchant payments, chargebacks, refunds, and reference-based requests.

CashIn Card

Test Credit Card

Valid credit card numbers to add funds in sandbox environment.

PAN

4918914107195005

CVV

123

Expiry

08/26 (or any future date)

3DS Code

555
POST{host}/api/operations/cashin/card/preview

Preview (by Phone)

Check feasibility of depositing funds into a customer's wallet from a card.

ParameterTypeInRequiredDescription
PhoneNumberstringqueryRequiredThe customer's phone number. Format: +212*********
AmountdecimalbodyRequiredAmount to deposit. Must be a positive number.
POST{host}/api/operations/cashin/card

Execute (by Phone)

Add funds to a customer's wallet from a payment card. Triggers 3D Secure authentication.

ParameterTypeInRequiredDescription
phoneNumberstringqueryRequiredThe customer's phone number.
firstNamestringbodyRequiredCardholder's first name.
lastNamestringbodyRequiredCardholder's last name.
cvvstringbodyRequired3-digit security code (CVV).
amountdecimalbodyRequiredAmount to deposit.
panstringbodyRequiredFull card number (PAN).
expiryDatestringbodyRequiredExpiry date in YYMM format.
keepAliveboolbodyRequiredtrue: save the card for future use / false: single use.
cardNamestringbodyOptionalName chosen by the user for the saved card.
3dSecureboolbodyOptionalEnable 3D Secure. Default: true.
autoCaptureboolbodyOptionalAutomatic payment capture.
allowInternationalCardsboolbodyOptionalAccept international cards.
feesPercentdecimalbodyOptionalFee percentage applied to the payer.
internationalFeesPercentdecimalbodyOptionalFee % specific to international cards.
acceptUrlstringbodyOptionalRedirect URL on 3DS success.
declineUrlstringbodyOptionalRedirect URL on 3DS failure.
notificationUrlstringbodyOptionalURL notified when the transaction ends (success/failure).
externalReferencestringbodyOptionalPartner external reference.

Notes

  • After 3D Secure authentication, the user is redirected to acceptURL or declineURL.
  • RESPONSE_CODE in the redirect URL: 0 = success, any other value = failure.
  • REASON_CODE : human-readable reason for the result (e.g., SUCCESS, DECLINED).
  • Validate RESPONSE_CODE and REASON_CODE to determine the next action in your application.
POST{host}/api/operations/cashin/card/{cardId}

Execute with Saved Card

Add funds from a saved tokenized card.

ParameterTypeInRequiredDescription
PhoneNumberstringqueryRequiredThe customer's phone number.
CardIdintrouteRequiredIdentifier of the saved card.
CvvstringbodyRequired3-digit security code.
AmountdecimalbodyRequiredAmount to deposit.

Notes

  • After 3D Secure authentication, the user is redirected to acceptURL or declineURL depending on the outcome.
  • The redirect URL includes parameters: RESPONSE_CODE (0 = success, any other = failure), REASON_CODE (human-readable reason: SUCCESS, DECLINED…) and OPERATION (operation type, e.g. PAYMENT).
  • Validate RESPONSE_CODE and REASON_CODE upon receiving the redirect to determine the next action in your application.
POST{host}/api/operations/cashin/card/agent/preview

Preview (by Agent)

Check feasibility of depositing funds via agent code.

ParameterTypeInRequiredDescription
codestringqueryRequiredAgent code.
AmountdecimalbodyRequiredAmount to deposit.
POST{host}/api/operations/cashin/card/agent

Execute (by Agent)

Add funds to a customer's wallet via agent.

ParameterTypeInRequiredDescription
codestringqueryOptionalCode of the agent whose wallet is credited.
firstNamestringbodyRequiredCardholder's first name.
lastNamestringbodyRequiredCardholder's last name.
cvvstringbodyRequired3-digit security code.
amountdecimalbodyRequiredAmount to deposit.
panstringbodyRequiredFull card number.
expiryDatestringbodyRequiredExpiry date in YYMM format.
keepAliveboolbodyRequiredSave the card for future use.
cardNamestringbodyOptionalName chosen by the user to save the card.
3dSecureboolbodyOptionalEnable 3D Secure. Default: true.
autoCaptureboolbodyOptionalAutomatic payment capture.
allowInternationalCardsboolbodyOptionalAccept international cards.
feesPercentdecimalbodyOptionalFee percentage applied to the payer.
internationalFeesPercentdecimalbodyOptionalFee % specific to international cards.
acceptUrlstringbodyOptionalRedirect URL on 3DS success.
declineUrlstringbodyOptionalRedirect URL on 3DS failure.
notificationUrlstringbodyOptionalURL notified when the transaction ends (success/failure).
externalReferencestringbodyOptionalPartner external reference.

Notes

  • After 3D Secure authentication, the user is redirected to acceptURL or declineURL depending on the outcome.
  • The redirect URL includes parameters: RESPONSE_CODE (0 = success, any other = failure), REASON_CODE (human-readable reason: SUCCESS, DECLINED…) and OPERATION (operation type, e.g. PAYMENT).
  • Validate RESPONSE_CODE and REASON_CODE upon receiving the redirect to determine the next action in your application.

Transfer

POST{host}/api/operations/transfer/preview

Preview

Check feasibility of moving funds between customers' wallets internally.

ParameterTypeInRequiredDescription
CustomerPhoneNumberstringbodyRequiredSender's phone number. Format: +212*********
AmountdecimalbodyRequiredAmount to transfer.
ReasonstringbodyRequiredTransfer reason.
RecipientPhoneNumberstringbodyRequiredBeneficiary's phone number. Format: +212*********
BeneficiaryIdintbodyOptionalReference to an existing beneficiary (optional).
POST{host}/api/operations/transfer

Execute

Move funds between customers' wallets internally.

ParameterTypeInRequiredDescription
CustomerPhoneNumberstringbodyRequiredSender's phone number.
AmountdecimalbodyRequiredAmount to transfer.
ReasonstringbodyRequiredTransfer reason.
RecipientPhoneNumberstringbodyRequiredBeneficiary's phone number.
BeneficiaryIdintbodyOptionalReference to an existing beneficiary (optional).

Bank Transfer

POST{host}/api/operations/bank-transfer/preview

Preview

Check feasibility of sending money from a wallet to an external bank account.

ParameterTypeInRequiredDescription
CustomerPhoneNumberstringbodyOptionalRequired if AgentCode is empty. Mutually exclusive with AgentCode (one OR the other).
AgentCodestringbodyOptionalRequired if CustomerPhoneNumber is empty. Agent Code (Principal or Retail). Mutually exclusive with CustomerPhoneNumber.
AmountdecimalbodyRequiredAmount to transfer.
ReasonstringbodyRequiredTransfer reason (latin characters only, max 35 chars).
BeneficiaryIdintbodyOptionalOptional if rib + beneficiaryName are provided.
BeneficiaryNamestringbodyOptionalOptional if beneficiaryId is provided.
RibstringbodyOptionalRIB: 24-digit numeric string. Optional if beneficiaryId is provided.

Notes

  • At least one identifier among beneficiaryId or (rib + beneficiaryName) must be provided.
POST{host}/api/operations/bank-transfer

Execute

Send money from a wallet to an external bank account.

ParameterTypeInRequiredDescription
CustomerPhoneNumberstringbodyOptionalRequired if AgentCode is empty. Mutually exclusive with AgentCode (one OR the other).
AgentCodestringbodyOptionalRequired if CustomerPhoneNumber is empty. Mutually exclusive with CustomerPhoneNumber.
AmountdecimalbodyRequiredAmount to transfer.
ReasonstringbodyOptionalTransfer reason (optional at execute step).
BeneficiaryIdintbodyOptionalOptional if rib + beneficiaryName are provided.
BeneficiaryNamestringbodyOptionalOptional if beneficiaryId is provided.
RibstringbodyOptionalRIB: 24 digits. Required if no beneficiaryId.

Merchant Payment

POST{host}/api/operations/merchant/payment/push/manual/preview

By Phone — Preview

Check Pay Merchant by PhoneNumber.

ParameterTypeInRequiredDescription
CustomerPhoneNumberstringbodyRequiredPaying customer's phone number.
AmountdecimalbodyRequiredPayment amount.
ReasonstringbodyRequiredPayment reason.
RecipientPhoneNumberstringbodyRequiredThe merchant's phone number.
BeneficiaryIdintbodyOptionalReference to an existing beneficiary (optional).
POST{host}/api/operations/merchant/payment/push/manual

By Phone — Execute

Pay Merchant by PhoneNumber.

ParameterTypeInRequiredDescription
CustomerPhoneNumberstringbodyRequiredPaying customer's phone number.
AmountdecimalbodyRequiredPayment amount.
ReasonstringbodyRequiredPayment reason.
RecipientPhoneNumberstringbodyRequiredThe merchant's phone number.
BeneficiaryIdintbodyOptionalReference to an existing beneficiary (optional).
POST{host}/api/operations/merchant/payment/push/qrcode/preview

By QR Code — Preview

Check Pay Merchant by QR Code.

ParameterTypeInRequiredDescription
CustomerPhoneNumberstringbodyRequiredPaying customer's phone number.
QrCodeContentstringbodyRequiredContent of the scanned QR Code.
AmountdecimalbodyRequiredPayment amount.
POST{host}/api/operations/merchant/payment/push/qrcode

By QR Code — Execute

Pay Merchant by QR Code.

ParameterTypeInRequiredDescription
CustomerPhoneNumberstringbodyRequiredPaying customer's phone number.
QrCodeContentstringbodyRequiredQR Code content.
AmountdecimalbodyRequiredPayment amount.
POST{host}/api/operations/merchant/payment/card/preview

By Card — Preview

Check Pay Merchant by card (Card to Wallet).

ParameterTypeInRequiredDescription
PhoneNumberstringqueryRequiredThe merchant's phone number.
AmountdecimalbodyRequiredPayment amount.
POST{host}/api/operations/merchant/payment/card

By Card — Execute

Pay Merchant by card (Card to Wallet). 3DS flow: the response provides `redirectionURL` to open.

ParameterTypeInRequiredDescription
phoneNumberstringqueryOptionalThe merchant's phone number. Format: +212*********
firstNamestringbodyRequiredCardholder's first name.
lastNamestringbodyRequiredCardholder's last name.
cvvstringbodyRequiredCVV (3 digits).
amountdecimalbodyRequiredPayment amount.
panstringbodyRequiredCard number (PAN).
expiryDatestringbodyRequiredExpiry date in `YYMM` format. Ex: `2608`.
keepAliveboolbodyRequiredTokenize the card for reuse via the Tokenized Card endpoint.
3dSecureboolbodyOptionalEnable 3D Secure. Default: true.
feesPercentdecimalbodyOptionalFee percentage applied to the payer.
allowInternationalCardsboolbodyOptionalAccept international cards.
internationalFeesPercentdecimalbodyOptionalFee % specific to international cards.
autoCaptureboolbodyOptionalAutomatic payment capture.
notificationUrlstringbodyOptionalURL notified when the transaction ends (success/failure).
acceptUrlstringbodyOptionalRedirect URL on 3DS success.
declineUrlstringbodyOptionalRedirect URL on 3DS failure.
cardNamestringbodyOptionalCard label (for tokenization).
externalReferencestringbodyOptionalMerchant external reference.

Notes

  • After 3D Secure authentication, the user is redirected to acceptURL or declineURL depending on the outcome.
  • The redirect URL includes parameters: RESPONSE_CODE (0 = success, any other = failure), REASON_CODE (human-readable reason: SUCCESS, DECLINED…) and OPERATION (operation type, e.g. PAYMENT).
  • Validate RESPONSE_CODE and REASON_CODE upon receiving the redirect to determine the next action in your application.
POST{host}/api/operations/merchant/payment/tokenized/card/{cardId}

By Tokenized Card — Execute

Pay Merchant via a previously tokenized card (`KeepAlive = true`). Only the CVV is required.

ParameterTypeInRequiredDescription
cardIdintpathRequiredTokenized card ID.
PhoneNumberstringqueryRequiredThe merchant's phone number. Format: +212*********
CvvstringbodyRequiredCVV (3 digits).
AmountdecimalbodyRequiredPayment amount.

Notes

  • Same response structure as "Merchant Payment By Card — Execute".
  • After 3D Secure authentication, the user is redirected to acceptURL or declineURL depending on the outcome.
  • The redirect URL includes parameters: RESPONSE_CODE (0 = success, any other = failure), REASON_CODE (human-readable reason) and OPERATION.
GET{host}/api/operations/merchant/qrcode/static

Static QR Generation

Generate a static QR Code for a merchant (no amount embedded). The customer enters the amount at payment time.

ParameterTypeInRequiredDescription
customerPhoneNumberstringqueryOptionalPhone number of the merchant (customer) to generate the QR for. Format: +212*********
maskedNumberboolqueryOptionalMask the merchant's number in the QR content. Ex: +2126######74
billNumberstringbodyOptionalBill number to embed in the QR content (optional).
additionalDatastringbodyOptionalFree-form additional data to embed in the QR content (optional).

Notes

  • The query parameter is named customerPhoneNumber (not phoneNumber).
  • billNumber and additionalData are sent in the request body (optional).
POST{host}/api/operations/merchant/qrcode

Dynamic QR Generation

Generate a dynamic QR Code with a fixed amount and a unique reference.

ParameterTypeInRequiredDescription
customerPhoneNumberstringqueryOptionalPhone number of the merchant (customer) to generate the QR for. Format: +212*********
maskedNumberboolqueryOptionalMask the merchant's number.
amountdecimalbodyRequiredFixed amount of the QR Code.
billNumberstringbodyOptionalBill number to embed in the QR content (optional).
additionalDatastringbodyOptionalFree-form additional data to embed in the QR content (optional).

Notes

  • Static QR (GET): no embedded amount, the customer enters the amount at payment time.
  • Dynamic QR (POST): fixed embedded amount, unique `qrCodeReference` reference.
  • The query parameter is named customerPhoneNumber (not phoneNumber).
POST{host}/api/operations/merchant/payment/card/capture

By Card — Capture

Capture a merchant card payment authorization. Use it to finalize a payment initiated with `AutoCapture = false`: the authorized funds are then actually debited.

ParameterTypeInRequiredDescription
PhoneNumberstringbodyRequiredThe merchant's phone number. Format: +212*********
AmountdecimalbodyRequiredAmount to capture.
OrderIdstringbodyRequiredOrder identifier returned by the card payment (`orderId`).
TransactionTrackIdstringbodyRequiredTracking identifier returned by the card payment (`transactionTrackId`).
SkipGatewayCallboolbodyOptionalIf true, skip the payment gateway call during capture.

Notes

  • Required scope: operations:merchant-payment.
  • orderId and transactionTrackId come from the card payment response ("By Card — Execute" endpoint).
  • Typical flow: card payment with AutoCapture = false → authorization → capture (this endpoint) or cancellation (reverse).
POST{host}/api/operations/merchant/payment/card/reverse

By Card — Reverse

Reverse a merchant card payment authorization that has not been captured yet: the authorized funds are released without being debited.

ParameterTypeInRequiredDescription
PhoneNumberstringbodyRequiredThe merchant's phone number. Format: +212*********
AmountdecimalbodyRequiredAmount of the authorization to reverse.
OrderIdstringbodyRequiredOrder identifier returned by the card payment (`orderId`).
TransactionTrackIdstringbodyRequiredTracking identifier returned by the card payment (`transactionTrackId`).
SkipGatewayCallboolbodyOptionalIf true, skip the payment gateway call during the reversal.

Notes

  • Required scope: operations:merchant-payment.
  • Request body identical to the Capture endpoint: target the transaction via orderId and transactionTrackId.
  • A reversal applies to an uncaptured authorization; for an already captured payment, use the Refund endpoint.
POST{host}/api/operations/merchant/payment/card/refund

By Card — Refund

Refund an already captured merchant card payment, in full or partially via `RefundAmount`.

ParameterTypeInRequiredDescription
PhoneNumberstringbodyRequiredThe merchant's phone number. Format: +212*********
OperationIdintbodyRequiredIdentifier of the operation to refund.
RefundAmountdecimalbodyRequiredAmount to refund.
OrderIdstringbodyOptionalOrder identifier of the original transaction (`orderId`).
TransactionTrackIdstringbodyOptionalTracking identifier of the original transaction (`transactionTrackId`).

Notes

  • Required scope: operations:refund (different from the operations:merchant-payment scope of the other card endpoints).
  • A RefundAmount lower than the captured amount performs a partial refund.
GET{host}/api/operations/merchant/qrcode/status

QR Code Status

Check the status of a merchant QR Code by its reference.

ParameterTypeInRequiredDescription
referencestringqueryRequiredReference of the QR Code to check.

ChargeBack

POST{host}/api/operations/chargeback/preview

Preview

Check the feasibility of performing a chargeback.

ParameterTypeInRequiredDescription
SourcePhoneNumberstringbodyRequiredOriginating customer's phone number. Format: +212*********
AmountdecimalbodyRequiredChargeback amount.
DescriptionstringbodyRequiredChargeback reason.
DestinationPhoneNumberstringbodyRequiredRecipient's phone number. Format: +212*********
OriginalOperationIdintbodyRequiredID of the original operation that triggered the chargeback.
POST{host}/api/operations/chargeback

Execute

Execute a chargeback operation.

ParameterTypeInRequiredDescription
SourcePhoneNumberstringbodyRequiredOriginating customer's phone number.
AmountdecimalbodyRequiredChargeback amount.
DescriptionstringbodyRequiredChargeback reason.
DestinationPhoneNumberstringbodyRequiredRecipient's phone number.
OriginalOperationIdintbodyRequiredOriginal operation ID.

Request Operations

POST{host}/api/operations/cashin/request

Request CashIn

Request a CashIn operation. Generates a unique reference that expires over time.

ParameterTypeInRequiredDescription
PhoneNumberstringbodyRequiredThe customer's phone number.
AmountdecimalbodyRequiredCashIn amount.

Notes

  • operationType: 1 = CashIn, 2 = CashOut
  • operationStatus: 1 = open, 2 = completed, 3 = failed, 4 = canceled
POST{host}/api/operations/fatourati/cashin/request

Request CashIn (Fatourati)

Initiate a CashIn operation via the Fatourati provider. Dedicated endpoint — Fatourati is a special provider with its own reference generation flow (FATREF- prefix). Use this dedicated route instead of the standard cashin endpoint; reference generation behavior and expiry rules may differ.

ParameterTypeInRequiredDescription
PhoneNumberstringbodyRequiredThe customer's phone number. For a principal agent, replace phoneNumber by the Agent Code (PhoneNumber => Code).
AmountdecimalbodyRequiredThe amount to cash in. Should be a positive numeric value.
DescriptionstringbodyOptionalA free-text field describing the purpose of the operation.
FeesPercentdecimalbodyOptionalFee percentage applied (shown in the documentation example).

Notes

  • Dedicated endpoint: Fatourati has its own reference generation flow (FATREF- prefix), distinct from the standard CashIn flow.
  • type (operationType): 1 = CashIn, 2 = CashOut
  • status (operationStatus): 1 = open, 2 = completed, 3 = failed
POST{host}/api/operations/cashout/request

Request CashOut

Request a CashOut operation. Generates a unique reference that expires over time.

ParameterTypeInRequiredDescription
PhoneNumberstringbodyRequiredThe customer's phone number.
AmountdecimalbodyRequiredCashOut amount.

Get Operations

GET{host}/api/operations

By Customer

Get a list of operations for a specific customer.

ParameterTypeInRequiredDescription
PhoneNumberstringqueryRequiredThe customer's phone number.
PageSizeintqueryOptionalResults per page. Default: 10.
PageNumberintqueryOptionalPage number. Default: 1.
OperationTypelist intqueryOptionalFilter by operation type (repeatable): 1=CASHIN, 2=CASHOUT, 3=TRANSFER, 5=MOBILE_PAYMENT, 7=PAYMENT_REFUND, 9=BANK_TRANSFER, 10=RECHARGE, 12=CHARGEBACK, 23=VOUCHER, 24=CARD_PAYMENT, 25=BILL_PAYMENT.
TransactionStatusintqueryOptionalFilter by status: 1=OPEN, 2=COMPLETED, 3=FAILED, 4=CANCELED.
SensintqueryOptionalOperation direction: 1=CREDIT, 2=DEBIT.
FromdatetimequeryOptionalFilter start date/time.
TodatetimequeryOptionalFilter end date/time.
KeywordstringqueryOptionalSearch keyword.

Notes

  • collection: paginated list of operations.
  • count: total number of operations matching the filters.
  • accountNumber: can be a phone number, a RIB or an accountId.
GET{host}/api/operations/{id}

By ID

Get a specific operation by its ID.

ParameterTypeInRequiredDescription
PhoneNumberstringqueryRequiredThe customer's phone number.
IdintrouteRequiredOperation ID.

Notes

  • operationId: identifier of the overall operation.
  • transactionId: identifier of the main transaction (one operation can generate several transactions: sender debit, recipient credit, fees, etc.).
  • transactionReference: reference of the main transaction.
  • amount: initial amount.
  • totalAmount: amount after fees and commissions are applied.
GET{host}/api/operations/all

All (by Partner)

Get a list of all operations by partner.

ParameterTypeInRequiredDescription
pageNumberintqueryOptionalPage number (starts at 1). Default: 1.
pageSizeintqueryOptionalResults per page. Default: 10.
operationTypelist intqueryOptionalFilter by operation type(s). Repeatable parameter.
operationStatuslist intqueryOptionalFilter by operation status(es). Repeatable parameter.
fromdatetimequeryOptionalOperations from datetime.
todatetimequeryOptionalOperations until datetime.
searchstringqueryOptionalSearch keyword.
openLoopbooleanqueryOptionalFilter open-loop operations (outside Chari wallets).
methodstringqueryOptionalFilter by payment method.
includeDetailsbooleanqueryOptionalInclude each operation's details in the response.

Notes

  • Partner-wide endpoint: no phoneNumber is required. For a specific customer's operations, use GET /api/operations.
  • operationType and operationStatus accept multiple values by repeating the parameter (e.g. ?operationType=1&operationType=2).

Refund

POST{host}/api/operations/refund/preview

Preview

Check refund feasibility after merchant payment.

ParameterTypeInRequiredDescription
PhoneNumberstringbodyRequiredPhone number of the customer to refund.
OperationIdintbodyRequiredID of the operation to refund.
RefundAmountdecimalbodyRequiredRefund amount.
OrderIdstringbodyRequiredOriginal paymentGateway OrderId.
TransactionTrackIdstringbodyRequiredOriginal paymentGateway TransactionTrackId.
POST{host}/api/operations/refund

Execute

Refund customers after merchant payment.

ParameterTypeInRequiredDescription
phoneNumberstringbodyRequiredThe customer's phone number.
OperationIdintbodyRequiredID of the operation to refund.
RefundAmountdecimalbodyRequiredRefund amount.
OrderIdstringbodyRequiredOriginal OrderId.
TransactionTrackIdstringbodyRequiredOriginal TransactionTrackId.
B

Beneficiary

Manage a customer's beneficiaries: list, add, update, and delete. Beneficiaries can be identified by phone number and/or RIB.

GET{host}/api/customer/beneficiaries

Get Beneficiaries

Get a list of beneficiaries for a customer.

ParameterTypeInRequiredDescription
PhoneNumberstringqueryRequiredThe customer's phone number.
PageSizeintqueryOptionalResults per page. Default: 10.
PageNumberintqueryOptionalPage number. Default: 1.
SortBystringqueryOptionalSort field.
SortOrderstringqueryOptionalSort order (asc or desc).
NamestringqueryOptionalFilter by beneficiary name.
BeneficiaryNumberstringqueryOptionalFilter by beneficiary phone number.
RibstringqueryOptionalFilter by beneficiary RIB.
SearchstringqueryOptionalFilter by keyword.
FromdatetimequeryOptionalCreation date — start.
TodatetimequeryOptionalCreation date — end.
POST{host}/api/customer/beneficiaries

Add Beneficiary

Add a new beneficiary. At least PhoneNumber or RIB must be provided.

ParameterTypeInRequiredDescription
phoneNumberstringqueryRequiredCustomer (owner) phone number.
namestringbodyRequiredBeneficiary name. Minimum 2 letters.
phoneNumberstringbodyOptionalBeneficiary's phone number. Format: +212*********
ribstringbodyOptionalBeneficiary RIB. 24 digits.
emailstringbodyOptionalBeneficiary email.

Notes

  • PhoneNumber or RIB: at least one of the two must be provided.
PUT{host}/api/customer/beneficiaries/{beneficiaryId}

Update Beneficiary

Update an existing beneficiary.

ParameterTypeInRequiredDescription
phoneNumberstringqueryRequiredCustomer (owner) phone number.
beneficiaryIdintpathRequiredBeneficiary ID to update.
namestringbodyRequiredBeneficiary name. Minimum 2 letters.
phoneNumberstringbodyOptionalBeneficiary phone number.
ribstringbodyOptionalBeneficiary RIB. 24 digits.
emailstringbodyOptionalBeneficiary email.
DELETE{host}/api/customer/beneficiaries/{Id}

Delete Beneficiary

Delete an existing beneficiary.

ParameterTypeInRequiredDescription
PhoneNumberstringqueryRequiredThe customer's phone number.
IdintrouteRequiredID of the beneficiary to delete.
T

Tokenized Cards

View and manage saved (tokenized) bank cards of a customer.

GET{host}/api/customers/tokenized/cards

Get Cards by Customer

Retrieve all tokenized cards for a customer.

ParameterTypeInRequiredDescription
PhoneNumberstringqueryRequiredThe customer's phone number.
PageSizeintqueryOptionalResults per page. Default: 10.
PageNumberintqueryOptionalPage number. Default: 1.

Notes

  • customerBankCardId: unique identifier for the saved card.
  • maskedPan: masked card number (last 4 digits).
  • issuer: name of the issuing bank.
  • scheme: card network (Visa, Mastercard, etc.).
  • cardName: optional label chosen by the customer at tokenization.
GET{host}/api/customers/tokenized/cards/{id}

Get Card by ID

Retrieve a specific tokenized card by its ID.

ParameterTypeInRequiredDescription
PhoneNumberstringqueryRequiredThe customer's phone number.
IdintrouteRequiredCard ID.
DELETE{host}/api/customers/tokenized/cards/{cardId}

Delete Tokenized Card

Delete a tokenized card by its Id.

ParameterTypeInRequiredDescription
cardIdintpathRequiredTokenized card ID to delete.
phoneNumberstringqueryRequiredThe customer's phone number. Format: +212*********
GET{host}/api/agents/tokenized/cards

Get Agent Cards

Get the paginated list of an agent's tokenized cards.

ParameterTypeInRequiredDescription
codestringqueryRequiredAgent code.
pageSizeintqueryOptionalHow many results are returned per page. Default value = 10.
pageNumberintqueryOptionalWhich page of results to retrieve. Starts at 1. Default value = 1.

Notes

  • customerTokenizedCardId: unique identifier of the tokenized card, to use as {cardId} in the detail, rename and delete endpoints.
  • maskedPan: masked card number (last 4 digits).
  • requiredCvv: true if the CVV must be re-entered for each cash-in with this card.
  • These cards are used for agent-side card deposits (agent card cash-in).
GET{host}/api/agents/tokenized/cards/{cardId}

Get Agent Card by ID

Retrieve a specific tokenized card of an agent by its ID.

ParameterTypeInRequiredDescription
codestringqueryRequiredAgent code.
cardIdintrouteRequiredTokenized card identifier.

Notes

  • The card must belong to the agent identified by code, otherwise it is not returned.
PUT{host}/api/agents/tokenized/cards/{cardId}

Update Agent Card Name

Update the name (cardName) of an agent's tokenized card.

ParameterTypeInRequiredDescription
codestringqueryRequiredAgent code.
cardIdintrouteRequiredIdentifier of the tokenized card to rename.
cardNamestringbodyRequiredNew card name.

Notes

  • HTTP 200 confirms the update (no detailed response body).
  • Only the cardName label can be changed: the other attributes of the tokenized card are immutable.
DELETE{host}/api/agents/tokenized/cards/{cardId}

Delete Agent Card

Delete an agent's tokenized card.

ParameterTypeInRequiredDescription
cardIdintrouteRequiredIdentifier of the tokenized card to delete.
codestringqueryRequiredAgent code.

Notes

  • HTTP 200 confirms the deletion (no detailed response body).
  • Deletion is permanent: to use the card again, it must be tokenized anew.
R

Retail Agents

Manage retail agents: list, add, and execute CashIn/CashOut operations by reference.

GET{host}/api/agents/retail

Get Retail Agents

List all retail agents.

ParameterTypeInRequiredDescription
CodestringqueryRequiredAgent code.
PageSizeintqueryOptionalResults per page. Default: 10.
PageNumberintqueryOptionalPage number. Default: 1.
FromdatetimequeryOptionalAgent creation — start date.
TodatetimequeryOptionalAgent creation — end date.
GET{host}/api/agents/retail/{code}

Get Agent by Code

Get a specific retail agent by code.

ParameterTypeInRequiredDescription
CodestringrouteRequiredAgent code.
POST{host}/api/agents/retail

Add Retail Agent

Add a new retail agent.

ParameterTypeInRequiredDescription
PhoneNumberstringbodyRequiredThe agent's phone number. Format: +212*********
NamestringbodyRequiredAgent's trade name.
FirstNamestringbodyRequiredFirst name. Minimum 2 letters.
LastNamestringbodyRequiredLast name. Minimum 2 letters.
CinstringbodyRequiredID document number.
AddressstringbodyOptionalAgent's address.
EmailstringbodyOptionalAgent's email.
PUT{host}/api/agents/retail/{code}

Update Retail Agent

Update an existing retail agent, identified by their code.

ParameterTypeInRequiredDescription
CodestringrouteRequiredCode of the agent to update.
NamestringbodyOptionalAgent's trade name.
FirstNamestringbodyOptionalAgent's first name.
LastNamestringbodyOptionalAgent's last name.
PhoneNumberstringbodyOptionalThe agent's phone number. Format: +212*********
CinstringbodyOptionalID document number.
AddressstringbodyOptionalAgent's address.
EmailstringbodyOptionalAgent's email.
GenderstringbodyOptionalAgent's gender.

Notes

  • All body fields are optional (nullable) in the swagger schema.
  • A 204 No Content response confirms the update; the production swagger does not publish a response body.
  • 400 / 401: ProblemDetails-formatted response (Bad Request / Unauthorized).
GET{host}/api/operations/cashin/request

Get CashIn by Reference

Retrieve requested operation details using a unique reference ID.

ParameterTypeInRequiredDescription
ReferencestringqueryRequiredUnique reference of the operation.

Notes

  • type: 1 = CashIn, 2 = CashOut
  • status: 1 = open, 2 = completed, 3 = failed
POST{host}/api/operations/cashin/agent

Execute CashIn by Reference

Execute a CashIn operation by the agent.

ParameterTypeInRequiredDescription
CodestringbodyRequiredThe code of the Agent performing the operation.
ReferencestringbodyRequiredThe reference ID of the operation to retrieve.
GET{host}/api/operations/cashout/request

Get CashOut by Reference

Retrieve CashOut operation details by reference.

ParameterTypeInRequiredDescription
ReferencestringqueryRequiredUnique reference of the operation.
POST{host}/api/operations/cashout/agent

Execute CashOut by Reference

Execute a CashOut operation by the agent.

ParameterTypeInRequiredDescription
CodestringbodyRequiredThe code of the Agent performing the operation.
ReferencestringbodyRequiredThe reference ID of the operation to retrieve.
P

Principal Agents

View information about a principal agent.

GET{host}/api/agents/principal/{code}

Get Principal Agent by Code

Get the account info of a principal agent.

ParameterTypeInRequiredDescription
codestringpathRequiredThe code of the principal agent.

Notes

  • Response: Agent object + Account object (balance, RIB, level, etc.).
C

Card Management

Card issuing and management: card programs, applications, cards, usage control and transactions.

⚠️ Beta section. The bank card documentation is still preliminary: missing endpoints will be added and it may contain errors. If you run into any issue, contact Hedi ZaZ (VP of BaaS) on WhatsApp: wa.me/212600000010

GET{host}/api/cards/programs

Get Programs

Get a list of available programs for the partner.

ParameterTypeInRequiredDescription
pageintqueryOptionalWhich page of results to retrieve. Starts at 1. Default value = 1.
takeintqueryOptionalHow many results are returned per page. Default value = 10.

Notes

  • collection : list of programs.
  • count : count of programs.
  • Pagination uses page and take (not PageNumber/PageSize).
POST{host}/api/cards/applications

Add Application

Add a new card application.

ParameterTypeInRequiredDescription
PhoneNumberstringqueryRequiredThe customer's phone number. Format: +212*********
cardProgramIdintqueryRequiredCard program identifier.

Notes

  • No body for now.
GET{host}/api/cards/applications

Get Applications

Get a list of applications by filters.

ParameterTypeInRequiredDescription
statusintqueryOptionalFilter by status: 1=Pending, 2=Validated, 3=Rejected.
pageintqueryOptionalWhich page of results to retrieve. Starts at 1. Default value = 1.
takeintqueryOptionalHow many results are returned per page. Default value = 10.

Notes

  • collection : list of applications.
  • count : count of applications.
  • CardApplicationStatus — 1: PENDING, 2: VALIDATED, 3: REJECTED.
  • Pagination uses page and take (not PageNumber/PageSize).
GET{host}/api/cards/applications/customer

Get Application by Customer

Get a list of applications by customer.

ParameterTypeInRequiredDescription
phoneNumberstringqueryRequiredThe customer's phone number. Format: +212*********
pageintqueryOptionalWhich page of results to retrieve. Starts at 1. Default value = 1.
takeintqueryOptionalHow many results are returned per page. Default value = 10.

Notes

  • collection : list of applications.
  • count : count of applications.
  • Pagination uses page and take (not PageNumber/PageSize).
PUT{host}/api/cards/applications/{id}/validate

Validate Application

Validate an existing application in progress.

ParameterTypeInRequiredDescription
idintpathRequiredApplication Id to validate.

Notes

  • No body for now.
PUT{host}/api/cards/applications/{id}/reject

Reject Application

Reject an existing application in progress.

ParameterTypeInRequiredDescription
idintpathRequiredApplication Id to reject.
reasonstringbodyOptionalRejection reason (optional), later returned in rejectionReason.

Notes

  • The body accepts an optional reason field: the reason is returned in the application's rejectionReason.
GET{host}/api/cards

Get Cards

Get a list of cards by partner.

ParameterTypeInRequiredDescription
pageNumberintqueryOptionalWhich page of results to retrieve. Starts at 1. Default value = 1.
pageSizeintqueryOptionalHow many results are returned per page. Default value = 10.
customerIdintqueryOptionalFilter by customer id.
accountIdintqueryOptionalFilter by account id.
cardProgramIdintqueryOptionalCard program id.
statusintqueryOptionalCard status: 1=ISSUED, 2=ACTIVATED, 3=BLOCKED, 4=SUSPENDED, 5=EXPIRED, 6=CANCELLED.
isVirtualbooleanqueryOptionalFilter virtual (true) or physical (false) cards.
schemaIdintqueryOptionalCard scheme id (e.g. VISA).
deliveryStatusIdintqueryOptionalDelivery status id (see card enums).

Notes

  • collection : list of cards.
  • count : count of cards.
  • CardType — 1: PHYSICAL, 2: VIRTUAL, 3: DIGITAL.
  • DeliveryStatus — 1: PENDING, 2: SENT_TO_PERSONALIZATION, 3: READY_FOR_DELIVERY, 4: DELIVERED.
  • CardStatus — 1: ISSUED, 2: ACTIVATED, 3: BLOCKED, 4: SUSPENDED, 5: EXPIRED, 6: CANCELLED.
  • The status filter is named status (not CardStatusId); filtering by customer uses customerId (no PhoneNumber).
GET{host}/api/cards/{id}

Get Card by Id

Get a specific card by id.

ParameterTypeInRequiredDescription
idintpathRequiredCard Id.
PUT{host}/api/cards/{id}/activate

Activate Card

Activate the card and make it ready for use.

ParameterTypeInRequiredDescription
PhoneNumberstringqueryRequiredThe customer's phone number. Format: +212*********
IdintrouteRequiredCard Id to activate.

Notes

  • Response: the updated card object. cardStatus 2 = ACTIVATED.
PUT{host}/api/cards/{id}/block

Block Card

Temporarily block the card from any transactions.

ParameterTypeInRequiredDescription
PhoneNumberstringqueryRequiredThe customer's phone number. Format: +212*********
IdintrouteRequiredCard Id to block.
ReasonstringbodyOptionalReason for blocking the card.

Notes

  • Response: the updated card object. cardStatus 3 = BLOCKED.
PUT{host}/api/cards/{id}/suspend

Suspend Card

Suspend the card usage until further notice.

ParameterTypeInRequiredDescription
PhoneNumberstringqueryRequiredThe customer's phone number. Format: +212*********
IdintrouteRequiredCard Id to suspend.
ReasonstringbodyOptionalReason for suspending the card.

Notes

  • Response: the updated card object. cardStatus 4 = SUSPENDED.
PUT{host}/api/cards/{id}/reactivate

Reactivate Card

Reactivate a previously suspended card.

ParameterTypeInRequiredDescription
PhoneNumberstringqueryRequiredThe customer's phone number. Format: +212*********
IdintrouteRequiredCard Id to reactivate.

Notes

  • Response: the updated card object. cardStatus 2 = ACTIVATED.
PUT{host}/api/cards/{id}/cancel

Cancel Card

Permanently cancel and deactivate the card.

ParameterTypeInRequiredDescription
PhoneNumberstringqueryRequiredThe customer's phone number. Format: +212*********
IdintrouteRequiredCard Id to cancel.
ReasonstringbodyOptionalReason for cancelling the card.

Notes

  • Response: the updated card object. cardStatus 6 = CANCELLED. This action is permanent: the card can no longer be reactivated.
PUT{host}/api/cards/{id}/services

Card Usage Control

Update card services for usage control.

ParameterTypeInRequiredDescription
PhoneNumberstringqueryRequiredThe customer's phone number. Format: +212*********
IdintrouteRequiredCard Id to update.
allowAtmboolbodyRequiredEnable or disable ATM withdrawals for the card.
allowOnlineboolbodyRequiredEnable or disable online/e-commerce transactions.
allowPosboolbodyRequiredEnable or disable POS (Point of Sale) payments.
contactlessEnabledboolbodyRequiredEnable or disable contactless payments.

Notes

  • Response: true / false.
GET{host}/api/card-transactions/card/{cardId}

Get Card Transactions

Get card transactions.

ParameterTypeInRequiredDescription
PhoneNumberstringqueryRequiredThe customer's phone number. Format: +212*********
CardIdintrouteRequiredCard Id.
PageSizeintqueryOptionalHow many results are returned per page. Default value = 10.
PageNumberintqueryOptionalWhich page of results to retrieve. Starts at 1. Default value = 1.
FromdatetimequeryOptionalFilter from date.
TodatetimequeryOptionalFilter to date.

Notes

  • collection : list of transactions.
  • count : count of transactions.
N

Network Operations (Sandbox)

Network endpoints to execute and look up CashIn/CashOut reference operations (network agent step). They work in sandbox as well as in production: in sandbox, call them yourself to complete your test flows without a real agent network, combined with the test card below to run an end-to-end flow.

Test Credit Card

Use this test card data for card deposit testing in sandbox environment.

PAN

Click to copy

CVV

Click to copy

Expiry

Click to copy — API: 2608 (or any future date)

3DS Code

Click to copy

POST{host}/api/network/operations/cashin200

Execute Network CashIn

Executes a CashIn from a network entity by reference (network agent step). Triggers the `cashin.network.executed` webhook. In sandbox, call this endpoint yourself to complete your tests.

ParameterTypeInRequiredDescription
withContextboolqueryOptionalGet the result with context if it exists. Default: false.
referencestringbodyRequiredNumeric reference returned when the CashIn request was created.
entitystringbodyOptionalNetwork entity executing the operation.
POST{host}/api/network/operations/cashout200

Execute Network CashOut

Executes a CashOut from a network entity by reference (network agent step). Triggers the `cashout.network.executed` webhook. In sandbox, call this endpoint yourself to complete your tests.

ParameterTypeInRequiredDescription
withContextboolqueryOptionalGet the result with context if it exists. Default: false.
referencestringbodyRequiredNumeric reference returned when the CashOut request was created.
entitystringbodyOptionalNetwork entity executing the operation.
W

Webhooks

Webhooks let ChariBaaS notify your system about events (operation completed, KYC updates, etc.) in near-real time. Your server exposes an HTTPS endpoint; we POST signed JSON events to it.

HTTP Request

POSThttps://{your-domain}/webhooks/chari

You can provide any other endpoint.

Headers

Content-Type: application/jsonUser-Agent: Chari-BAAS-Webhook/1.0C-Webhook-Id: xxxxxxxx-xxxxxxxx-xxxxxxxx-xxxxxxxxX-Api-Key: xxxxxxxx
  • C-Webhook-Id: unique identifier of the webhook request, generated by Chari.
  • X-Api-Key: secret key used to authenticate against your system (you must provide us with this key).

Expected response: 200 OK within 5s (empty body). In case of a business error or breach of contract sent by us, please return a 400 error with a description of the problem. Any non-2xx triggers a retry.

Event Body Properties

Common properties

PropertyTypeRequiredDescription
WebhookIdstringRequiredWebhook identifier.
EventIdstringRequiredEvent type. Ex: bank-transfer.initiated
CRequestIdstringRequiredTracking identifier received from the partner.
OperationIdintRequiredID of the executed operation (can be 0 if no operation was created).
TransactionIdintOptionalMain transaction ID.
OperationTypeintRequiredOperation type code (see Types).
OperationStatusintRequired1 = Open, 2 = Completed, 3 = Failed, 4 = Canceled
CreatedAtdateRequiredProcess start date.
ExecutedAtdateRequiredOperation execution date.
AmountdecimalRequiredOperation amount.
FeeAmountdecimalRequiredFee amount.
PrimaryAccountNumberstringRequiredSender's phone number.
SecondaryAccountNumberstringOptionalRecipient's phone number.
MethodstringOptionalMethod: Card / Agent / Network

Cash-in Card specific

PropertyTypeRequiredDescription
CustomDatastringOptionalCustom data provided by the partner (max 128 characters).
GatewayTrackIdstringOptionalGateway Transaction Track Id.
GatewayOrderIdstringOptionalGateway Transaction Order Id.
GatewayReferenceIdstringOptionalGateway Transaction Reference Id.

Bank Transfer specific

PropertyTypeRequiredDescription
BankTransferBeneficiaryNamestringOptionalBeneficiary name for bank transfers.

Cash-in / Cash-out (network reference)

PropertyTypeRequiredDescription
NetworkNamestringOptionalNetwork name for network operations.
ReferencestringOptionalReference of the by-reference operation.

Retry Policy

Backoff:1m, 5m, 30m, 60m, then every 6h up to 72h total.
Stop:On first 200.
Dead letter:After 72h marked as undeliverable.

Events

Event IDDescription
customer.level.updatedCustomer account level updated
cashin.card.authorizedCashIn by Card accepted
payment.card.authorizedPayment by Card accepted
payment.receivedPayment received by merchant
payment.confirmedBill payment confirmed (CONFIRME state)
payment.cancelledBill payment cancelled (ANNULE state)
payment.refundedBill payment refunded (REMBOURSE state)
payment.failedBill payment failed (FAILED state)
bank-transfer.initiatedBank transfer sent
bank-transfer.completedBank transfer finalized (settled, rejected, or returned — inspect OperationStatus)
bank-transfer.receivedBank transfer received
transfer.receivedTransfer received
cashin.network.executedCashIn by reference executed
cashout.network.executedCashOut by reference executed

Example Event Body

customer.level.updated — Customer level updated

json
{
  "data": {
    "WebhookId": 12344,
    "EventId": "customer.level.updated",
    "CRequestId": "3f2c8d71-4b6e-4a2f-9c58-1e7d0a6b3c44",
    "OperationId": 0,
    "CreatedAt": "2025-11-05T08:55:00Z",
    "ExecutedAt": "2025-11-05T08:55:04Z",
    "PrimaryAccountNumber": "+212711111111",
    "CustomData": "kyc-upgrade-7841"
  }
}

cashin.card.authorized — CashIn by Card accepted

json
{
  "data": {
    "WebhookId": 12346,
    "EventId": "cashin.card.authorized",
    "CRequestId": "7b8c9f1a-15da-4e1c-8c3b-3a2bd0ed5e6f",
    "OperationId": 563210,
    "OperationType": 1,
    "OperationStatus": 2,
    "CreatedAt": "2025-11-05T09:41:00Z",
    "ExecutedAt": "2025-11-05T09:41:18Z",
    "Amount": 10000.00,
    "FeeAmount": 150.00,
    "CustomData": "ref12345",
    "PrimaryAccountNumber": "+212711111111",
    "Method": "Card",
    "GatewayTrackId": "83c1d1c7",
    "GatewayOrderId": "20251105_00045",
    "GatewayReferenceId": "6f92b0aa"
  }
}

payment.card.authorized — Payment by Card accepted

json
{
  "data": {
    "WebhookId": 12347,
    "EventId": "payment.card.authorized",
    "CRequestId": "c91d2a47-6f3b-4e8d-a1c5-7b9e0d2f4a61",
    "OperationId": 641205,
    "OperationType": 24,
    "OperationStatus": 2,
    "CreatedAt": "2025-11-05T09:47:00Z",
    "ExecutedAt": "2025-11-05T09:47:21Z",
    "Amount": 450.00,
    "FeeAmount": 0.00,
    "CustomData": "order-88123",
    "PrimaryAccountNumber": "+212711111111",
    "SecondaryAccountNumber": "+212722222222",
    "Method": "Card",
    "GatewayTrackId": "9ad2f3b1",
    "GatewayOrderId": "20251105_00072",
    "GatewayReferenceId": "4b7e91cc"
  }
}

payment.received — Payment received by merchant

json
{
  "data": {
    "WebhookId": 12348,
    "EventId": "payment.received",
    "CRequestId": "5e8a1c3d-92f4-4b7a-8d6e-0c1b3a5f7e92",
    "OperationId": 652118,
    "OperationType": 5,
    "OperationStatus": 2,
    "CreatedAt": "2025-11-05T11:02:00Z",
    "ExecutedAt": "2025-11-05T11:02:09Z",
    "Amount": 250.00,
    "FeeAmount": 0.00,
    "CustomData": "pos-ticket-4521",
    "PrimaryAccountNumber": "+212711111111",
    "SecondaryAccountNumber": "+212722222222",
    "Method": null
  }
}

payment.confirmed — Bill payment confirmed (CONFIRME)

json
{
  "data": {
    "WebhookId": 12349,
    "EventId": "payment.confirmed",
    "CRequestId": "d2f7b9e1-3c5a-4d8f-b6a0-9e4c1d7a2b53",
    "OperationId": 673402,
    "OperationType": 25,
    "OperationStatus": 2,
    "CreatedAt": "2025-11-05T11:30:00Z",
    "ExecutedAt": "2025-11-05T11:30:41Z",
    "Amount": 286.50,
    "FeeAmount": 5.00,
    "CustomData": "invoice-2025-1105",
    "PrimaryAccountNumber": "+212711111111",
    "Method": null
  }
}

payment.cancelled — Bill payment cancelled (ANNULE)

json
{
  "data": {
    "WebhookId": 12350,
    "EventId": "payment.cancelled",
    "CRequestId": "e6a3c8d5-1b7f-4a2e-9c4d-3f8b0a6e1d27",
    "OperationId": 673415,
    "OperationType": 25,
    "OperationStatus": 4,
    "CreatedAt": "2025-11-05T11:32:00Z",
    "ExecutedAt": "2025-11-05T11:32:38Z",
    "Amount": 286.50,
    "FeeAmount": 0.00,
    "CustomData": "invoice-2025-1105",
    "PrimaryAccountNumber": "+212711111111",
    "Method": null
  }
}

payment.refunded — Bill payment refunded (REMBOURSE)

json
{
  "data": {
    "WebhookId": 12351,
    "EventId": "payment.refunded",
    "CRequestId": "f1b4d7a2-8e6c-4f3a-b5d9-2a7c0e4b8f16",
    "OperationId": 674033,
    "OperationType": 25,
    "OperationStatus": 2,
    "CreatedAt": "2025-11-05T14:05:00Z",
    "ExecutedAt": "2025-11-05T14:05:33Z",
    "Amount": 286.50,
    "FeeAmount": 0.00,
    "CustomData": "invoice-2025-1105",
    "PrimaryAccountNumber": "+212711111111",
    "Method": null
  }
}

payment.failed — Bill payment failed (FAILED)

json
{
  "data": {
    "WebhookId": 12352,
    "EventId": "payment.failed",
    "CRequestId": "0a5c9e2f-7d1b-4c6a-8f3e-b9d4a2c7e051",
    "OperationId": 674590,
    "OperationType": 25,
    "OperationStatus": 3,
    "CreatedAt": "2025-11-05T14:18:00Z",
    "ExecutedAt": "2025-11-05T14:18:27Z",
    "Amount": 286.50,
    "FeeAmount": 0.00,
    "CustomData": "invoice-2025-1105",
    "PrimaryAccountNumber": "+212711111111",
    "Method": null
  }
}

bank-transfer.initiated — Bank transfer sent

json
{
  "data": {
    "WebhookId": 12353,
    "EventId": "bank-transfer.initiated",
    "CRequestId": "9c2e5a7b-4d8f-4b1c-a6e3-0f7d2b5c8a94",
    "OperationId": 918274,
    "OperationType": 9,
    "OperationStatus": 1,
    "CreatedAt": "2025-11-05T10:05:00Z",
    "ExecutedAt": "2025-11-05T10:05:12Z",
    "Amount": 12000.00,
    "FeeAmount": 200.00,
    "CustomData": "supplier-invoice-1188",
    "PrimaryAccountNumber": "+212711111111",
    "SecondaryAccountNumber": "+212722222222",
    "Method": null,
    "Reference": "BANK-REF-7Q4TZ9",
    "BankTransferBeneficiaryName": "Hicham Bouzid"
  }
}

bank-transfer.completed — Bank transfer finalized

json
{
  "data": {
    "WebhookId": 12345,
    "EventId": "bank-transfer.completed",
    "CRequestId": "a4d1e0b5-9f6a-4c1d-bc7b-2d0a7f4b9b12",
    "OperationId": 924381,
    "OperationType": 9,
    "OperationStatus": 2,
    "CreatedAt": "2025-11-05T10:12:00Z",
    "ExecutedAt": "2025-11-05T10:12:22Z",
    "Amount": 25000.00,
    "FeeAmount": 350.00,
    "CustomData": "{\"note\":\"Salary for October\"}",
    "PrimaryAccountNumber": "+212711111111",
    "SecondaryAccountNumber": "+212722222222",
    "Method": null,
    "Reference": "BANK-REF-9FJ2X7",
    "BankTransferBeneficiaryName": "Aminata Diop"
  }
}

bank-transfer.received — Bank transfer received

json
{
  "data": {
    "WebhookId": 12354,
    "EventId": "bank-transfer.received",
    "CRequestId": "1d6f3b8a-5c9e-4a7d-b2f4-8e0a3c6d9b15",
    "OperationId": 926504,
    "OperationType": 9,
    "OperationStatus": 2,
    "CreatedAt": "2025-11-05T12:20:00Z",
    "ExecutedAt": "2025-11-05T12:20:31Z",
    "Amount": 8000.00,
    "FeeAmount": 0.00,
    "PrimaryAccountNumber": "+212722222222",
    "Method": null,
    "Reference": "BANK-REF-5N1WD4",
    "BankTransferBeneficiaryName": "Yassine El Amrani"
  }
}

transfer.received — Transfer received

json
{
  "data": {
    "WebhookId": 12355,
    "EventId": "transfer.received",
    "CRequestId": "2b7d0f4c-9a3e-4d5b-8c1f-6e9b2d4a7c38",
    "OperationId": 934187,
    "OperationType": 3,
    "OperationStatus": 2,
    "CreatedAt": "2025-11-05T13:10:00Z",
    "ExecutedAt": "2025-11-05T13:10:06Z",
    "Amount": 500.00,
    "FeeAmount": 0.00,
    "CustomData": "p2p-note-201",
    "PrimaryAccountNumber": "+212711111111",
    "SecondaryAccountNumber": "+212722222222",
    "Method": null
  }
}

cashin.network.executed — CashIn by reference executed

json
{
  "data": {
    "WebhookId": 12356,
    "EventId": "cashin.network.executed",
    "CRequestId": "4e9b2d6f-0c5a-4e8b-a3d7-1f6c8b0e5a29",
    "OperationId": 947261,
    "OperationType": 1,
    "OperationStatus": 2,
    "CreatedAt": "2025-11-05T15:40:00Z",
    "ExecutedAt": "2025-11-05T15:41:12Z",
    "Amount": 250.00,
    "FeeAmount": 0.00,
    "CustomData": "cashin-req-778",
    "PrimaryAccountNumber": "+212711111111",
    "Method": "Network",
    "NetworkName": "AGENCY",
    "Reference": "1122334455"
  }
}

cashout.network.executed — CashOut by reference executed

json
{
  "data": {
    "WebhookId": 12357,
    "EventId": "cashout.network.executed",
    "CRequestId": "8f0d4b7e-2a6c-4c9f-b1e5-3d8a0f2c6b47",
    "OperationId": 948730,
    "OperationType": 2,
    "OperationStatus": 2,
    "CreatedAt": "2025-11-05T16:22:00Z",
    "ExecutedAt": "2025-11-05T16:23:05Z",
    "Amount": 200.00,
    "FeeAmount": 5.00,
    "CustomData": "cashout-req-902",
    "PrimaryAccountNumber": "+212711111111",
    "Method": "Network",
    "NetworkName": "AGENCY",
    "Reference": "5566778899"
  }
}
R

Response Format

All API responses are wrapped in a `data` object. The C-Request-Id header you send is echoed back in the response.

C-Request-Id Header

Our API supports the C-Request-Id header to allow networks to track requests efficiently. You can include a unique C-Request-Id in the request headers, which will be echoed back in the response.

T

Telco Top-up

The Telco API provides a unified, secure interface for prepaid mobile top-up services. It exposes two services: retrieve the catalog of available recharge products, and trigger a top-up for a given phone number and selected offer, with real-time validation. Supported operators in Morocco: Maroc Telecom (IAM), Orange and Inwi.

POST{host}/api/services/telco/catalog/b2b

Retrieve Catalog

Get the list of available recharge products and offers for a given phone number and operator.

ParameterTypeInRequiredDescription
RecipientPhoneNumberstringbodyRequiredThe customer's phone number, in the required format: +212*********.
AmountintbodyRequiredThe monetary value to be transacted. Should be a positive numeric value.
OperatorintbodyRequiredOperator: 1 = Maroc Telecom, 2 = Orange, 3 = Inwi.

Notes

  • The data array contains the list of products available for the requested operator.
  • Use productCode in the recharge endpoint to select the offer.
POST{host}/api/operations/service/telco/recharge/b2b

Request Top-up

Initiate a mobile top-up for a given phone number and selected offer, with real-time validation and transaction tracking.

ParameterTypeInRequiredDescription
RecipientPhoneNumberstringbodyRequiredThe customer's phone number, in the required format: +212*********.
AmountintbodyRequiredThe monetary value to be transacted. Should be a positive numeric value.
OperatorintbodyRequiredOperator: 1 = Maroc Telecom, 2 = Orange, 3 = Inwi.
ProductCodeintbodyRequiredThe available product code, given by the catalog endpoint.
CodestringbodyRequiredThe principal agent code — the account that will be debited. Provided by Chari after activation of your Partner Account.
RechargeTypeintbodyRequiredRecharge type: 0 = Classic, 1 = Product.

Notes

  • All three operators are supported: 1 = Maroc Telecom, 2 = Orange, 3 = Inwi.
  • Code is the principal agent code (the debited account), provided by Chari after partner account activation.
  • operationType: value 10 (see the "Types & References" table).
POST{host}/api/operations/service/telco/recharge/preview

Customer Recharge — Preview

Check the feasibility of a phone recharge paid from the customer's wallet (amount, fees) before execution.

ParameterTypeInRequiredDescription
customerPhoneNumberstringbodyRequiredPhone number of the customer whose wallet will be debited. Format: +212*********
recipientPhoneNumberstringbodyRequiredPhone number to top up. Format: +212*********
amountdecimalbodyRequiredTop-up amount.
operatorintbodyRequiredOperator: 1 = Maroc Telecom, 2 = Orange, 3 = Inwi.
rechargeTypeintbodyRequiredRecharge type: 0 = Classic, 1 = Product (swagger enum: 0 to 3).
productCodeintbodyOptionalProduct code from the catalog endpoint (used for a Product-type recharge).
rechargeStatusintbodyOptionalRecharge status (swagger enum: 0 to 4). Field of the DTO shared with responses.
beneficiaryIdintbodyOptionalReference to an existing beneficiary (optional).

Notes

  • Customer variant: the customer's wallet (customerPhoneNumber) is debited — unlike /api/operations/service/telco/recharge/b2b which debits the principal agent account.
  • operator: 1 = Maroc Telecom, 2 = Orange, 3 = Inwi.
  • rechargeType: 0 = Classic, 1 = Product; for a Product recharge, use the productCode returned by the catalog.
POST{host}/api/operations/service/telco/recharge

Customer Recharge — Execute

Execute a phone recharge paid from the customer's wallet, for the selected number and offer.

ParameterTypeInRequiredDescription
customerPhoneNumberstringbodyRequiredPhone number of the customer whose wallet will be debited. Format: +212*********
recipientPhoneNumberstringbodyRequiredPhone number to top up. Format: +212*********
amountdecimalbodyRequiredTop-up amount.
operatorintbodyRequiredOperator: 1 = Maroc Telecom, 2 = Orange, 3 = Inwi.
rechargeTypeintbodyRequiredRecharge type: 0 = Classic, 1 = Product (swagger enum: 0 to 3).
productCodeintbodyOptionalProduct code from the catalog endpoint (used for a Product-type recharge).
rechargeStatusintbodyOptionalRecharge status (swagger enum: 0 to 4). Field of the DTO shared with responses.
beneficiaryIdintbodyOptionalReference to an existing beneficiary (optional).

Notes

  • Call /api/operations/service/telco/recharge/preview first to check the amount and fees.
  • Customer variant: the customer's wallet is debited — the /b2b variant debits the principal agent account.
GET{host}/api/operations/service/telco/recharge

Customer Recharge History

Retrieve the list of a customer's phone recharge operations, with pagination and status filter.

ParameterTypeInRequiredDescription
phoneNumberstringqueryRequiredThe customer's phone number. Format: +212*********
pageSizeintqueryOptionalNumber of items per page.
pageNumberintqueryOptionalPage number to retrieve.
statuslist intqueryOptionalRecharge status(es) to filter on (swagger enum: 0 to 4). Repeatable parameter.

Notes

  • The response is a list of recharge operations (no pagination envelope: use pageSize/pageNumber to page through).
  • status is repeatable to filter on multiple statuses, e.g., status=2&status=3.
POST{host}/api/services/telco/catalog

Telco Catalog (generic variant)

Generic variant of the catalog endpoint: takes a phone number, an amount and an operator, and returns a list of strings.

ParameterTypeInRequiredDescription
phoneNumberstringbodyOptionalPhone number concerned. Format: +212*********
amountintbodyRequiredAmount of the intended top-up.
operatorintbodyRequiredOperator: 1 = Maroc Telecom, 2 = Orange, 3 = Inwi.

Notes

  • The swagger provides no summary for this endpoint; this sheet sticks strictly to the declared schemas.
  • The 200 response is declared as a plain array of strings, with no further documented structure.
  • For a structured catalog (productCode, labels, availability), use /api/services/telco/catalog/b2b.
GET{host}/api/services/telco/export

Telco Data Export

Trigger the export of telco data over a given period. Returns a boolean indicating whether the request succeeded.

ParameterTypeInRequiredDescription
fromdatetimequeryRequiredStart date/time of the period to export (ISO 8601).
todatetimequeryRequiredEnd date/time of the period to export (ISO 8601).

Notes

  • Both from and to parameters are required.
  • The 200 response is a boolean: true if the export request was accepted.
V

Vouchers

The Voucher API provides a standardized, secure interface to issue, manage and redeem digital vouchers within the BaaS ecosystem: value distribution and prepaid services (gift cards, game top-ups, etc.). The purchase flow follows a preview/confirm model.

GET{host}/api/vouchers/articles

Retrieve Catalog (articles)

Retrieve the current catalog: the list of voucher articles for a given brand.

ParameterTypeInRequiredDescription
phoneNumberstringqueryRequiredThe customer's phone number, in the format +212*********.
brandIdintqueryRequiredBrand identifier. Should be a positive numeric value.
pageintqueryOptionalWhich page of results to retrieve. Starts at 1. Default: 1.
takeintqueryOptionalHow many results are returned per page. Default: 10.
GET{host}/api/vouchers/brands

Retrieve Brands

Retrieve the current list of available voucher brands.

ParameterTypeInRequiredDescription
phoneNumberstringqueryRequiredThe customer's phone number, in the format +212*********.
pageintqueryOptionalWhich page of results to retrieve. Starts at 1. Default: 1.
takeintqueryOptionalHow many results are returned per page. Default: 10.

Notes

  • No brandId filter on this endpoint: for a specific brand, use GET /api/vouchers/brands/{id}.
GET{host}/api/vouchers/brands/{id}

Get Brand by Id

Get a specific brand by its Id.

ParameterTypeInRequiredDescription
idintpathRequiredBrand Id.
phoneNumberstringqueryRequiredThe customer's phone number, in the format +212*********.
GET{host}/api/vouchers/{id}/articles

Get Vouchers by Brand Id

Get the list of vouchers associated with a brand, by brand Id.

ParameterTypeInRequiredDescription
idintpathRequiredBrand Id.
phoneNumberstringqueryRequiredThe customer's phone number, in the format +212*********.

Notes

  • The response mirrors a Brand object, as defined in the source documentation.
POST{host}/api/operations/voucher/preview

Purchase Voucher — Preview

Check the feasibility of the voucher purchase operation (amount, fees) before confirmation.

ParameterTypeInRequiredDescription
CustomerPhoneNumberstringbodyRequiredThe customer phone number, in the format +212*********.
DestinationPhoneNumberstringbodyRequiredThe recipient's phone number, in the format +212*********.
BeneficiaryNamestringbodyRequiredA free-text field describing the beneficiary name.
ProviderSkuIdstringbodyRequiredThe article identifier.
ProviderIdstringbodyRequiredThe Id of the provider that supplies the voucher.

Notes

  • type: value 23 (see the "Types & References" table).
  • feesAmount is the fees; totalAmount is the total amount incl. tax.
POST{host}/api/operations/voucher/confirm

Purchase Voucher — Confirm

Execute the voucher purchase operation. Returns the voucher code and its details.

ParameterTypeInRequiredDescription
customerPhoneNumberstringbodyRequiredThe customer phone number, in the format +212*********.
destinationPhoneNumberstringbodyRequiredThe recipient's phone number, in the format +212*********.
beneficiaryNamestringbodyRequiredA free-text field describing the beneficiary name.
providerSkuIdstringbodyRequiredThe article identifier.
providerIdstringbodyRequiredThe Id of the provider that supplies the voucher.

Notes

  • type / operation.operationType: value 23 (see the "Types & References" table).
  • operation.code holds the voucher code to share with the beneficiary.
  • cashBack: optional cashback amount.
POST{host}/api/operations/service/voucher/preview

Voucher Service — Preview

Check the feasibility of purchasing a local voucher identified by its SKU, before execution. Returns the completed voucher object (amount included).

ParameterTypeInRequiredDescription
customerPhoneNumberstringbodyRequiredThe customer phone number, in the format +212*********.
skuIdintbodyRequiredSKU identifier of the local voucher (see the local vouchers list).
providerSkuIdstringbodyOptionalProvider-side SKU identifier (if any).
destinationPhoneNumberstringbodyOptionalThe recipient's phone number, in the format +212*********.
beneficiaryNamestringbodyOptionalA free-text field describing the beneficiary name.
amountdecimalbodyOptionalVoucher amount (filled in by the server in the response).
providerIdintbodyOptionalThe Id of the provider that supplies the voucher.

Notes

  • Required scope: operations:voucher (as stated in the swagger).
  • The response returns the same voucher object as the request, completed (notably amount).
  • Not to be confused with /api/operations/voucher/preview (the "Purchase Voucher — Preview" sheet) which uses a different body and returns an operation preview envelope.
POST{host}/api/operations/service/voucher

Voucher Service — Purchase

Execute the purchase of a local voucher identified by its SKU. The customer's wallet is debited and the operation information is returned.

ParameterTypeInRequiredDescription
customerPhoneNumberstringbodyRequiredThe customer phone number, in the format +212*********.
skuIdintbodyRequiredSKU identifier of the local voucher (see the local vouchers list).
providerSkuIdstringbodyOptionalProvider-side SKU identifier (if any).
destinationPhoneNumberstringbodyOptionalThe recipient's phone number, in the format +212*********.
beneficiaryNamestringbodyOptionalA free-text field describing the beneficiary name.
amountdecimalbodyOptionalVoucher amount (if applicable).
providerIdintbodyOptionalThe Id of the provider that supplies the voucher.

Notes

  • Required scope: operation:voucher (as stated in the swagger).
  • Call /api/operations/service/voucher/preview first to validate the voucher and its amount.
GET{host}/api/vouchers

List Local Vouchers

Fetch the list of local vouchers available for a customer, with pagination and brand/keyword filters.

ParameterTypeInRequiredDescription
phoneNumberstringqueryRequiredThe customer's phone number, in the format +212*********.
pageintqueryOptionalPage number to retrieve.
takeintqueryOptionalNumber of items per page.
brandIdintqueryOptionalFilter by brand Id (see the brands endpoint).
keywordstringqueryOptionalKeyword search across vouchers.

Notes

  • The swagger does not document the 200 response schema for this endpoint (only 400/500 errors are described).
  • The skuId of returned vouchers is used by the preview and purchase endpoints (/api/operations/service/voucher).
GET{host}/api/vouchers/product

Click & Collect Products

Fetch the paginated list of available "click & collect" products.

ParameterTypeInRequiredDescription
pageintqueryOptionalPage number to retrieve.
takeintqueryOptionalNumber of items per page.

Notes

  • The swagger does not document the 200 response schema for this endpoint (only 400/500 errors are described).
  • Use a product's configId with the detail endpoint /api/vouchers/products/{configId}.
GET{host}/api/vouchers/products/{configId}

Get Product Details

Fetch detailed product information from its configuration identifier.

ParameterTypeInRequiredDescription
configIdstringpathRequiredProduct configuration identifier (returned by the products list).

Notes

  • The swagger does not document the 200 response schema for this endpoint (only 400/500 errors are described).
  • The configId comes from the "click & collect" products list (/api/vouchers/product).
B

Bill Payment

The Bill Payment module lets end users settle bills with creditors connected to the Fatourati network in Morocco (RADEEMA, LYDEC, IAM, TGR, AMENDIS, REDAL, and other Fatourati billers). The flow follows 5 steps: list creditors, list a creditor's receivables, fetch the dynamic identification form, retrieve unpaid items, then confirm payment. Single-creditor model (no multi-biller cart); partial payment supported. Sandbox base: https://sandbox.charimoney.com.

GET{host}/api/bills/creanciers

List Creditors

Returns the list of active creditors accessible to the partner via ChariBaaS (filtered by the partner's contract and Fatourati configuration). Since the response is relatively stable, caching for several hours on the partner side is acceptable.

No parameters required.

Notes

  • codeRetour: 000 = ACCEPTE (success), 908 = Fatourati technical error.
  • The response is relatively stable: caching for a few hours on the partner side is acceptable.
GET{host}/api/bills/creances?creancierId={creancierId}

List a Creditor's Receivables

Returns the list of active receivables exposed by a given creditor (a receivable corresponds to a service type: bill, top-up, tax…). A single creditor may expose several receivables.

ParameterTypeInRequiredDescription
creancierIdstringqueryRequiredCreditor identifier obtained via GET /creanciers (4 digits).

Notes

  • codeRetour: 000 = ACCEPTE, 104 = creditor non-existent or inactive, 908 = technical error.
GET{host}/api/bills/form?creancierId={creancierId}&creanceId={creanceId}

Get Identification Form

Returns the schema of the dynamic customer-identification form for the (creditor, receivable) pair: fields to display (label, type, format, size, constraints). The partner MUST build their input screen from this response (no hardcoded form) to stay compatible with new creditors added to the Fatourati network.

ParameterTypeInRequiredDescription
creancierIdstringqueryRequiredCreditor identifier (4 digits).
creanceIdstringqueryRequiredReceivable identifier, always 2 positions (e.g., 01).

Notes

  • typeChamp: text, select, password, libelle. A libelle field is static text (not editable) and must NEVER be sent in creancierVals.
  • formatChamp: 1 = string, 2 = integer, 3 = real. contrainte: 0 = optional, 1 = required.
  • refTxFatourati: 1 = call /impayes (default value), 2 = sendRecharge (potentially obsolete).
  • Return codes: 000 = ACCEPTE (success), 103 = receivable/service inactive for the chosen creditor, 104 = creditor non-existent, 908 = Fatourati technical error.
POST{host}/api/bills/impayes?phoneNumber={phoneNumber}&creancierId={creancierId}&creanceId={creanceId}

Retrieve Unpaid Items

Submits the customer identification (entered via /form) and retrieves the customer's unpaid items with the creditor. This call opens the transaction (EN_ATTENTE state) and returns a refTxFatourati to use for /confirm. The association is valid for 7 calendar days (Fatourati timeout).

ParameterTypeInRequiredDescription
phoneNumberstringqueryRequiredEnd user's Chari Money phone number, international format (e.g., +212670770743).
creancierIdstringqueryRequiredCreditor identifier (4 digits).
creanceIdstringqueryRequiredReceivable identifier (2 positions).
creancierValsarraybodyRequiredArray of user-entered values: { nomChamp, valChamp } objects (excluding typeChamp=libelle fields). Note: the property is named valChamp (not valeurChamp) in this body.
aliasstringbodyOptionalAlias to save if the bill is added to favorites.
addToFavoritesbooleanbodyOptionaltrue to add the bill to the customer's favorites.
qrCodeContentstringbodyOptionalContent of a scanned QR code, as an alternative to entering the identification fields.

Notes

  • The transaction moves to EN_ATTENTE; keep refTxFatourati for /confirm. Valid for 7 calendar days.
  • creancierVals: the value property is named valChamp in this body (not valeurChamp as in the /form and /impayes responses); do not send typeChamp=libelle fields.
  • codeDevise: 504 = MAD.
  • typeFrais: forfait, commission, forfait_facture. valeurFrais = percentage × 100 (e.g., 1% → 100).
  • typeArticle: 0 = receivable, 1 = fee, 2 = mandatory, 3 = stamp fee.
  • globalParams: technical parameters with empty libelle (contrPaiement, isConfTO, isAnnul, rejoue, colAffiche) must never be shown to the customer.
  • Key return codes: 000 = success (EN_ATTENTE), 103 = receivable inactive, 104 = creditor non-existent, 107 = no bill to pay, 109 = required field missing, 902/908/909/910/911 = technical/connection errors.
  • Offline mode: a payment can also be initiated via a static 13-digit Fatourati reference (4 creditor + 2 receivable + 6 bill + 1 checksum), passed in creancierVals.
POST{host}/api/bills/confirm?phoneNumber={phoneNumber}

Confirm Payment

Confirms payment of the article selection made by the end user. A 000 return code indicates effective settlement on the creditor's side. The end user is identified by their Chari Money phone number (phoneNumber query parameter).

ParameterTypeInRequiredDescription
phoneNumberstringqueryRequiredEnd user's Chari Money phone number, international format (e.g., +212670770743). Must match an existing Chari Money user, otherwise the transaction is rejected before any call to Fatourati.
creancierIdstringbodyRequiredCreditor identifier (same values as /impayes).
creanceIdstringbodyRequiredReceivable identifier.
refTxFatouratistringbodyRequiredReference returned by /impayes. Links the call to the open transaction.
totalPaymentbooleanbodyOptionaltrue to settle all unpaid items, false for a partial selection.
listeArticleSelectionnesarraybodyRequiredSubset of impayesParams selected by the user: { idArticle, prixTTC, typeArticle, dateFacture, description } objects.
creancierValsarraybodyRequiredEntered identification fields: { nomChamp, valChamp } objects. Note: the property is named valChamp (not valeurChamp) in this body, and libelle is not accepted here.
globalParamsarraybodyOptionalGlobal parameters returned by /impayes: { libelle, nomChamp, valeurChamp } objects.

Notes

  • Body identical to /preview: creancierVals uses { nomChamp, valChamp } (no libelle), and listeArticleSelectionnes items only accept { idArticle, prixTTC, typeArticle, dateFacture, description } (no extraArticleParams).
  • codeRetour 000 = CONFIRME (effective settlement). 301 = already processed (treat as success, show the receipt).
  • Asynchronous behavior (digital channel): codes 908/909/910 are NOT definitive failures — the transaction stays in AUTORISE state and its final resolution (CONFIRME/ANNULE) is notified by webhook.
  • refReglement must appear on the receipt. numCRC / texteCRC (params): display on the receipt if present.
  • Module webhooks: payment.confirmed, payment.cancelled, payment.refunded, payment.failed — emitted to notify the final resolution (CONFIRME / ANNULE / REMBOURSE / FAILED states).
POST{host}/api/bills/preview?phoneNumber={phoneNumber}

Preview Payment

Previews the settlement of the article selection before confirmation. The body is identical to /confirm: the call validates the selection (creditor, receivable, articles) for the user identified by phoneNumber, without executing the payment.

ParameterTypeInRequiredDescription
phoneNumberstringqueryRequiredEnd user's Chari Money phone number, international format (+212*********).
creancierIdstringbodyRequiredCreditor identifier (4 digits, same values as /impayes).
creanceIdstringbodyRequiredReceivable identifier (2 positions).
refTxFatouratistringbodyRequiredReference returned by /impayes (12 digits). Links the call to the open transaction.
totalPaymentbooleanbodyOptionaltrue to settle all unpaid items, false for a partial selection.
listeArticleSelectionnesarraybodyRequiredArticles selected by the user: { idArticle, prixTTC, typeArticle, dateFacture, description } objects taken from impayesParams.
creancierValsarraybodyRequiredEntered identification fields: { nomChamp, valChamp } objects. Note: the property is named valChamp (not valeurChamp) in this body.
globalParamsarraybodyOptionalGlobal parameters returned by /impayes: { libelle, nomChamp, valeurChamp } objects.

Notes

  • Body identical to /confirm: build it from the /form and /impayes responses, then replay it as-is on /confirm after user validation.
  • creancierVals: the value property is named valChamp in this body (not valeurChamp as in the /form and /impayes responses).
  • totalPayment: true = settle all unpaid items, false = partial selection (partial payment is supported by the module).
  • The production swagger does not publish a detailed response schema for this endpoint (200 Success); the example above is indicative.
GET{host}/api/bills/history?phoneNumber={phoneNumber}&pageNumber={pageNumber}&pageSize={pageSize}

Customer Bill History

Returns the payable bills and bill-payment history of the customer identified by their Chari Money phone number. Results are paginated via pageNumber and pageSize.

ParameterTypeInRequiredDescription
phoneNumberstringqueryRequiredCustomer's Chari Money phone number, international format (+212*********).
pageNumberintqueryOptionalPage number to return.
pageSizeintqueryOptionalNumber of items per page.

Notes

  • Pagination: pageNumber and pageSize are optional; when omitted, the server's default pagination applies.
  • The production swagger does not publish the detailed response schema (200 Success); the example above is indicative and reuses the module vocabulary (refTxFatourati, montantTotalTTC, CONFIRME/ANNULE states…).
GET{host}/api/bills/reference/status?reference={reference}

Cash-In Status by Reference

Returns the status of a Fatourati cash-in from its reference: execution flag, status, amount, timestamps, and the associated Chari operation identifier.

ParameterTypeInRequiredDescription
referencestringqueryOptionalFatourati reference of the cash-in to query.

Notes

  • The response is returned at the root, without a { "data": … } envelope.
  • 204 No Content: no transaction matches the provided reference.
  • 400 / 401: ProblemDetails-formatted response (Bad Request / Unauthorized).
GET{host}/api/bills/bill-receipt/{operationId}?phoneNumber={phoneNumber}

Download Payment Receipt

Downloads the receipt of a bill payment from the Chari operation identifier. The customer is identified by their Chari Money phone number.

ParameterTypeInRequiredDescription
operationIdintpathRequiredChari operation identifier of the bill payment (see chariOperationId from /reference/status or the history).
phoneNumberstringqueryRequiredCustomer's Chari Money phone number, international format (+212*********). Must match the customer who performed the operation.

Notes

  • The 200 response contains the payment-receipt file (binary content to download), not a JSON body.
  • The receipt must mention the settlement reference (refReglement) returned by /confirm.
GET{host}/api/bills/favorite?phoneNumber={phoneNumber}

List Favorites

Returns the customer's favorite bills, grouped by creditor category. Favorites let the user quickly re-initiate payment of a recurring bill without re-entering the identification.

ParameterTypeInRequiredDescription
phoneNumberstringqueryRequiredCustomer's Chari Money phone number, international format (+212*********).

Notes

  • Favorites are grouped by creditor category.
  • favoriteId is the identifier to use with PUT and DELETE /api/bills/favorite/{favoriteId}.
  • The production swagger does not publish the detailed response schema (200 Success); the example above is indicative.
PUT{host}/api/bills/favorite/{favoriteId}?phoneNumber={phoneNumber}

Update a Favorite

Updates the alias of one of the customer's favorite bills. The alias is the label displayed to the user (e.g., "Maison Marrakech").

ParameterTypeInRequiredDescription
favoriteIdintpathRequiredFavorite identifier (obtained via GET /api/bills/favorite).
phoneNumberstringqueryRequiredChari Money phone number of the customer who owns the favorite, international format (+212*********).
aliasstringbodyRequiredNew alias for the favorite.

Notes

  • alias is the only field editable via this endpoint.
  • A 200 response confirms the update; the production swagger does not publish a response body.
DELETE{host}/api/bills/favorite/{favoriteId}?phoneNumber={phoneNumber}

Delete a Favorite

Deletes one of the customer's favorite bills. Deleting a favorite does not affect payments already made.

ParameterTypeInRequiredDescription
favoriteIdintpathRequiredIdentifier of the favorite to delete (obtained via GET /api/bills/favorite).
phoneNumberstringqueryRequiredChari Money phone number of the customer who owns the favorite, international format (+212*********).

Notes

  • A 200 response confirms the deletion; the production swagger does not publish a response body.
T

Types & References

Operation Types

IDCode
1CASHIN
2CASHOUT
3TRANSFER
5MOBILE_PAYMENT
7PAYMENT_REFUND
9BANK_TRANSFER
10RECHARGE
12CHARGEBACK
23VOUCHER
24CARD_PAYMENT
25BILL_PAYMENT

Transaction Types

IDCode
1CASHIN
2CASHOUT
3TRANSFER
5MOBILE_PAYMENT
6TRANSACTION_FEES
7PAYMENT_REFUND
9CHARGEBACK
10CHARGEBACK_CANCELLATION
16BANK_TRANSFER
17RECHARGE
18CASHBACK
24CARD_PAYMENT
25BILL_PAYMENT

Operation Statuses

IDCodeDescription
1OPENOpen (lifecycle in progress)
2COMPLETEDCompleted successfully
3FAILEDFailed
4CANCELEDCanceled

Transaction Statuses

IDCodeDescription
1OPENOpen (in progress)
2COMPLETEDCompleted
3FAILEDFailed
4CANCELEDCanceled

Transaction Direction (Sens)

IDCodeDescription
1CREDITCredit (incoming funds)
2DEBITDebit (outgoing funds)

Customer Statuses

IDCodeDescription
0NOT_EXISTSNumber does not exist at ChariMoney
1NOT_CONFIRMEDExists but not confirmed (OTP not entered)
2CONFIRMEDConfirmed and registered with Switch
3ACTIVERegistered, active, and PIN created
4LOCKED_TEMPORARYTemporarily locked (excessive attempts)
5LOCKEDLocked

Account Levels

IDCodeDescription
1LEVEL_1Level 1 — Name + valid phone + CIN number. Limit: 1,000 MAD.
2LEVEL_2Level 2 — Full KYC (CIN + selfie or document scan). Limit: 4,000 MAD.
3LEVEL_3Level 3 — Verified ID + interview + digital customer record. Limit: 20,000 MAD.
4LEVEL_4Level 4 — Full KYC + interview + proof of income + proof of address. Limit: 100,000 MAD.
5MERCHANTMerchant — Full KYB + IF/RC business registration. Limit: negotiated.

Document Types

IDCodeDescription
1IdentityCardNational identity card
2DrivingLicenseDriving license
3PassportPassport
4ResidencePermitResidence permit
5ProofOfIncomeProof of income
6ProofOfResidenceProof of residence
7SelfieSelfie / Face photo
8CommercialRegisterCommercial register

API scopes

Scopes declared by the production API specification. Endpoints not listed here have no scope declared in the specification; your API key still delimits overall access.

ScopeEndpoints
cards:read
GET /api/cards
operation:voucher
POST /api/operations/service/voucherPOST /api/operations/voucher/confirm
operations:cashin
POST /api/operations/cashin/cardPOST /api/operations/cashin/card/agentPOST /api/operations/cashin/card/agent/previewPOST /api/operations/cashin/card/previewPOST /api/operations/cashin/card/{cardId}GET /api/operations/cashin/requestGET /api/operations/cashout/requestPOST /api/operations/cashin/agentPOST /api/operations/cashin/requestPOST /api/operations/fatourati/cashin/request
operations:cashout
GET /api/operations/cashin/requestGET /api/operations/cashout/requestPOST /api/operations/cashout/agentPOST /api/operations/cashout/request
operations:merchant-payment
POST /api/operations/merchant/payment/cardPOST /api/operations/merchant/payment/card/capturePOST /api/operations/merchant/payment/card/previewPOST /api/operations/merchant/payment/card/reversePOST /api/operations/merchant/payment/push/manual/previewPOST /api/operations/merchant/payment/push/qrcodePOST /api/operations/merchant/payment/push/qrcode/previewPOST /api/operations/merchant/payment/tokenized/card/{cardId}
operations:read
GET /api/operationsGET /api/operations/allGET /api/operations/{operationId}
operations:refund
POST /api/operations/merchant/payment/card/refundPOST /api/operations/refundPOST /api/operations/refund/preview
operations:transfer
POST /api/operations/transferPOST /api/operations/transfer/preview
operations:voucher
POST /api/operations/service/voucher/previewPOST /api/operations/voucher/preview
E

Error Codes

HTTP Status Codes

401 UnauthorizedAuthentication credentials (API KEY) not authorized.
422 UnprocessableThe server is unable to process the request.
423 LockedThe access is locked for the given customer.
400 Bad RequestCase-specific error with Chari error code.

Error Response Format

json
{
  "errorCode": 20005,
  "errorDescription": "The specified user could not be found."
}

Chari Error Codes

10xxxGeneral

CodeMessageRelated Endpoints
10001Missing Parameters.

20xxxCustomer

CodeMessageRelated Endpoints
20000The phone number format is invalid.
20005The specified user could not be found.
20006The initial parameters provided are incorrect or invalid.
20007The Merchant Category Code (MCC) provided is incorrect or not recognized.
20008Registration is temporarily locked due to security or policy restrictions.
20009The request is pending confirmation. Please wait for further processing.
20017There is no pending request associated with the provided Phone Number.

26xxxPIN / Authentication

CodeMessageRelated Endpoints
26001The entered PIN is incorrect.
26004A PIN has already been set for this wallet.
26005The provided PIN does not meet the required format (must be a 4-digit number).

27xxxBeneficiary

CodeMessageRelated Endpoints
27000The Beneficiary already exists with the same phoneNumber.
27001The Beneficiary does not exist.

32xxxKYC / Upgrade

CodeMessageRelated Endpoints
32000An upgrade request is already under review for this account.
I

Infrastructure & Security

Environments

Sandbox

https://sandbox.charimoney.com

Development and testing. Transactions are simulated.

Production

Communiqué sur demande

Live transactions. Requires prior approval.

API Key Management

You will be assigned a dedicated API key for each environment (sandbox and production). Keys must be included in the Chari-Api-Key header of every request.

IP & Domain Whitelisting

You must share the IP addresses and/or domains that will be used to consume our API. Only whitelisted IPs/domains will be allowed to access the API. If your infrastructure changes, update your IP/domain list with the support team.

How to submit IPs / domains

  1. 1Provide a list of public IP addresses or domains that will be used to access the API.
  2. 2Send this information to the support team before attempting API integration.
  3. 3Any changes must be communicated at least 72 hours in advance so we can update our security rules.

Security & Compliance

  • API authentication is handled using API Keys.
  • Requests from non-whitelisted IPs/domains will be rejected.
  • If an API key is compromised, it must be rotated immediately.
  • Rate limiting may apply to prevent abuse.
  • The production environment requires prior approval and testing in sandbox.

Next Steps for Integration

  1. 1
    Request API keys

    Contact support to receive your dedicated sandbox and production keys.

  2. 2
    Submit IPs/domains

    Provide the list of public IPs or domains for whitelisting.

  3. 3
    Test in sandbox

    Run all your integration tests in the sandbox environment.

  4. 4
    Go to production

    Once approved, switch to production with your live API key.

You will receive a form to fill out with the necessary elements.

Get sandbox access

Fill in this form to start your technical onboarding: sandbox API key, IP whitelisting, module activation and Partner Back Office invitation. The BaaS team gets back to you quickly.