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:
| Header | Type | Required | Description |
|---|---|---|---|
Chari-Api-Key | string | Required | API key for authentication. Provided by Chari for each environment (sandbox / production). |
C-Request-Id | string | Optional | Unique 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
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.
Interactive Reference (Swagger UI)
Browse the 114 operations and their schemas in Swagger UI, hosted on this site and generated from the production API.
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.
Postman Collection
Download the full Postman collection to test all API endpoints.
Changelog
2025-11-05
Initial documentation. Full API v1.8 coverage.
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.
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).
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.
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.
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.
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.
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
| Type | Owner | Description | Operations |
|---|---|---|---|
| Consumer (Particulier) | Individuals | Personal 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 provider | Business wallet linked to a merchant account or store. | Receive payments, transfer to bank, refund customer, other payment services. |
| Agent Retail | Authorized agent network/partner | Used by distribution agents to facilitate cash-in/out for users. | Load/unload customer wallets. |
| Agent Principal | Partner / EDP | Dedicated wallet for enterprises with higher limits and integration solutions. | Mass payouts, salary disbursements, collections, multiple other operations. |
Account Levels
| Level | KYC Requirement | Balance Limit |
|---|---|---|
| Level 1 | Name + valid phone + CIN number | 1,000 MAD |
| Level 2 | Full KYC (CIN + selfie or document scan) | 4,000 MAD |
| Level 3 | Verified ID (KYC), Interview, Digital customer record | 20,000 MAD |
| Level 4 | Full KYC, Interview, Digital customer record, Proof of income, Proof of address | 100,000 MAD |
| Merchant | Full KYB + Business registration (IF/RC) | Negotiated |
Glossary
| Term | Definition |
|---|---|
| M-Wallet | A regulated electronic money account linked to a mobile number, allowing users to perform financial transactions such as transfers, payments, and cash operations. |
| Wallet | A user account within the system that stores electronic money and is associated with a unique identifier (MSISDN). |
| MSISDN | Mobile 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 Level | Regulatory level assigned to a wallet based on verification status, defining transaction and balance limits. |
| Operation | A high-level business action initiated by a user or partner (e.g., cash-in, transfer, payment). |
| Transaction | A financial movement (debit, credit, fees, adjustment) generated as part of an operation. |
| Operation Type | Category of business action (e.g., CASHIN, TRANSFER, PAYMENT). |
| Transaction Type | Type of financial movement associated with an operation (e.g., debit, credit, fees). |
| Operation Status | Current lifecycle state of an operation (e.g., OPEN, COMPLETED, FAILED). |
| Transaction Status | Processing state of a transaction (e.g., COMPLETED, FAILED). |
| Reference | A unique identifier generated for a pending operation (e.g., cash-in/out), used to complete the transaction through an external network. |
| Agent / Network | Authorized third-party entity or distribution channel used to execute cash-in and cash-out operations. |
| API Key | Secure token used to authenticate partner requests to the BAAS API. |
| Webhook | Automated HTTP callback sent by the system to notify partners about operation or transaction updates. |
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
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
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:
bashcurl -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
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étier— Telco top-up: service not enabled for your account — request operator activation.200/204 vide— Empty voucher catalog: brands must be provisioned in sandbox by Chari.403— missing scopes — the endpoint requires a scope your key does not carry (e.g. operations:admin-read on GET /api/operations/all). - 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
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
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
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
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:
bashcurl -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" } }20005— The specified user could not be found. - 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.
bashcurl --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 }20000— The phone number format is invalid (expected: +212*********).20006— The initial parameters provided are incorrect or invalid.20008— Registration is temporarily locked due to security or policy restrictions.20009— The request is pending confirmation. Please wait for further processing. - 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.
bashcurl --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 }20000— The phone number format is invalid.20017— There is no pending request associated with the provided phone number — redo the Register step. - 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.
bashcurl -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 }26004— A PIN has already been set for this wallet — use Update PIN or Reset PIN.26005— The provided PIN does not meet the required format (must be a 4-digit number). - 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).
bashcurl -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 } }20005— The specified user could not be found — check the number and the status (step 1).26001— The entered PIN is incorrect — watch remainingAttempts to avoid lockout. - 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.
bashcurl -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 } }20005— The specified user could not be found. - 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.
bashcurl -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 } }20005— The 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
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:
bashcurl -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 } }401— Authentication credentials (API KEY) not authorized — check the Chari-Api-Key header.10001— Missing Parameters — a required parameter is missing (e.g. phoneNumber in the query or amount in the body). - 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:
bashcurl -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
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
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
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.
bashcurl -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
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:
bashcurl -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
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:
bashcurl -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
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.
bashcurl -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 } }401— API key not authorized — check the Chari-Api-Key header.10001— Missing Parameters — a required parameter is missing (e.g. amount in the body).20005— The specified user could not be found — check the merchant's phone number (+212********* format). - 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.
bashcurl -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
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
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.
bashcurl -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
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).
bashcurl -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
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.
bashcurl -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
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.
bashcurl -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
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.
bashcurl -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
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.
bashcurl -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 } }10001— Missing Parameters — a required body field (PhoneNumber, Amount) is missing.401— Authentication credentials (API KEY) not authorized — check the Chari-Api-Key header. - 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).
bashcurl -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
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.
bashcurl -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
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).
bashcurl -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
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.
bashcurl -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
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
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.
bashcurl -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
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.
bashcurl -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" } ] }401— Authentication credentials (API KEY) not authorized — check the Chari-Api-Key header. - 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.
bashcurl -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
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.
bashcurl -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
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.
bashcurl -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 } ] }10001— Missing Parameters — a required parameter is missing (phoneNumber, creancierId, creanceId or the creancierVals array). - 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.
bashcurl -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." } ] }20005— The 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
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.
bashcurl -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
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
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
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.
bashcurl -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
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).
bashcurl -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
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).
bashcurl -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
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.
bashcurl -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
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.
bashcurl -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
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 Unauthorized— Authentication credentials (API KEY) not authorized — check the Chari-Api-Key header and the environment (keys are per-environment).10001— Missing 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
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
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}.
bashcurl -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
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.
bashcurl -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
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.
bashcurl -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
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.
bashcurl -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
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.
bashcurl -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
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.
401— Authentication credentials (API KEY) not authorized — check the Chari-Api-Key header.10001— Missing Parameters — one of the five required body fields (customerPhoneNumber, destinationPhoneNumber, beneficiaryName, providerSkuId, providerId) is missing.422— The server is unable to process the request.
Customer Registration
Full customer lifecycle management: status check, registration, OTP confirmation, PIN management, balance and info retrieval, and unregistration.
{host}/api/customers/statusCheck Status with Chari
Retrieve the current registration status of a customer with Chari only.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
PhoneNumber | string | query | Required | The 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.
{host}/api/customers/defaultCheck Default Wallet (Switch)
Retrieve whether Chari is the default wallet for the customer.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
phoneNumber | string | query | Required | The 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.
{host}/api/customers/register202Register
Initiate a new customer registration process. An OTP will be sent via SMS.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
phoneNumber | string | body | Required | The customer's phone number. Format: +212********* |
firstName | string | body | Required | Minimum 2 letters (latin characters only) |
lastName | string | body | Required | Minimum 2 letters (latin characters only) |
cin | string | body | Required | Minimum 5 characters |
walletType | string | body | Required | "P": Particular (Particulier) / "C": Merchant (Commerçant) |
closeLoopOnly | boolean | body | Optional | If true, enroll the customer in CloseLoop mode only. In that case, the OTP is sent directly by CHARI. |
{host}/api/customers/confirm200Confirm
Confirm a registration using OTP as a verification method.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
phoneNumber | string | body | Required | The customer's phone number. Format: +212********* |
code | string | body | Required | The received OTP code with format: xxx-xxx |
autoActivate | boolean | body | Optional | Default 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.
{host}/api/customers/confirm/resend-otpResend OTP
Resend the One-Time Password for registration or confirmation.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
phoneNumber | string | query | Required | The customer's phone number. Format: +212********* |
{host}/api/customers/loginLogin with PIN
Authenticate an existing customer using their PIN.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
phoneNumber | string | body | Required | The customer's phone number. Format: +212********* |
pin | string | body | Required | PIN of the customer. |
Notes
- •logged : true if authentication succeeded, false otherwise.
- •remainingAttempts : number of remaining attempts before account lockout.
{host}/api/customers/pinCreate PIN
Set up a secure PIN for a registered customer.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
phoneNumber | string | body | Required | The customer's phone number. Format: +212********* |
pin | string | body | Required | PIN of the customer. (4 numbers required) |
{host}/api/customers/pinUpdate PIN
Change an existing PIN for security or user preference.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
phoneNumber | string | body | Required | The customer's phone number. Format: +212********* |
oldPin | string | body | Required | Existing PIN of the customer. |
newPin | string | body | Required | New PIN of the customer. |
{host}/api/customers/pin/resetReset PIN
Reset customer PIN after OTP validation.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
phoneNumber | string | body | Required | The customer's phone number. Format: +212********* |
otp | string | body | Required | OTP code received via SMS. |
pin | string | body | Required | New PIN of the customer (4 digits). |
{host}/api/customers/balanceGet Customer Balance
Retrieve the balance of a registered customer.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
phoneNumber | string | query | Required | The customer's phone number. Format: +212********* |
{host}/api/customers/infoGet Customer Info
Retrieve detailed profile data for a registered customer.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
phoneNumber | string | query | Required | The 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.
{host}/api/customers/unregisterUnregister
Deactivate or remove a customer from the platform.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
PhoneNumber | string | body | Required | The customer's phone number. Format: +212********* |
Reason | int | body | Required | Closure 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
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
- 1Your app calls /api/kyc/shareid/auth to obtain a short-lived KYC token.
- 2The app opens the ShareID SDK with that token.
- 3The user scans their ID and completes a guided selfie.
- 4ShareID runs the checks.
- 5Once the ShareID verification is complete, your app requests the account upgrade via PUT /api/customers/upgrade/request (see "Confirmation").
- 6A callback is sent to our API with status and documents.
{host}/api/kyc/shareid/authAuthentication
Obtain a short-lived KYC token to launch ShareID SDK.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
PhoneNumber | string | query | Required | The 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.
{host}/api/customers/upgrade/requestConfirmation
Signal the KYC flow has finished on-device and request account upgrade.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
PhoneNumber | string | query | Required | The customer's phone number. Format: +212********* |
AccountLevel | int | query | Required | The account level to upgrade to (2, 3, or 4). |
{host}/api/customers/merchant/kyc/requestMerchant KYC Upload
Upload merchant KYC documents to request an account upgrade (multipart/form-data).
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
phoneNumber | string | query | Optional | Merchant phone number. Format: +212********* |
kycDocuments | multipart form | form | Required | Array 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].docType | int | form | Required | Document type (see Document Types table). |
kycDocuments[n].docFront | file | form | Required | Front image of the document. Accepted formats: PNG, JPG/JPEG, PDF. |
kycDocuments[n].docBack | file | form | Optional | Back 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).
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
4918914107195005CVV
123Expiry
08/26 (or any future date)3DS Code
555{host}/api/operations/cashin/card/previewPreview (by Phone)
Check feasibility of depositing funds into a customer's wallet from a card.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
PhoneNumber | string | query | Required | The customer's phone number. Format: +212********* |
Amount | decimal | body | Required | Amount to deposit. Must be a positive number. |
{host}/api/operations/cashin/cardExecute (by Phone)
Add funds to a customer's wallet from a payment card. Triggers 3D Secure authentication.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
phoneNumber | string | query | Required | The customer's phone number. |
firstName | string | body | Required | Cardholder's first name. |
lastName | string | body | Required | Cardholder's last name. |
cvv | string | body | Required | 3-digit security code (CVV). |
amount | decimal | body | Required | Amount to deposit. |
pan | string | body | Required | Full card number (PAN). |
expiryDate | string | body | Required | Expiry date in YYMM format. |
keepAlive | bool | body | Required | true: save the card for future use / false: single use. |
cardName | string | body | Optional | Name chosen by the user for the saved card. |
3dSecure | bool | body | Optional | Enable 3D Secure. Default: true. |
autoCapture | bool | body | Optional | Automatic payment capture. |
allowInternationalCards | bool | body | Optional | Accept international cards. |
feesPercent | decimal | body | Optional | Fee percentage applied to the payer. |
internationalFeesPercent | decimal | body | Optional | Fee % specific to international cards. |
acceptUrl | string | body | Optional | Redirect URL on 3DS success. |
declineUrl | string | body | Optional | Redirect URL on 3DS failure. |
notificationUrl | string | body | Optional | URL notified when the transaction ends (success/failure). |
externalReference | string | body | Optional | Partner 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.
{host}/api/operations/cashin/card/{cardId}Execute with Saved Card
Add funds from a saved tokenized card.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
PhoneNumber | string | query | Required | The customer's phone number. |
CardId | int | route | Required | Identifier of the saved card. |
Cvv | string | body | Required | 3-digit security code. |
Amount | decimal | body | Required | Amount 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.
{host}/api/operations/cashin/card/agent/previewPreview (by Agent)
Check feasibility of depositing funds via agent code.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
code | string | query | Required | Agent code. |
Amount | decimal | body | Required | Amount to deposit. |
{host}/api/operations/cashin/card/agentExecute (by Agent)
Add funds to a customer's wallet via agent.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
code | string | query | Optional | Code of the agent whose wallet is credited. |
firstName | string | body | Required | Cardholder's first name. |
lastName | string | body | Required | Cardholder's last name. |
cvv | string | body | Required | 3-digit security code. |
amount | decimal | body | Required | Amount to deposit. |
pan | string | body | Required | Full card number. |
expiryDate | string | body | Required | Expiry date in YYMM format. |
keepAlive | bool | body | Required | Save the card for future use. |
cardName | string | body | Optional | Name chosen by the user to save the card. |
3dSecure | bool | body | Optional | Enable 3D Secure. Default: true. |
autoCapture | bool | body | Optional | Automatic payment capture. |
allowInternationalCards | bool | body | Optional | Accept international cards. |
feesPercent | decimal | body | Optional | Fee percentage applied to the payer. |
internationalFeesPercent | decimal | body | Optional | Fee % specific to international cards. |
acceptUrl | string | body | Optional | Redirect URL on 3DS success. |
declineUrl | string | body | Optional | Redirect URL on 3DS failure. |
notificationUrl | string | body | Optional | URL notified when the transaction ends (success/failure). |
externalReference | string | body | Optional | Partner 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
{host}/api/operations/transfer/previewPreview
Check feasibility of moving funds between customers' wallets internally.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
CustomerPhoneNumber | string | body | Required | Sender's phone number. Format: +212********* |
Amount | decimal | body | Required | Amount to transfer. |
Reason | string | body | Required | Transfer reason. |
RecipientPhoneNumber | string | body | Required | Beneficiary's phone number. Format: +212********* |
BeneficiaryId | int | body | Optional | Reference to an existing beneficiary (optional). |
{host}/api/operations/transferExecute
Move funds between customers' wallets internally.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
CustomerPhoneNumber | string | body | Required | Sender's phone number. |
Amount | decimal | body | Required | Amount to transfer. |
Reason | string | body | Required | Transfer reason. |
RecipientPhoneNumber | string | body | Required | Beneficiary's phone number. |
BeneficiaryId | int | body | Optional | Reference to an existing beneficiary (optional). |
Bank Transfer
{host}/api/operations/bank-transfer/previewPreview
Check feasibility of sending money from a wallet to an external bank account.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
CustomerPhoneNumber | string | body | Optional | Required if AgentCode is empty. Mutually exclusive with AgentCode (one OR the other). |
AgentCode | string | body | Optional | Required if CustomerPhoneNumber is empty. Agent Code (Principal or Retail). Mutually exclusive with CustomerPhoneNumber. |
Amount | decimal | body | Required | Amount to transfer. |
Reason | string | body | Required | Transfer reason (latin characters only, max 35 chars). |
BeneficiaryId | int | body | Optional | Optional if rib + beneficiaryName are provided. |
BeneficiaryName | string | body | Optional | Optional if beneficiaryId is provided. |
Rib | string | body | Optional | RIB: 24-digit numeric string. Optional if beneficiaryId is provided. |
Notes
- •At least one identifier among beneficiaryId or (rib + beneficiaryName) must be provided.
{host}/api/operations/bank-transferExecute
Send money from a wallet to an external bank account.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
CustomerPhoneNumber | string | body | Optional | Required if AgentCode is empty. Mutually exclusive with AgentCode (one OR the other). |
AgentCode | string | body | Optional | Required if CustomerPhoneNumber is empty. Mutually exclusive with CustomerPhoneNumber. |
Amount | decimal | body | Required | Amount to transfer. |
Reason | string | body | Optional | Transfer reason (optional at execute step). |
BeneficiaryId | int | body | Optional | Optional if rib + beneficiaryName are provided. |
BeneficiaryName | string | body | Optional | Optional if beneficiaryId is provided. |
Rib | string | body | Optional | RIB: 24 digits. Required if no beneficiaryId. |
Merchant Payment
{host}/api/operations/merchant/payment/push/manual/previewBy Phone — Preview
Check Pay Merchant by PhoneNumber.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
CustomerPhoneNumber | string | body | Required | Paying customer's phone number. |
Amount | decimal | body | Required | Payment amount. |
Reason | string | body | Required | Payment reason. |
RecipientPhoneNumber | string | body | Required | The merchant's phone number. |
BeneficiaryId | int | body | Optional | Reference to an existing beneficiary (optional). |
{host}/api/operations/merchant/payment/push/manualBy Phone — Execute
Pay Merchant by PhoneNumber.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
CustomerPhoneNumber | string | body | Required | Paying customer's phone number. |
Amount | decimal | body | Required | Payment amount. |
Reason | string | body | Required | Payment reason. |
RecipientPhoneNumber | string | body | Required | The merchant's phone number. |
BeneficiaryId | int | body | Optional | Reference to an existing beneficiary (optional). |
{host}/api/operations/merchant/payment/push/qrcode/previewBy QR Code — Preview
Check Pay Merchant by QR Code.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
CustomerPhoneNumber | string | body | Required | Paying customer's phone number. |
QrCodeContent | string | body | Required | Content of the scanned QR Code. |
Amount | decimal | body | Required | Payment amount. |
{host}/api/operations/merchant/payment/push/qrcodeBy QR Code — Execute
Pay Merchant by QR Code.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
CustomerPhoneNumber | string | body | Required | Paying customer's phone number. |
QrCodeContent | string | body | Required | QR Code content. |
Amount | decimal | body | Required | Payment amount. |
{host}/api/operations/merchant/payment/card/previewBy Card — Preview
Check Pay Merchant by card (Card to Wallet).
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
PhoneNumber | string | query | Required | The merchant's phone number. |
Amount | decimal | body | Required | Payment amount. |
{host}/api/operations/merchant/payment/cardBy Card — Execute
Pay Merchant by card (Card to Wallet). 3DS flow: the response provides `redirectionURL` to open.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
phoneNumber | string | query | Optional | The merchant's phone number. Format: +212********* |
firstName | string | body | Required | Cardholder's first name. |
lastName | string | body | Required | Cardholder's last name. |
cvv | string | body | Required | CVV (3 digits). |
amount | decimal | body | Required | Payment amount. |
pan | string | body | Required | Card number (PAN). |
expiryDate | string | body | Required | Expiry date in `YYMM` format. Ex: `2608`. |
keepAlive | bool | body | Required | Tokenize the card for reuse via the Tokenized Card endpoint. |
3dSecure | bool | body | Optional | Enable 3D Secure. Default: true. |
feesPercent | decimal | body | Optional | Fee percentage applied to the payer. |
allowInternationalCards | bool | body | Optional | Accept international cards. |
internationalFeesPercent | decimal | body | Optional | Fee % specific to international cards. |
autoCapture | bool | body | Optional | Automatic payment capture. |
notificationUrl | string | body | Optional | URL notified when the transaction ends (success/failure). |
acceptUrl | string | body | Optional | Redirect URL on 3DS success. |
declineUrl | string | body | Optional | Redirect URL on 3DS failure. |
cardName | string | body | Optional | Card label (for tokenization). |
externalReference | string | body | Optional | Merchant 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.
{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.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
cardId | int | path | Required | Tokenized card ID. |
PhoneNumber | string | query | Required | The merchant's phone number. Format: +212********* |
Cvv | string | body | Required | CVV (3 digits). |
Amount | decimal | body | Required | Payment 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.
{host}/api/operations/merchant/qrcode/staticStatic QR Generation
Generate a static QR Code for a merchant (no amount embedded). The customer enters the amount at payment time.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
customerPhoneNumber | string | query | Optional | Phone number of the merchant (customer) to generate the QR for. Format: +212********* |
maskedNumber | bool | query | Optional | Mask the merchant's number in the QR content. Ex: +2126######74 |
billNumber | string | body | Optional | Bill number to embed in the QR content (optional). |
additionalData | string | body | Optional | Free-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).
{host}/api/operations/merchant/qrcodeDynamic QR Generation
Generate a dynamic QR Code with a fixed amount and a unique reference.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
customerPhoneNumber | string | query | Optional | Phone number of the merchant (customer) to generate the QR for. Format: +212********* |
maskedNumber | bool | query | Optional | Mask the merchant's number. |
amount | decimal | body | Required | Fixed amount of the QR Code. |
billNumber | string | body | Optional | Bill number to embed in the QR content (optional). |
additionalData | string | body | Optional | Free-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).
{host}/api/operations/merchant/payment/card/captureBy 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.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
PhoneNumber | string | body | Required | The merchant's phone number. Format: +212********* |
Amount | decimal | body | Required | Amount to capture. |
OrderId | string | body | Required | Order identifier returned by the card payment (`orderId`). |
TransactionTrackId | string | body | Required | Tracking identifier returned by the card payment (`transactionTrackId`). |
SkipGatewayCall | bool | body | Optional | If 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).
{host}/api/operations/merchant/payment/card/reverseBy Card — Reverse
Reverse a merchant card payment authorization that has not been captured yet: the authorized funds are released without being debited.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
PhoneNumber | string | body | Required | The merchant's phone number. Format: +212********* |
Amount | decimal | body | Required | Amount of the authorization to reverse. |
OrderId | string | body | Required | Order identifier returned by the card payment (`orderId`). |
TransactionTrackId | string | body | Required | Tracking identifier returned by the card payment (`transactionTrackId`). |
SkipGatewayCall | bool | body | Optional | If 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.
{host}/api/operations/merchant/payment/card/refundBy Card — Refund
Refund an already captured merchant card payment, in full or partially via `RefundAmount`.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
PhoneNumber | string | body | Required | The merchant's phone number. Format: +212********* |
OperationId | int | body | Required | Identifier of the operation to refund. |
RefundAmount | decimal | body | Required | Amount to refund. |
OrderId | string | body | Optional | Order identifier of the original transaction (`orderId`). |
TransactionTrackId | string | body | Optional | Tracking 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.
{host}/api/operations/merchant/qrcode/statusQR Code Status
Check the status of a merchant QR Code by its reference.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
reference | string | query | Required | Reference of the QR Code to check. |
ChargeBack
{host}/api/operations/chargeback/previewPreview
Check the feasibility of performing a chargeback.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
SourcePhoneNumber | string | body | Required | Originating customer's phone number. Format: +212********* |
Amount | decimal | body | Required | Chargeback amount. |
Description | string | body | Required | Chargeback reason. |
DestinationPhoneNumber | string | body | Required | Recipient's phone number. Format: +212********* |
OriginalOperationId | int | body | Required | ID of the original operation that triggered the chargeback. |
{host}/api/operations/chargebackExecute
Execute a chargeback operation.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
SourcePhoneNumber | string | body | Required | Originating customer's phone number. |
Amount | decimal | body | Required | Chargeback amount. |
Description | string | body | Required | Chargeback reason. |
DestinationPhoneNumber | string | body | Required | Recipient's phone number. |
OriginalOperationId | int | body | Required | Original operation ID. |
Request Operations
{host}/api/operations/cashin/requestRequest CashIn
Request a CashIn operation. Generates a unique reference that expires over time.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
PhoneNumber | string | body | Required | The customer's phone number. |
Amount | decimal | body | Required | CashIn amount. |
Notes
- •operationType: 1 = CashIn, 2 = CashOut
- •operationStatus: 1 = open, 2 = completed, 3 = failed, 4 = canceled
{host}/api/operations/fatourati/cashin/requestRequest 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.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
PhoneNumber | string | body | Required | The customer's phone number. For a principal agent, replace phoneNumber by the Agent Code (PhoneNumber => Code). |
Amount | decimal | body | Required | The amount to cash in. Should be a positive numeric value. |
Description | string | body | Optional | A free-text field describing the purpose of the operation. |
FeesPercent | decimal | body | Optional | Fee 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
{host}/api/operations/cashout/requestRequest CashOut
Request a CashOut operation. Generates a unique reference that expires over time.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
PhoneNumber | string | body | Required | The customer's phone number. |
Amount | decimal | body | Required | CashOut amount. |
Get Operations
{host}/api/operationsBy Customer
Get a list of operations for a specific customer.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
PhoneNumber | string | query | Required | The customer's phone number. |
PageSize | int | query | Optional | Results per page. Default: 10. |
PageNumber | int | query | Optional | Page number. Default: 1. |
OperationType | list int | query | Optional | Filter 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. |
TransactionStatus | int | query | Optional | Filter by status: 1=OPEN, 2=COMPLETED, 3=FAILED, 4=CANCELED. |
Sens | int | query | Optional | Operation direction: 1=CREDIT, 2=DEBIT. |
From | datetime | query | Optional | Filter start date/time. |
To | datetime | query | Optional | Filter end date/time. |
Keyword | string | query | Optional | Search 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.
{host}/api/operations/{id}By ID
Get a specific operation by its ID.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
PhoneNumber | string | query | Required | The customer's phone number. |
Id | int | route | Required | Operation 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.
{host}/api/operations/allAll (by Partner)
Get a list of all operations by partner.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
pageNumber | int | query | Optional | Page number (starts at 1). Default: 1. |
pageSize | int | query | Optional | Results per page. Default: 10. |
operationType | list int | query | Optional | Filter by operation type(s). Repeatable parameter. |
operationStatus | list int | query | Optional | Filter by operation status(es). Repeatable parameter. |
from | datetime | query | Optional | Operations from datetime. |
to | datetime | query | Optional | Operations until datetime. |
search | string | query | Optional | Search keyword. |
openLoop | boolean | query | Optional | Filter open-loop operations (outside Chari wallets). |
method | string | query | Optional | Filter by payment method. |
includeDetails | boolean | query | Optional | Include 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
{host}/api/operations/refund/previewPreview
Check refund feasibility after merchant payment.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
PhoneNumber | string | body | Required | Phone number of the customer to refund. |
OperationId | int | body | Required | ID of the operation to refund. |
RefundAmount | decimal | body | Required | Refund amount. |
OrderId | string | body | Required | Original paymentGateway OrderId. |
TransactionTrackId | string | body | Required | Original paymentGateway TransactionTrackId. |
{host}/api/operations/refundExecute
Refund customers after merchant payment.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
phoneNumber | string | body | Required | The customer's phone number. |
OperationId | int | body | Required | ID of the operation to refund. |
RefundAmount | decimal | body | Required | Refund amount. |
OrderId | string | body | Required | Original OrderId. |
TransactionTrackId | string | body | Required | Original TransactionTrackId. |
Beneficiary
Manage a customer's beneficiaries: list, add, update, and delete. Beneficiaries can be identified by phone number and/or RIB.
{host}/api/customer/beneficiariesGet Beneficiaries
Get a list of beneficiaries for a customer.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
PhoneNumber | string | query | Required | The customer's phone number. |
PageSize | int | query | Optional | Results per page. Default: 10. |
PageNumber | int | query | Optional | Page number. Default: 1. |
SortBy | string | query | Optional | Sort field. |
SortOrder | string | query | Optional | Sort order (asc or desc). |
Name | string | query | Optional | Filter by beneficiary name. |
BeneficiaryNumber | string | query | Optional | Filter by beneficiary phone number. |
Rib | string | query | Optional | Filter by beneficiary RIB. |
Search | string | query | Optional | Filter by keyword. |
From | datetime | query | Optional | Creation date — start. |
To | datetime | query | Optional | Creation date — end. |
{host}/api/customer/beneficiariesAdd Beneficiary
Add a new beneficiary. At least PhoneNumber or RIB must be provided.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
phoneNumber | string | query | Required | Customer (owner) phone number. |
name | string | body | Required | Beneficiary name. Minimum 2 letters. |
phoneNumber | string | body | Optional | Beneficiary's phone number. Format: +212********* |
rib | string | body | Optional | Beneficiary RIB. 24 digits. |
email | string | body | Optional | Beneficiary email. |
Notes
- •PhoneNumber or RIB: at least one of the two must be provided.
{host}/api/customer/beneficiaries/{beneficiaryId}Update Beneficiary
Update an existing beneficiary.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
phoneNumber | string | query | Required | Customer (owner) phone number. |
beneficiaryId | int | path | Required | Beneficiary ID to update. |
name | string | body | Required | Beneficiary name. Minimum 2 letters. |
phoneNumber | string | body | Optional | Beneficiary phone number. |
rib | string | body | Optional | Beneficiary RIB. 24 digits. |
email | string | body | Optional | Beneficiary email. |
{host}/api/customer/beneficiaries/{Id}Delete Beneficiary
Delete an existing beneficiary.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
PhoneNumber | string | query | Required | The customer's phone number. |
Id | int | route | Required | ID of the beneficiary to delete. |
Tokenized Cards
View and manage saved (tokenized) bank cards of a customer.
{host}/api/customers/tokenized/cardsGet Cards by Customer
Retrieve all tokenized cards for a customer.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
PhoneNumber | string | query | Required | The customer's phone number. |
PageSize | int | query | Optional | Results per page. Default: 10. |
PageNumber | int | query | Optional | Page 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.
{host}/api/customers/tokenized/cards/{id}Get Card by ID
Retrieve a specific tokenized card by its ID.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
PhoneNumber | string | query | Required | The customer's phone number. |
Id | int | route | Required | Card ID. |
{host}/api/customers/tokenized/cards/{cardId}Delete Tokenized Card
Delete a tokenized card by its Id.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
cardId | int | path | Required | Tokenized card ID to delete. |
phoneNumber | string | query | Required | The customer's phone number. Format: +212********* |
{host}/api/agents/tokenized/cardsGet Agent Cards
Get the paginated list of an agent's tokenized cards.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
code | string | query | Required | Agent code. |
pageSize | int | query | Optional | How many results are returned per page. Default value = 10. |
pageNumber | int | query | Optional | Which 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).
{host}/api/agents/tokenized/cards/{cardId}Get Agent Card by ID
Retrieve a specific tokenized card of an agent by its ID.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
code | string | query | Required | Agent code. |
cardId | int | route | Required | Tokenized card identifier. |
Notes
- •The card must belong to the agent identified by code, otherwise it is not returned.
{host}/api/agents/tokenized/cards/{cardId}Update Agent Card Name
Update the name (cardName) of an agent's tokenized card.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
code | string | query | Required | Agent code. |
cardId | int | route | Required | Identifier of the tokenized card to rename. |
cardName | string | body | Required | New 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.
{host}/api/agents/tokenized/cards/{cardId}Delete Agent Card
Delete an agent's tokenized card.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
cardId | int | route | Required | Identifier of the tokenized card to delete. |
code | string | query | Required | Agent code. |
Notes
- •HTTP 200 confirms the deletion (no detailed response body).
- •Deletion is permanent: to use the card again, it must be tokenized anew.
Retail Agents
Manage retail agents: list, add, and execute CashIn/CashOut operations by reference.
{host}/api/agents/retailGet Retail Agents
List all retail agents.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
Code | string | query | Required | Agent code. |
PageSize | int | query | Optional | Results per page. Default: 10. |
PageNumber | int | query | Optional | Page number. Default: 1. |
From | datetime | query | Optional | Agent creation — start date. |
To | datetime | query | Optional | Agent creation — end date. |
{host}/api/agents/retail/{code}Get Agent by Code
Get a specific retail agent by code.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
Code | string | route | Required | Agent code. |
{host}/api/agents/retailAdd Retail Agent
Add a new retail agent.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
PhoneNumber | string | body | Required | The agent's phone number. Format: +212********* |
Name | string | body | Required | Agent's trade name. |
FirstName | string | body | Required | First name. Minimum 2 letters. |
LastName | string | body | Required | Last name. Minimum 2 letters. |
Cin | string | body | Required | ID document number. |
Address | string | body | Optional | Agent's address. |
Email | string | body | Optional | Agent's email. |
{host}/api/agents/retail/{code}Update Retail Agent
Update an existing retail agent, identified by their code.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
Code | string | route | Required | Code of the agent to update. |
Name | string | body | Optional | Agent's trade name. |
FirstName | string | body | Optional | Agent's first name. |
LastName | string | body | Optional | Agent's last name. |
PhoneNumber | string | body | Optional | The agent's phone number. Format: +212********* |
Cin | string | body | Optional | ID document number. |
Address | string | body | Optional | Agent's address. |
Email | string | body | Optional | Agent's email. |
Gender | string | body | Optional | Agent'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).
{host}/api/operations/cashin/requestGet CashIn by Reference
Retrieve requested operation details using a unique reference ID.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
Reference | string | query | Required | Unique reference of the operation. |
Notes
- •type: 1 = CashIn, 2 = CashOut
- •status: 1 = open, 2 = completed, 3 = failed
{host}/api/operations/cashin/agentExecute CashIn by Reference
Execute a CashIn operation by the agent.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
Code | string | body | Required | The code of the Agent performing the operation. |
Reference | string | body | Required | The reference ID of the operation to retrieve. |
{host}/api/operations/cashout/requestGet CashOut by Reference
Retrieve CashOut operation details by reference.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
Reference | string | query | Required | Unique reference of the operation. |
{host}/api/operations/cashout/agentExecute CashOut by Reference
Execute a CashOut operation by the agent.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
Code | string | body | Required | The code of the Agent performing the operation. |
Reference | string | body | Required | The reference ID of the operation to retrieve. |
Principal Agents
View information about a principal agent.
{host}/api/agents/principal/{code}Get Principal Agent by Code
Get the account info of a principal agent.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
code | string | path | Required | The code of the principal agent. |
Notes
- •Response: Agent object + Account object (balance, RIB, level, etc.).
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
{host}/api/cards/programsGet Programs
Get a list of available programs for the partner.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
page | int | query | Optional | Which page of results to retrieve. Starts at 1. Default value = 1. |
take | int | query | Optional | How 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).
{host}/api/cards/applicationsAdd Application
Add a new card application.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
PhoneNumber | string | query | Required | The customer's phone number. Format: +212********* |
cardProgramId | int | query | Required | Card program identifier. |
Notes
- •No body for now.
{host}/api/cards/applicationsGet Applications
Get a list of applications by filters.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
status | int | query | Optional | Filter by status: 1=Pending, 2=Validated, 3=Rejected. |
page | int | query | Optional | Which page of results to retrieve. Starts at 1. Default value = 1. |
take | int | query | Optional | How 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).
{host}/api/cards/applications/customerGet Application by Customer
Get a list of applications by customer.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
phoneNumber | string | query | Required | The customer's phone number. Format: +212********* |
page | int | query | Optional | Which page of results to retrieve. Starts at 1. Default value = 1. |
take | int | query | Optional | How 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).
{host}/api/cards/applications/{id}/validateValidate Application
Validate an existing application in progress.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
id | int | path | Required | Application Id to validate. |
Notes
- •No body for now.
{host}/api/cards/applications/{id}/rejectReject Application
Reject an existing application in progress.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
id | int | path | Required | Application Id to reject. |
reason | string | body | Optional | Rejection reason (optional), later returned in rejectionReason. |
Notes
- •The body accepts an optional reason field: the reason is returned in the application's rejectionReason.
{host}/api/cardsGet Cards
Get a list of cards by partner.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
pageNumber | int | query | Optional | Which page of results to retrieve. Starts at 1. Default value = 1. |
pageSize | int | query | Optional | How many results are returned per page. Default value = 10. |
customerId | int | query | Optional | Filter by customer id. |
accountId | int | query | Optional | Filter by account id. |
cardProgramId | int | query | Optional | Card program id. |
status | int | query | Optional | Card status: 1=ISSUED, 2=ACTIVATED, 3=BLOCKED, 4=SUSPENDED, 5=EXPIRED, 6=CANCELLED. |
isVirtual | boolean | query | Optional | Filter virtual (true) or physical (false) cards. |
schemaId | int | query | Optional | Card scheme id (e.g. VISA). |
deliveryStatusId | int | query | Optional | Delivery 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).
{host}/api/cards/{id}Get Card by Id
Get a specific card by id.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
id | int | path | Required | Card Id. |
{host}/api/cards/{id}/activateActivate Card
Activate the card and make it ready for use.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
PhoneNumber | string | query | Required | The customer's phone number. Format: +212********* |
Id | int | route | Required | Card Id to activate. |
Notes
- •Response: the updated card object. cardStatus 2 = ACTIVATED.
{host}/api/cards/{id}/blockBlock Card
Temporarily block the card from any transactions.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
PhoneNumber | string | query | Required | The customer's phone number. Format: +212********* |
Id | int | route | Required | Card Id to block. |
Reason | string | body | Optional | Reason for blocking the card. |
Notes
- •Response: the updated card object. cardStatus 3 = BLOCKED.
{host}/api/cards/{id}/suspendSuspend Card
Suspend the card usage until further notice.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
PhoneNumber | string | query | Required | The customer's phone number. Format: +212********* |
Id | int | route | Required | Card Id to suspend. |
Reason | string | body | Optional | Reason for suspending the card. |
Notes
- •Response: the updated card object. cardStatus 4 = SUSPENDED.
{host}/api/cards/{id}/reactivateReactivate Card
Reactivate a previously suspended card.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
PhoneNumber | string | query | Required | The customer's phone number. Format: +212********* |
Id | int | route | Required | Card Id to reactivate. |
Notes
- •Response: the updated card object. cardStatus 2 = ACTIVATED.
{host}/api/cards/{id}/cancelCancel Card
Permanently cancel and deactivate the card.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
PhoneNumber | string | query | Required | The customer's phone number. Format: +212********* |
Id | int | route | Required | Card Id to cancel. |
Reason | string | body | Optional | Reason for cancelling the card. |
Notes
- •Response: the updated card object. cardStatus 6 = CANCELLED. This action is permanent: the card can no longer be reactivated.
{host}/api/cards/{id}/servicesCard Usage Control
Update card services for usage control.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
PhoneNumber | string | query | Required | The customer's phone number. Format: +212********* |
Id | int | route | Required | Card Id to update. |
allowAtm | bool | body | Required | Enable or disable ATM withdrawals for the card. |
allowOnline | bool | body | Required | Enable or disable online/e-commerce transactions. |
allowPos | bool | body | Required | Enable or disable POS (Point of Sale) payments. |
contactlessEnabled | bool | body | Required | Enable or disable contactless payments. |
Notes
- •Response: true / false.
{host}/api/card-transactions/card/{cardId}Get Card Transactions
Get card transactions.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
PhoneNumber | string | query | Required | The customer's phone number. Format: +212********* |
CardId | int | route | Required | Card Id. |
PageSize | int | query | Optional | How many results are returned per page. Default value = 10. |
PageNumber | int | query | Optional | Which page of results to retrieve. Starts at 1. Default value = 1. |
From | datetime | query | Optional | Filter from date. |
To | datetime | query | Optional | Filter to date. |
Notes
- •collection : list of transactions.
- •count : count of transactions.
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
{host}/api/network/operations/cashin200Execute 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.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
withContext | bool | query | Optional | Get the result with context if it exists. Default: false. |
reference | string | body | Required | Numeric reference returned when the CashIn request was created. |
entity | string | body | Optional | Network entity executing the operation. |
{host}/api/network/operations/cashout200Execute 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.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
withContext | bool | query | Optional | Get the result with context if it exists. Default: false. |
reference | string | body | Required | Numeric reference returned when the CashOut request was created. |
entity | string | body | Optional | Network entity executing the operation. |
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
https://{your-domain}/webhooks/chariYou 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
| Property | Type | Required | Description |
|---|---|---|---|
WebhookId | string | Required | Webhook identifier. |
EventId | string | Required | Event type. Ex: bank-transfer.initiated |
CRequestId | string | Required | Tracking identifier received from the partner. |
OperationId | int | Required | ID of the executed operation (can be 0 if no operation was created). |
TransactionId | int | Optional | Main transaction ID. |
OperationType | int | Required | Operation type code (see Types). |
OperationStatus | int | Required | 1 = Open, 2 = Completed, 3 = Failed, 4 = Canceled |
CreatedAt | date | Required | Process start date. |
ExecutedAt | date | Required | Operation execution date. |
Amount | decimal | Required | Operation amount. |
FeeAmount | decimal | Required | Fee amount. |
PrimaryAccountNumber | string | Required | Sender's phone number. |
SecondaryAccountNumber | string | Optional | Recipient's phone number. |
Method | string | Optional | Method: Card / Agent / Network |
Cash-in Card specific
| Property | Type | Required | Description |
|---|---|---|---|
CustomData | string | Optional | Custom data provided by the partner (max 128 characters). |
GatewayTrackId | string | Optional | Gateway Transaction Track Id. |
GatewayOrderId | string | Optional | Gateway Transaction Order Id. |
GatewayReferenceId | string | Optional | Gateway Transaction Reference Id. |
Bank Transfer specific
| Property | Type | Required | Description |
|---|---|---|---|
BankTransferBeneficiaryName | string | Optional | Beneficiary name for bank transfers. |
Cash-in / Cash-out (network reference)
| Property | Type | Required | Description |
|---|---|---|---|
NetworkName | string | Optional | Network name for network operations. |
Reference | string | Optional | Reference of the by-reference operation. |
Retry Policy
Events
| Event ID | Description |
|---|---|
customer.level.updated | Customer account level updated |
cashin.card.authorized | CashIn by Card accepted |
payment.card.authorized | Payment by Card accepted |
payment.received | Payment received by merchant |
payment.confirmed | Bill payment confirmed (CONFIRME state) |
payment.cancelled | Bill payment cancelled (ANNULE state) |
payment.refunded | Bill payment refunded (REMBOURSE state) |
payment.failed | Bill payment failed (FAILED state) |
bank-transfer.initiated | Bank transfer sent |
bank-transfer.completed | Bank transfer finalized (settled, rejected, or returned — inspect OperationStatus) |
bank-transfer.received | Bank transfer received |
transfer.received | Transfer received |
cashin.network.executed | CashIn by reference executed |
cashout.network.executed | CashOut by reference executed |
Example Event Body
customer.level.updated — Customer level updated
{
"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
{
"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
{
"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
{
"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)
{
"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)
{
"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)
{
"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)
{
"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
{
"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
{
"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
{
"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
{
"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
{
"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
{
"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"
}
}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.
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.
{host}/api/services/telco/catalog/b2bRetrieve Catalog
Get the list of available recharge products and offers for a given phone number and operator.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
RecipientPhoneNumber | string | body | Required | The customer's phone number, in the required format: +212*********. |
Amount | int | body | Required | The monetary value to be transacted. Should be a positive numeric value. |
Operator | int | body | Required | Operator: 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.
{host}/api/operations/service/telco/recharge/b2bRequest Top-up
Initiate a mobile top-up for a given phone number and selected offer, with real-time validation and transaction tracking.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
RecipientPhoneNumber | string | body | Required | The customer's phone number, in the required format: +212*********. |
Amount | int | body | Required | The monetary value to be transacted. Should be a positive numeric value. |
Operator | int | body | Required | Operator: 1 = Maroc Telecom, 2 = Orange, 3 = Inwi. |
ProductCode | int | body | Required | The available product code, given by the catalog endpoint. |
Code | string | body | Required | The principal agent code — the account that will be debited. Provided by Chari after activation of your Partner Account. |
RechargeType | int | body | Required | Recharge 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).
{host}/api/operations/service/telco/recharge/previewCustomer Recharge — Preview
Check the feasibility of a phone recharge paid from the customer's wallet (amount, fees) before execution.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
customerPhoneNumber | string | body | Required | Phone number of the customer whose wallet will be debited. Format: +212********* |
recipientPhoneNumber | string | body | Required | Phone number to top up. Format: +212********* |
amount | decimal | body | Required | Top-up amount. |
operator | int | body | Required | Operator: 1 = Maroc Telecom, 2 = Orange, 3 = Inwi. |
rechargeType | int | body | Required | Recharge type: 0 = Classic, 1 = Product (swagger enum: 0 to 3). |
productCode | int | body | Optional | Product code from the catalog endpoint (used for a Product-type recharge). |
rechargeStatus | int | body | Optional | Recharge status (swagger enum: 0 to 4). Field of the DTO shared with responses. |
beneficiaryId | int | body | Optional | Reference 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.
{host}/api/operations/service/telco/rechargeCustomer Recharge — Execute
Execute a phone recharge paid from the customer's wallet, for the selected number and offer.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
customerPhoneNumber | string | body | Required | Phone number of the customer whose wallet will be debited. Format: +212********* |
recipientPhoneNumber | string | body | Required | Phone number to top up. Format: +212********* |
amount | decimal | body | Required | Top-up amount. |
operator | int | body | Required | Operator: 1 = Maroc Telecom, 2 = Orange, 3 = Inwi. |
rechargeType | int | body | Required | Recharge type: 0 = Classic, 1 = Product (swagger enum: 0 to 3). |
productCode | int | body | Optional | Product code from the catalog endpoint (used for a Product-type recharge). |
rechargeStatus | int | body | Optional | Recharge status (swagger enum: 0 to 4). Field of the DTO shared with responses. |
beneficiaryId | int | body | Optional | Reference 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.
{host}/api/operations/service/telco/rechargeCustomer Recharge History
Retrieve the list of a customer's phone recharge operations, with pagination and status filter.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
phoneNumber | string | query | Required | The customer's phone number. Format: +212********* |
pageSize | int | query | Optional | Number of items per page. |
pageNumber | int | query | Optional | Page number to retrieve. |
status | list int | query | Optional | Recharge 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.
{host}/api/services/telco/catalogTelco Catalog (generic variant)
Generic variant of the catalog endpoint: takes a phone number, an amount and an operator, and returns a list of strings.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
phoneNumber | string | body | Optional | Phone number concerned. Format: +212********* |
amount | int | body | Required | Amount of the intended top-up. |
operator | int | body | Required | Operator: 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.
{host}/api/services/telco/exportTelco Data Export
Trigger the export of telco data over a given period. Returns a boolean indicating whether the request succeeded.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
from | datetime | query | Required | Start date/time of the period to export (ISO 8601). |
to | datetime | query | Required | End 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.
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.
{host}/api/vouchers/articlesRetrieve Catalog (articles)
Retrieve the current catalog: the list of voucher articles for a given brand.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
phoneNumber | string | query | Required | The customer's phone number, in the format +212*********. |
brandId | int | query | Required | Brand identifier. Should be a positive numeric value. |
page | int | query | Optional | Which page of results to retrieve. Starts at 1. Default: 1. |
take | int | query | Optional | How many results are returned per page. Default: 10. |
{host}/api/vouchers/brandsRetrieve Brands
Retrieve the current list of available voucher brands.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
phoneNumber | string | query | Required | The customer's phone number, in the format +212*********. |
page | int | query | Optional | Which page of results to retrieve. Starts at 1. Default: 1. |
take | int | query | Optional | How 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}.
{host}/api/vouchers/brands/{id}Get Brand by Id
Get a specific brand by its Id.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
id | int | path | Required | Brand Id. |
phoneNumber | string | query | Required | The customer's phone number, in the format +212*********. |
{host}/api/vouchers/{id}/articlesGet Vouchers by Brand Id
Get the list of vouchers associated with a brand, by brand Id.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
id | int | path | Required | Brand Id. |
phoneNumber | string | query | Required | The customer's phone number, in the format +212*********. |
Notes
- •The response mirrors a Brand object, as defined in the source documentation.
{host}/api/operations/voucher/previewPurchase Voucher — Preview
Check the feasibility of the voucher purchase operation (amount, fees) before confirmation.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
CustomerPhoneNumber | string | body | Required | The customer phone number, in the format +212*********. |
DestinationPhoneNumber | string | body | Required | The recipient's phone number, in the format +212*********. |
BeneficiaryName | string | body | Required | A free-text field describing the beneficiary name. |
ProviderSkuId | string | body | Required | The article identifier. |
ProviderId | string | body | Required | The 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.
{host}/api/operations/voucher/confirmPurchase Voucher — Confirm
Execute the voucher purchase operation. Returns the voucher code and its details.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
customerPhoneNumber | string | body | Required | The customer phone number, in the format +212*********. |
destinationPhoneNumber | string | body | Required | The recipient's phone number, in the format +212*********. |
beneficiaryName | string | body | Required | A free-text field describing the beneficiary name. |
providerSkuId | string | body | Required | The article identifier. |
providerId | string | body | Required | The 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.
{host}/api/operations/service/voucher/previewVoucher Service — Preview
Check the feasibility of purchasing a local voucher identified by its SKU, before execution. Returns the completed voucher object (amount included).
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
customerPhoneNumber | string | body | Required | The customer phone number, in the format +212*********. |
skuId | int | body | Required | SKU identifier of the local voucher (see the local vouchers list). |
providerSkuId | string | body | Optional | Provider-side SKU identifier (if any). |
destinationPhoneNumber | string | body | Optional | The recipient's phone number, in the format +212*********. |
beneficiaryName | string | body | Optional | A free-text field describing the beneficiary name. |
amount | decimal | body | Optional | Voucher amount (filled in by the server in the response). |
providerId | int | body | Optional | The 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.
{host}/api/operations/service/voucherVoucher 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.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
customerPhoneNumber | string | body | Required | The customer phone number, in the format +212*********. |
skuId | int | body | Required | SKU identifier of the local voucher (see the local vouchers list). |
providerSkuId | string | body | Optional | Provider-side SKU identifier (if any). |
destinationPhoneNumber | string | body | Optional | The recipient's phone number, in the format +212*********. |
beneficiaryName | string | body | Optional | A free-text field describing the beneficiary name. |
amount | decimal | body | Optional | Voucher amount (if applicable). |
providerId | int | body | Optional | The 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.
{host}/api/vouchersList Local Vouchers
Fetch the list of local vouchers available for a customer, with pagination and brand/keyword filters.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
phoneNumber | string | query | Required | The customer's phone number, in the format +212*********. |
page | int | query | Optional | Page number to retrieve. |
take | int | query | Optional | Number of items per page. |
brandId | int | query | Optional | Filter by brand Id (see the brands endpoint). |
keyword | string | query | Optional | Keyword 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).
{host}/api/vouchers/productClick & Collect Products
Fetch the paginated list of available "click & collect" products.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
page | int | query | Optional | Page number to retrieve. |
take | int | query | Optional | Number 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}.
{host}/api/vouchers/products/{configId}Get Product Details
Fetch detailed product information from its configuration identifier.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
configId | string | path | Required | Product 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).
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.
{host}/api/bills/creanciersList 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.
{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.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
creancierId | string | query | Required | Creditor identifier obtained via GET /creanciers (4 digits). |
Notes
- •codeRetour: 000 = ACCEPTE, 104 = creditor non-existent or inactive, 908 = technical error.
{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.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
creancierId | string | query | Required | Creditor identifier (4 digits). |
creanceId | string | query | Required | Receivable 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.
{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).
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
phoneNumber | string | query | Required | End user's Chari Money phone number, international format (e.g., +212670770743). |
creancierId | string | query | Required | Creditor identifier (4 digits). |
creanceId | string | query | Required | Receivable identifier (2 positions). |
creancierVals | array | body | Required | Array of user-entered values: { nomChamp, valChamp } objects (excluding typeChamp=libelle fields). Note: the property is named valChamp (not valeurChamp) in this body. |
alias | string | body | Optional | Alias to save if the bill is added to favorites. |
addToFavorites | boolean | body | Optional | true to add the bill to the customer's favorites. |
qrCodeContent | string | body | Optional | Content 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.
{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).
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
phoneNumber | string | query | Required | End 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. |
creancierId | string | body | Required | Creditor identifier (same values as /impayes). |
creanceId | string | body | Required | Receivable identifier. |
refTxFatourati | string | body | Required | Reference returned by /impayes. Links the call to the open transaction. |
totalPayment | boolean | body | Optional | true to settle all unpaid items, false for a partial selection. |
listeArticleSelectionnes | array | body | Required | Subset of impayesParams selected by the user: { idArticle, prixTTC, typeArticle, dateFacture, description } objects. |
creancierVals | array | body | Required | Entered identification fields: { nomChamp, valChamp } objects. Note: the property is named valChamp (not valeurChamp) in this body, and libelle is not accepted here. |
globalParams | array | body | Optional | Global 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).
{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.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
phoneNumber | string | query | Required | End user's Chari Money phone number, international format (+212*********). |
creancierId | string | body | Required | Creditor identifier (4 digits, same values as /impayes). |
creanceId | string | body | Required | Receivable identifier (2 positions). |
refTxFatourati | string | body | Required | Reference returned by /impayes (12 digits). Links the call to the open transaction. |
totalPayment | boolean | body | Optional | true to settle all unpaid items, false for a partial selection. |
listeArticleSelectionnes | array | body | Required | Articles selected by the user: { idArticle, prixTTC, typeArticle, dateFacture, description } objects taken from impayesParams. |
creancierVals | array | body | Required | Entered identification fields: { nomChamp, valChamp } objects. Note: the property is named valChamp (not valeurChamp) in this body. |
globalParams | array | body | Optional | Global 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.
{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.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
phoneNumber | string | query | Required | Customer's Chari Money phone number, international format (+212*********). |
pageNumber | int | query | Optional | Page number to return. |
pageSize | int | query | Optional | Number 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…).
{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.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
reference | string | query | Optional | Fatourati 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).
{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.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
operationId | int | path | Required | Chari operation identifier of the bill payment (see chariOperationId from /reference/status or the history). |
phoneNumber | string | query | Required | Customer'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.
{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.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
phoneNumber | string | query | Required | Customer'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.
{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").
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
favoriteId | int | path | Required | Favorite identifier (obtained via GET /api/bills/favorite). |
phoneNumber | string | query | Required | Chari Money phone number of the customer who owns the favorite, international format (+212*********). |
alias | string | body | Required | New 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.
{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.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
favoriteId | int | path | Required | Identifier of the favorite to delete (obtained via GET /api/bills/favorite). |
phoneNumber | string | query | Required | Chari 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.
Types & References
Operation Types
| ID | Code |
|---|---|
| 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 |
Transaction Types
| ID | Code |
|---|---|
| 1 | CASHIN |
| 2 | CASHOUT |
| 3 | TRANSFER |
| 5 | MOBILE_PAYMENT |
| 6 | TRANSACTION_FEES |
| 7 | PAYMENT_REFUND |
| 9 | CHARGEBACK |
| 10 | CHARGEBACK_CANCELLATION |
| 16 | BANK_TRANSFER |
| 17 | RECHARGE |
| 18 | CASHBACK |
| 24 | CARD_PAYMENT |
| 25 | BILL_PAYMENT |
Operation Statuses
| ID | Code | Description |
|---|---|---|
| 1 | OPEN | Open (lifecycle in progress) |
| 2 | COMPLETED | Completed successfully |
| 3 | FAILED | Failed |
| 4 | CANCELED | Canceled |
Transaction Statuses
| ID | Code | Description |
|---|---|---|
| 1 | OPEN | Open (in progress) |
| 2 | COMPLETED | Completed |
| 3 | FAILED | Failed |
| 4 | CANCELED | Canceled |
Transaction Direction (Sens)
| ID | Code | Description |
|---|---|---|
| 1 | CREDIT | Credit (incoming funds) |
| 2 | DEBIT | Debit (outgoing funds) |
Customer Statuses
| ID | Code | Description |
|---|---|---|
| 0 | NOT_EXISTS | Number does not exist at ChariMoney |
| 1 | NOT_CONFIRMED | Exists but not confirmed (OTP not entered) |
| 2 | CONFIRMED | Confirmed and registered with Switch |
| 3 | ACTIVE | Registered, active, and PIN created |
| 4 | LOCKED_TEMPORARY | Temporarily locked (excessive attempts) |
| 5 | LOCKED | Locked |
Account Levels
| ID | Code | Description |
|---|---|---|
| 1 | LEVEL_1 | Level 1 — Name + valid phone + CIN number. Limit: 1,000 MAD. |
| 2 | LEVEL_2 | Level 2 — Full KYC (CIN + selfie or document scan). Limit: 4,000 MAD. |
| 3 | LEVEL_3 | Level 3 — Verified ID + interview + digital customer record. Limit: 20,000 MAD. |
| 4 | LEVEL_4 | Level 4 — Full KYC + interview + proof of income + proof of address. Limit: 100,000 MAD. |
| 5 | MERCHANT | Merchant — Full KYB + IF/RC business registration. Limit: negotiated. |
Document Types
| ID | Code | Description |
|---|---|---|
| 1 | IdentityCard | National identity card |
| 2 | DrivingLicense | Driving license |
| 3 | Passport | Passport |
| 4 | ResidencePermit | Residence permit |
| 5 | ProofOfIncome | Proof of income |
| 6 | ProofOfResidence | Proof of residence |
| 7 | Selfie | Selfie / Face photo |
| 8 | CommercialRegister | Commercial 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.
| Scope | Endpoints |
|---|---|
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 |
Error Codes
HTTP Status Codes
Error Response Format
{
"errorCode": 20005,
"errorDescription": "The specified user could not be found."
}Chari Error Codes
10xxxGeneral
| Code | Message | Related Endpoints |
|---|---|---|
| 10001 | Missing Parameters. |
20xxxCustomer
| Code | Message | Related Endpoints |
|---|---|---|
| 20000 | The phone number format is invalid. | |
| 20005 | The specified user could not be found. | |
| 20006 | The initial parameters provided are incorrect or invalid. | |
| 20007 | The Merchant Category Code (MCC) provided is incorrect or not recognized. | |
| 20008 | Registration is temporarily locked due to security or policy restrictions. | |
| 20009 | The request is pending confirmation. Please wait for further processing. | |
| 20017 | There is no pending request associated with the provided Phone Number. |
26xxxPIN / Authentication
| Code | Message | Related Endpoints |
|---|---|---|
| 26001 | The entered PIN is incorrect. | |
| 26004 | A PIN has already been set for this wallet. | |
| 26005 | The provided PIN does not meet the required format (must be a 4-digit number). |
27xxxBeneficiary
| Code | Message | Related Endpoints |
|---|---|---|
| 27000 | The Beneficiary already exists with the same phoneNumber. | |
| 27001 | The Beneficiary does not exist. |
32xxxKYC / Upgrade
| Code | Message | Related Endpoints |
|---|---|---|
| 32000 | An upgrade request is already under review for this account. |
Infrastructure & Security
Environments
Sandbox
https://sandbox.charimoney.comDevelopment and testing. Transactions are simulated.
Production
Communiqué sur demandeLive 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
- 1Provide a list of public IP addresses or domains that will be used to access the API.
- 2Send this information to the support team before attempting API integration.
- 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
- 1Request API keys
Contact support to receive your dedicated sandbox and production keys.
- 2Submit IPs/domains
Provide the list of public IPs or domains for whitelisting.
- 3Test in sandbox
Run all your integration tests in the sandbox environment.
- 4Go 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.