Hosted online store in Morocco: publish your products, get paid and track your orders
Hosted online store in Morocco: publish products with a price and optional stock, share each sales page and track orders from your portal or through the API.
A hosted online store lets you sell in Morocco without building a website: every product you publish gets its own sales page, with its price in dirhams and, if you want, its stock; you share that page wherever you like, the buyer orders there and pays by card or in cash at an agency, and you track every order from your portal, from awaiting payment to delivered. This guide shows how to publish a product from the portal or through the API, share its page, track orders, get notified of a payment, sync a catalog, and when to move to a more complete tool.
The hosted online store, in plain terms
ChariPay is a Moroccan payment platform, a PSP operated by Chari Money, a payment institution licensed by Bank Al-Maghrib. Its hosted storefront answers a specific situation: no website yet? Publish your products on your hosted storefront and track your orders — awaiting payment, paid, shipped, delivered — from your portal. Through the API, the Products module carries each product's price, optional stock and sales page.
In practice, the tool does two things, and does them simply:
- One sales page per product. It presents the product and its price, and it is shared like a link.
- Order tracking. Every order placed on that page shows up in your portal with its status.
On the payment side, on the hosted storefront, the buyer chooses at checkout to pay by card — on the hosted payment page, with 3-D Secure — or in cash: they then receive a reference to pay at an agency of the Chari network. Card payment happens on the same page as the hosted checkout: you never see the card number.
What the hosted storefront does not do, to be clear from the start: it does not handle delivery or carriers, it offers no cart that groups several products and no domain name of your own. It is a simple storefront, designed for a handful of products and for getting started.
Publishing a product from the portal
From the portal, publishing takes a few steps:
- 1Create the product with its price in dirhams and, if needed, its stock. With no stock set, the product stays on sale with no quantity limit.
- 2Get its sales page. That is the address you will share, exactly as you would share a payment link.
- 3Check it in test mode. Open the page the way a customer would, place a mock order by card, and watch the order appear in the portal with its status.
Try it with a real product from your catalog: Start in test mode. Three fields (name, work email, company), an activation link received by email to choose your password, then the portal, where you publish your product and, if you integrate through the API, create your test key after re-authenticating. Pay your mock order with the test card 4918 9141 0719 5005, CVV 123, any future expiry date, 3-D Secure code 555: only this card is accepted, and no real money moves. Test mode is free, with no time limit and no commitment; a real cash deposit at an agency is not simulated.
Publishing through the API: the Products module
If your catalog already lives in another tool, or if you want to automate, the Products module of the API docs exposes six endpoints on the single base URL https://api-psp.charipay.ma:
| Endpoint | Role |
|---|---|
POST /v1/products | Create a product |
GET /v1/products | List your products (paginated) |
GET /v1/products/{reference} | Read a product |
PATCH /v1/products/{reference} | Update a product (only the fields you send change) |
DELETE /v1/products/{reference} | Deactivate a product |
GET /v1/products/{reference}/orders | List a product's orders |
Creating a product, in curl:
curl -X POST 'https://api-psp.charipay.ma/v1/products' \
-H 'X-CHARI-PAY-API-KEY: chari_sk_test_...' \
-H 'Content-Type: application/json' \
-d '{
"name": "Coffret savon noir 500 g",
"description": "Savon noir artisanal, coffret cadeau",
"price": 149.90,
"stockQuantity": 40,
"externalId": "sku-savon-noir-500",
"metadata": { "sku": "SN-500" }
}'Only name and price are required. The price is in dirhams, in major units (149.90 = MAD 149.90); stockQuantity is optional, and leaving it out means unlimited stock; description, imageUrl and expiresAt (the end of the sale, in the future) complete the listing. The response (201, or 200 if the externalId already exists) carries the product's reference (prod_…) and its shopUrl, the sales page to share, along with the available and reserved quantities. The optional metadata is echoed back verbatim on product reads and in the payment event for this product's orders.
The chari_sk_test_… key works in the sandbox; the same request with a production key publishes in production. A key is a secret: never in the browser, a mobile app, a git repository or a screenshot.
Sharing a product page with payment
A product page with payment is only worth something if your customers see it. Share it wherever you talk to them:
- On social media, as a link in your profile, a post or a story.
- In messaging apps, when a customer asks about a specific product: the page gives them the price, the description and a way to pay, with no back-and-forth.
- By email, in a newsletter or a reply to an inquiry.
- On an existing website, behind a "Buy" button: the method is covered in payment button on a website.
The customer orders on the hosted page, then pays by card with 3-D Secure, or chooses cash and receives a reference to pay at an agency. For a service that is not a catalog product (a quote, a repair, an amount that changes every time), the right tool is the payment link: see creating a payment link.
Tracking your orders and their statuses
Every order placed on a product page appears in your portal with its status. Here are the four stages of its journey, and what they mean for your work.
| Status | What it means | What you do |
|---|---|---|
| Awaiting payment | The order exists, the payment is not confirmed | Nothing to prepare until the payment is confirmed |
| Paid | The payment is confirmed | Prepare the order; the amount is already in your payment account |
| Shipped | The order has left | Let the customer know, with your courier's tracking details |
| Delivered | The customer has received the order | Close it, and handle any return |
At "paid", the money is already there: as soon as a payment succeeds — a card authenticated with 3-D Secure or a reference paid in cash at an agency — the amount is available in your ChariPay payment account and usable right away. "Available instantly in the account" does not mean "instant bank transfer": the payout to your bank remains a separate operation.
If a customer returns a product paid by card, refund them from the portal or through the API, in full or partially: refunds are free, the amount is deducted from your available balance, and it is not instantaneous on the bank side.
Getting notified: order.paid and payment.succeeded
To react automatically to a paid order (decrement stock in your own tool, alert the workshop, send your own confirmation), register a webhook endpoint. Two events concern you:
- `order.paid` signals that an order from your store has been paid.
- `payment.succeeded`, the payment event that comes with it, carries your product's
metadata, echoed verbatim. So it is inpayment.succeeded, not inorder.paid, that you find your own identifiers, such as theskuin the example above.
Three receiving rules, common to all webhooks: verify the signature (X-CHARI-SIGNATURE, X-CHARI-TIMESTAMP) on the raw body; route on the Chari-Event-Type header; and deduplicate on Chari-Event-Id, not on Chari-Webhook-Id, which identifies the delivery, not the event.
The webhook does not replace reading: read a product's orders back with GET /v1/products/{reference}/orders for reconciliation or after your server has been unavailable. For an order paid in cash at an agency, do not build your processing on an event: follow the order's status in the portal, or read it back through the API.
Syncing an existing catalog through the API
Does your catalog live in a spreadsheet or management software? Make it the source, and let the hosted storefront mirror it.
- 1Create each product once, with
POST /v1/productsand oneexternalIdper product (your item reference). If the call is replayed, after a timeout or a rerun script, the API returns the existing product with200instead of creating a second one. - 2Update with `PATCH`, sending only what changes: a price, a stock level, a description.
- 3Deactivate instead of deleting:
DELETE /v1/products/{reference}deactivates the product, which can no longer be ordered.
A price and stock update looks like this:
curl -X PATCH 'https://api-psp.charipay.ma/v1/products/prod_2Bc9Zt' \
-H 'X-CHARI-PAY-API-KEY: chari_sk_test_...' \
-H 'Content-Type: application/json' \
-d '{
"price": 159.90,
"stockQuantity": 25
}'To list your products, page through the list (page starting at zero, size) up to totalPages. If you sync many products at once, respect the rate limits: a 429 RATE_LIMITED response tells you, through the Retry-After header, when to try again. Keep the externalId as the pivot between your tool and ChariPay: it is what makes every sync replayable without duplicates.
When to move to Shopify, WooCommerce or your own site
The hosted storefront is made for getting started and for short catalogs. Some needs signal that it is time for a more complete tool:
- A multi-product cart, because your customers rarely buy a single item.
- Delivery built into checkout, with shipping costs calculated from the address.
- A custom design, beyond one sales page per product.
- A domain name of your own, and a site that carries your brand end to end.
Shopify and WooCommerce meet those needs, and payment follows. There is no ChariPay extension for Shopify or WooCommerce: you send a payment link for each order, without a line of code, or connect the hosted checkout through the API for an automatic redirect. A custom site uses checkout sessions and webhooks. The overview of these setups is on our page about e-commerce payments in Morocco. And if you are at the very beginning, the full beginner's path is in starting an online store in Morocco.
Frequently asked questions
How do I create an online store with payment in Morocco without a developer?
With the hosted storefront: from the portal, you create each product with its price in dirhams and, if needed, its stock; each product gets a sales page you share on social media, by message or by email. The buyer orders there and pays by card or in cash at an agency, and you track orders in the portal. No code is needed.
What is a hosted storefront, in practice?
A storefront run by the platform: one sales page per product, with its price and optional stock, and order tracking in your portal (awaiting payment, paid, shipped, delivered). The buyer orders there and pays by card or in cash at an agency. You host nothing and build nothing. In exchange, it stays simple: no multi-product cart, no domain name of your own.
Can I manage my products' stock?
Yes, if you want to: stock is optional. Set a stock quantity when you create the product, from the portal or with stockQuantity in the API; with no stock set, the product stays on sale with no limit. You can update the quantity at any time, for example with PATCH from your management software, and the API distinguishes available and reserved quantities.
Which order statuses does the portal show?
Order tracking follows the order's journey: awaiting payment, paid, shipped, delivered. The "paid" status is your signal to prepare the order: the amount is then available in your payment account. "Shipped" and "delivered" help you follow what happens next and answer your customers' questions without digging through your messages or spreadsheets.
Does the hosted storefront handle delivery?
No. The hosted storefront publishes your products, collects payments and tracks orders; it does not handle delivery or carriers. You choose who delivers and when, ideally after the "paid" status. If you need delivery built into the checkout flow, that is a signal to move to Shopify, WooCommerce or a custom site.
How do I get notified of a new paid order?
In the portal, every order appears with its status. On the server side, register a webhook endpoint: order.paid signals the paid order, and the payment.succeeded that comes with it carries your product's metadata. Route on Chari-Event-Type, deduplicate on Chari-Event-Id, and read orders back when needed with GET /v1/products/{reference}/orders, especially after your server has been unavailable.
Can I import an existing catalog?
Yes, through the API: create each product with POST /v1/products and an externalId equal to your item reference, then update it with PATCH. If a creation is replayed, the API returns the existing product with 200 instead of duplicating it, so every sync stays replayable without duplicates. Deactivate withdrawn products with DELETE: they can no longer be ordered.
When should I move to Shopify or WooCommerce?
When your needs go beyond one sales page per product: a cart grouping several items, delivery built into checkout, a custom design or a domain name of your own. Payment follows with no extension: a payment link per order, with no code, or the hosted checkout connected through the API for an automatic redirect.
Next step
Publish two or three products in test mode, share a page with yourself and follow a mock order all the way to "paid": Start in test mode. Then prepare your move to production and, if your catalog lives elsewhere, set up the sync with the Products module of the API docs.
Written by ChariPay team.