A subscription takes its plan whole: one item per charge, all billed on one invoice, each line naming its charge. This guide builds that catalog through the API, subscribes a customer, and moves them to Growth.
Every request sends
Authorization: Bearer sk_test_… and, for POST and PATCH, an Idempotency-Key. Amounts are in major units (3.5 is ₦3.50). Usage prices need metered billing turned on for your account.
Build the catalog
1
Create a meter for each kind of usage
A meter counts one kind of event. Your app reports events by Do the same for SMS:
eventName.{"name": "SMS sent", "eventName": "sms.sent", "aggregation": "count", "unitLabel": "SMS"}. Keep both ids (mtr_…).2
Create the product and the plan
POST /products and {"name": "Verifi API"}. A new plan starts with one unnamed charge, listed in charges.3
Add a charge for each kind of usage
Adding a second charge names the first one too:Then give the first charge its code with
PATCH /charges/chg_… and {"code": "bvn"}. A code is how a fixed charge is recognised on another plan. Usage charges are matched by their meter.4
Price each charge
One price per charge in each way to pay (currency and billing interval):The SMS price is the same with the SMS charge, the SMS meter and
"unitAmount": 3.5.5
Build Growth the same way
Growth has three charges: a platform fee (code Its BVN and SMS prices use the same meters as Pay as you go, at 40 and 3.
platform), BVN (bvn) and SMS (sms). Its fee is an ordinary price with no meter:GET /plans/{id} lists the plan’s charges and its waysToPay. A way to pay is available when every active charge has exactly one price for it. Otherwise problems says what is missing, such as “SMS has no price for NGN, every year.” The dashboard shows the same on the product page.
Subscribe a customer
Name the plan and the way to pay. Every charge comes with it:items[].priceIdwith any one of the plan’s prices works too: that price names the plan and the way to pay.- Set quantities per fixed charge with
"quantities": {"seats": 10}, by charge code or id. A charge left out starts at its price’s fewest, else 1. - A plan with nothing billed up front, such as Pay as you go, has nothing to charge today, so it starts active. If a card is required at signup (your team’s setting, or
"requirePaymentMethod": true), the customer first saves a card through a small charge that is refunded automatically, and the subscription starts once it settles.
POST /meter-events as it happens. At the end of each month the invoice bills each charge’s usage on its own line, at its own price.
A customer’s usage on a meter is billed by every subscription of theirs that has that meter, because events carry no subscription. So Bouclay refuses a second subscription, plan change or price swap that would put the same meter on two of one customer’s subscriptions. The API answers
422 with meter_billed_elsewhere, naming the other subscription. Put every charge on one subscription instead.Change plans
Preview first. The preview runs the same decision and pricing as the change:data.change lists the charges that carry on, end and start. Moving from Pay as you go to Growth, BVN and SMS carry on onto Growth’s prices and the platform fee starts. Make the change with the same body at POST /subscriptions/{id}/plan-change.
How charges are matched:
- A usage charge carries on onto the new plan’s charge on the same meter.
- A fixed charge carries on onto the one with the same code. When each plan has one fixed charge left, those two pair, so Basic to Pro is a price change of the same item.
- Old charges with no match end, and their usage so far bills on the next invoice. New ones start.
- When the fixed fees cost the same or more, the change happens now. The rest of the period is billed on one invoice.
- When they cost less, it waits for the next renewal and is applied before that renewal bills. Send
"timing": "now"to make it now: the unused time on the old fees is credited by credit note. - A new billing interval, or a charge moving between billing at the start and at the end of the period, always waits for the renewal.
- While trialing, the change happens now and bills nothing.
Discounts on a usage plan
A discount takes off every line by default. To take a launch promo off the platform fee only, so it costs a known amount however much the customer uses, set What it takes off to Fixed fees only, not usage when you create the discount. The API’s discount object shows it ascovers: "fixed_fees".
A plan change checks the discount again. One the new plan doesn’t qualify for, such as “20% off Growth” after a move to Pay as you go, stops applying to future invoices. Invoices already issued keep theirs.
Add a charge later
A charge added to a plan, such as NIN checks on Pay as you go, applies to new subscribers. To give it to current ones, use Add to current subscribers in the plan’s charges drawer, orPOST /charges/{id}/add-to-subscribers. Each subscriber gets it at their next renewal, or at once while trialing or paused. The response lists anyone left out and why, such as a subscriber whose way to pay has no price for the new charge.
To stop a charge for current subscribers, archive it, then use End for current subscribers or POST /charges/{id}/end-for-subscribers.
Payment links on a plan
A payment link on any price of a plan made of several charges sells the whole plan in that price’s way to pay. The buyer pays the fees billed up front, and the hosted page lists what is billed later: “Plus BVN at NGN 40.00 per lookup and SMS at NGN 3.00 per SMS, billed at the end of each month.” On a plan with nothing billed up front, the checkout is the refunded card check.Moving off one plan per meter
Before plans could hold several charges, the way to sell two kinds of usage was one plan per meter: a “BVN lookups” plan as the subscription’s plan, and an “SMS” plan beside it as an add-on. To move such a subscription onto one plan:- Create one plan with a charge per meter, at the same rates.
- Change each subscription to it with
"timing": "next_renewal". BVN carries on by its meter. The SMS add-on ends at that renewal, and the new plan’s SMS starts at the same moment, so every message is billed once. - If the subscription has a discount limited to the old plans, replace it with one for the new plan.
- Archive the old plans. Don’t retire the old SMS plan: a retirement looks for one successor price, finds two usage prices, and pauses the subscription instead.