Recurring revenue, on Djiboutian rails.
The MerasPay Billing surface ships eight composable resources — Product, Price, Customer, Invoice, Subscription, Coupon, TaxRate, CreditNote — so your SaaS, your subscription service, or your installment plan runs the same way it would in Europe or North America. Renewals charge against mobile wallets and bank accounts; everything else just works.
At a glance
- Resources
- 8
- Renewal intervals
- D · W · M · Q · Y
- Currencies
- DJF · USD · ETB · EUR
- Pricing models
- Flat · Tiered · Per-unit
Eight resources, one commerce surface
The full set, with the responsibilities you expect. Each is a separately addressable REST resource with list / get / create / update / delete where applicable.
Products
Catalogue items with descriptions, images, metadata. The thing your customer is paying for, decoupled from how you price it.
Prices
One-time or recurring (daily, weekly, monthly, quarterly, yearly). Tiered, graduated, package, or per-unit. Multi-currency on a single product.
Customers
Long-lived recipient records with default payment_method, billing address, tax exemption, and metadata. Re-used across charges.
Invoices
Draft, finalised, paid, uncollectible, void. Auto-generated for subscription renewals or manually composed for one-off bills.
Subscriptions
Customer + Price = recurring revenue. Trial periods, proration on plan changes, cancel-at-period-end, and grace-period dunning.
Coupons & promotions
Percentage or fixed amount, with redemption limits, expiry, and scoping to specific products or customer cohorts.
Tax rates
Inclusive or exclusive, per-jurisdiction, per-product. The tax row is computed on the invoice so the audit trail is bulletproof.
Credit notes
When a refund happens for an invoiced charge, a matching credit_note posts so revenue recognition reconciles cleanly with your accounting system.
Why teams pick MerasPay Billing over a generic processor
Familiar resource model
Product, Price, Customer, Invoice, Subscription, Coupon, TaxRate — separated, composable resources that map cleanly to the lifecycle of recurring revenue. The OpenAPI 3.1 spec is the source of truth.
Built on Djiboutian rails
Subscription renewals charge against mobile wallets and bank accounts using the same Direct Payment engine. Card-not-present subs land once Cybersource CNP is live.
Local-currency-first
DJF is a first-class currency throughout. So is ETB. So is USD for cross-border SaaS. Multi-currency prices on a single product, displayed correctly on every invoice.
Dunning that respects the rails
Retry windows align with rail-specific reasons: insufficient_funds retries a day later, otp_expired retries immediately, frozen_account stops trying and pings the merchant.
Start a subscription in four steps
- 1
Define a product and a recurring price
POST /v1/products, then POST /v1/prices with a recurring spec. The price can target any currency you intend to bill in.
- 2
Create a customer and attach a payment method
POST /v1/customers, then POST /v1/payment_methods/.../attach. We tokenise the underlying wallet or bank reference per-merchant.
- 3
Start the subscription
POST /v1/subscriptions with customer + price + optional trial_period_days. The first invoice is auto-generated and the first charge fires (or waits for trial end).
- 4
Renewals are automatic
Every period close, an invoice is finalised and charged against the default payment method. invoice.payment_succeeded fires on each successful collection.
In code
A complete subscription bootstrap: product, price, customer, payment method, subscription — with a 30-day free trial.
# Set up a 30-day-free / 1,500 DJF-per-month SaaS subscription.
# 1. Product.
$ curl -X POST https://api.meraspay.io/v1/products \
-u sk_live_xxx: \
-d name="MerasShop Pro" \
-d description="Pro tier — analytics, exports, priority support."
{ "id": "prod_01HZ...", "name": "MerasShop Pro", ... }
# 2. Recurring price.
$ curl -X POST https://api.meraspay.io/v1/prices \
-u sk_live_xxx: \
-d product=prod_01HZ... \
-d "recurring[interval]=month" \
-d unit_amount=150000 \
-d currency=DJF
{ "id": "price_01HZ...", "unit_amount": 150000, "currency": "DJF",
"recurring": { "interval": "month", "interval_count": 1 }, ... }
# 3. Customer + attached payment method (a Waafipay wallet).
$ curl -X POST https://api.meraspay.io/v1/customers \
-u sk_live_xxx: \
-d email=halima@example.dj -d "phone=+25377101010"
{ "id": "cus_01HZ...", ... }
$ curl -X POST https://api.meraspay.io/v1/payment_methods \
-u sk_live_xxx: \
-d type=wallet -d "wallet[provider]=waafi" \
-d "wallet[msisdn]=+25377101010" -d customer=cus_01HZ...
{ "id": "pm_01HZ...", ... }
# 4. Subscribe.
$ curl -X POST https://api.meraspay.io/v1/subscriptions \
-u sk_live_xxx: \
-d customer=cus_01HZ... -d "items[0][price]=price_01HZ..." \
-d trial_period_days=30
{ "id": "sub_01HZ...", "status": "trialing",
"trial_end": "2026-06-23T...", "current_period_end": "2026-06-23T...", ... }Frequently asked
Can I migrate subscriptions from another platform?▾
Yes. We provide a migration tool that imports customers, payment methods, subscriptions, and invoices from a CSV or JSON export, preserving period anchors and proration history.
What rails can I bill subscriptions on?▾
Any rail the Direct Payment engine supports. In practice, mobile wallets (Waafipay, D-Money, SabaPay) and bank pulls (CAC, EAB) for DJF subs; cards via Cybersource CNP once that adapter ships.
How does proration work?▾
Prorated by default on plan changes — credit for the unused portion of the old plan, charge for the prorated portion of the new plan, surfaced on the next invoice. Disable with proration_behavior=none.
What about dunning?▾
Configurable retry schedule per merchant: typically 1, 3, and 7 days after the first failure. After the final retry, the subscription moves to past_due or unpaid based on your policy.
Do you handle invoice PDFs?▾
Yes. Every finalised invoice gets a signed PDF available at invoice.invoice_pdf. The PDF respects your merchant branding, language, and tax format.
Ready to integrate?
Get a sandbox account in minutes. Production goes live after a brief KYB review.