Sell online courses in Morocco: get paid, then grant access after payment
Sell online courses in Morocco: one-off sales, limited-seat cohorts or monthly memberships, access granted on the webhook, and a clear refund policy.
To sell online courses in Morocco, you first pick a sales model, then tie access to proof of payment. For one-off sales — an e-book, a recorded course, a coaching session — a payment link or a product page is enough. For a cohort with limited seats, one single-use link per student, with a deadline if it is paid by card. For a monthly membership, a subscription: a payment link emailed at every due date. In all three cases, the customer pays in dirhams on a hosted page, and it is proof of payment — never the return to your website — that opens access. This guide walks through each model, how to grant access to the right student, and the refund policy.
Sell online courses in Morocco: three models, three tools
ChariPay is a Moroccan payment platform, a PSP operated by Chari Money, a payment institution licensed by Bank Al-Maghrib. It collects payments; it does not replace your course platform, your private group or your file delivery tool, and it is not wired into them out of the box. Your job is to connect the two: when the payment is secured, you open access. Everything is in Moroccan dirhams (MAD), with no conversion.
| Model | ChariPay tool | What triggers access |
|---|---|---|
| One-off sale: e-book, templates, recorded course, coaching session | Payment link, or a product page on the hosted storefront | Card payment: payment.succeeded (link) or order.paid (storefront) |
| Limited-seat cohort: bootcamp, online workshop, fall intake | One single-use link per student, with an expiry date if it is paid by card, or a product with stock | Card payment: payment.succeeded (link) or order.paid (storefront); cash on a link: the link turns "Paid" |
| Monthly membership: club, course library, ongoing coaching | Subscription: one payment link per due date, sent by email | subscription.payment_succeeded |
Two neighbors have their own guide. If you publish software sold by subscription, with access opened and cut automatically, read SaaS billing in Morocco. If you run a school, with families and a school year, read school fees online. This guide is for the trainer, coach or creator who sells their know-how online.
Sell digital products one at a time: link or product page
For a product sold one at a time, there are two tools.
The payment link. A payment link is an amount and a description; the customer pays on a page hosted by ChariPay. It is shared as a link, a QR code, a printable PDF poster, by email or WhatsApp. From the portal, every payment link you create is single-use: one link per buyer, at the course price. The reusable link — one amount paid by several customers, the kind you put in a bio, a newsletter or a students' group — is created through the API, with singleUse: false; once created, it shows up in the portal like the others. A link carries a fixed amount: for a launch price or a student rate, create a separate link.
One limit to know: a link's payment event returns the link's metadata; with a reusable link, it is therefore the same for every buyer — it tells you what was sold, not to whom. To tie each payment to a specific student — which matters as soon as access is personal — one single-use link per student, created with their details, remains the safest option.
The product page on the hosted storefront. No website yet? Publish your products on your hosted storefront and track your orders — awaiting payment, paid, shipped, delivered — from your portal. Each course becomes a product with its price and sales page, and each purchase an order you track. It is the no-developer way to sell a course several times at the same price: share the link to its page. The step-by-step is in hosted storefront.
In both cases, neither the link nor the storefront delivers your course: you send the access yourself, once the payment is confirmed.
Try it with your first course before putting it on sale: 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 create your own test key. Create the link for your course and pay it with the test card, the way a student would: no real money moves.
Limited-seat cohort: one link per student, one deadline
A cohort has two constraints: a number of seats and a closing date. The single-use payment link handles both. A link is single-use or reusable, with an expiry of your choice — 24 hours, 7 days, 30 days, never, or an exact date — and a clear status: active, paid, canceled, expired.
The method:
- 1One single-use link per student, at the course price, with their name in the description.
- 2An expiry on an exact date for a link paid by card, the day before the start, for instance, or the deadline you announced.
- 3As many links as seats: you set the cap yourself, by not creating one link more.
- 4A waiting list: when a link expires unpaid, the seat goes to the next person, with a new link.
Another option if you sell through the hosted storefront: a product with optional stock, set to the number of seats, and the list of paid orders in the portal.
The single-use link has one last advantage for a cohort: on its page, the student can also pay in cash at an agency. They choose cash, receive a reference, pay it at an agency of the Chari network, and you are notified as soon as the network confirms the deposit. A checkout session created through the API, by contrast, only takes cards.
One setting matters here. In the portal, turning on "Agency payment" on a link disables its expiry: the link stays payable with no time limit. A link with an expiry date is therefore presented as a link to be paid by card; for a student who pays in cash, create a link with "Agency payment", without an expiry. The other settings are described on the payment links page.
Monthly membership: a payment link at every due date
A training club, a course library refreshed every month, monthly coaching: that is a subscription. On every due date, ChariPay generates a single-use payment link and emails it to your student, who pays it by card on the hosted payment page, with 3-D Secure. The first payment activates the subscription.
What the student experiences, and what you manage:
- A link at every due date: they receive a payment link for the period by email, with the subscription's description; no link is sent before the first due date you chose.
- Reminders while the installment is unpaid: a reminder goes out by email every day, with the same link, and no new period opens; the link stays payable for 14 days after the due date.
- A clean ending: if the link expires unpaid, the subscription is canceled automatically;
subscription.canceledsignals that automatic cancellation, and it is when it arrives that you cut access, not before. When you cancel yourself — from the portal or through the API — do not wait for an event: the response toPOST /v1/subscriptions/{reference}/cancelalready carries theCANCELEDstatus; update your system at that point. Once it reaches its end date, the subscription becomes "completed". - Readable statuses: not yet started, active, paused, completed, canceled; pause, resume and cancel from the portal or through the API.
The full mechanics — schedule, reminders, pause, cancellation — are described in subscriptions and recurring payments; what happens when an installment stays unpaid is covered in unpaid subscription installments. Keep the essential point for a course: access follows the subscription's status, and your system is what enforces it.
Grant access after payment, never before the event
The rule of every online sale applies twice over to a digital product, which can be copied and shared. Confirm the order when the webhook arrives, never on the redirect alone: the redirect says the buyer came back, not that the payment is secured. A student who lands back on your "thank you" page has not necessarily paid; send nothing before the event.
| Model | The event that opens access |
|---|---|
| Payment link or session, paid by card | payment.succeeded |
| Hosted storefront order, paid by card | order.paid |
| Subscription due date | subscription.payment_succeeded |
| Single-use link paid in cash | The link turns "Paid": notification in the portal; on the server side, GET /v1/payment-links/{reference} |
Without a developer, the method still works: you are notified in the portal when the payment comes in, and you send the access by hand — the group invitation, the download link, the platform credentials. With a developer, your server receives the event, verifies its signature and opens access on its own. The five mistakes that derail this step — signature, duplicates, heavy work inside the request — are covered in getting your webhook integration right.
Grant access to the right student
A payment event is useless if you do not know whom it belongs to. The tool is metadata: a flat object — strings, numbers, booleans, no nested object or array, 4 KB at most — that you send when creating the link or session, and that comes back verbatim in the payment event. Put in it what your system needs to open the right access: courseId, cohort, your student identifier.
Three rules prevent bad surprises:
- Find your order through your `metadata`, echoed verbatim in the event; for a session, the event also carries your `orderId`. The
externalIdof a session or a link does not come back in the event: it exists so you never create the same resource twice. - For the hosted storefront, the product's
metadatacomes back in the companionpayment.succeeded, not inorder.paid: listen to both. - No sensitive data in `metadata`: an identifier is enough, never a password or an ID card number.
The full table of identifiers — who creates them, where they come back — is in matching a payment to its order.
Refund policy for an online course
A digital product raises a question a pair of shoes does not: once the course has been viewed, what do you give back? The answer is yours, but it must be written before the sale, on your page or in the message that comes with the link. A clear policy separates at least two moments: before the start (or before first access) and after access.
For a card payment, the move is always the same: refund a customer, in full or partially, from the portal or through the API. Refunds are free; the amount is deducted from your available balance, and if the balance is not enough, the operation is blocked rather than creating an overdraft. A refund is not instantaneous on the bank side: let the student know without promising a date. And cut access when you refund, not before and not weeks later.
For invoicing and the tax treatment of your courses, only your advisor can give an opinion. The refund how-to — API call, tracking, customer message — is in refunding a customer, and the big picture of selling online in the guide to e-commerce payments in Morocco.
Frequently asked questions
How do I collect payment for an online course without a website?
With one single-use payment link per student, created from the portal and shared by WhatsApp, email or QR code: the customer pays on a page hosted by ChariPay, and you are notified in the portal when the payment comes in. To sell the same course several times at the same price, or a whole catalog, the hosted storefront gives you a sales page per product and order tracking, still with no website to build.
How do I grant access automatically after payment?
By connecting your server to the card payment event: payment.succeeded for a link or session, order.paid for the hosted storefront, subscription.payment_succeeded for a membership. Your server verifies the signature, reads your metadata to identify the student and the course, then opens access. Never on the redirect: it says the buyer came back, not that they paid.
Can I sell a course as a monthly subscription?
Yes, with a subscription. On every due date, the student receives a payment link by email and pays it by card on the hosted page, with 3-D Secure; until they pay, a reminder goes out every day, and if the link is still unpaid 14 days after the due date, the subscription is canceled automatically. Open access on each subscription.payment_succeeded and cut it on subscription.canceled; if you cancel yourself, from the portal or through the API, cut it right away, without waiting for an event.
How do I limit the number of seats in a cohort?
By creating exactly as many single-use links as seats, one per student, with an expiry on the closing date for those who pay by card. A link that expires unpaid frees the seat for the next person. If you sell through the hosted storefront, set the product's optional stock to the number of seats and track the paid orders in the portal.
Can a student pay for a course in cash?
Yes, with a single-use payment link, created in the portal with "Agency payment" and therefore without an expiry: on its page, the student chooses cash, receives a reference and pays it at an agency of the Chari network. As soon as the network confirms the deposit, the link turns "Paid" and you are notified in the portal. A checkout session created through the API or a reusable link only take cards.
How do I refund a student who cancels their enrollment?
If they paid by card, according to the policy you wrote before the sale, in full or partially, from the portal or through the API. Refunds are free, the amount is deducted from your available balance, and a refund is not instantaneous on the bank side. Cut access at the moment of the refund. If the student had not paid yet, simply cancel their link: a canceled link can no longer be paid.
Which currency should I sell my online courses in?
In Moroccan dirhams: everything is in MAD — collections, balances, transfers and payouts — with no conversion. API amounts are in major units (149.90 = MAD 149.90). So show your prices in dirhams on your sales page, so that the amount the student reads is exactly the one they will find on the payment page.
Next step
Pick your model (one-off, cohort or membership), then create in test mode the link, product or subscription that matches it: Start in test mode. Then tie access to the payment event by following getting your webhook integration right, and prepare your catalog with the hosted storefront.
Written by ChariPay team.