Appearance
Plans
Plans are what customers buy. Each plan = price + billing interval + a limits block + an allowed-model list. Prices are in BDT (stored as poisha, 1/100 BDT).
Anatomy of a plan
| Field | Example | Meaning |
|---|---|---|
| Slug / Name | pro-monthly / "Pro" | Identity shown at checkout |
| Interval | DAILY · WEEKLY · MONTHLY · YEARLY · ENTERPRISE | Billing cycle |
| Price | 99900 poisha = ৳999 | Charged through whichever channels are enabled — see Payment channels |
| Limits JSON | see below | tokenLimit is what the plan grants each cycle |
| Allowed models | list of model ids | What the tier can use |
json
{
"tokenLimit": 21169200,
"concurrentJobs": 4,
"apiAccess": true,
"priorityLevel": 3
}tokenLimit is the plan's token allowance per cycle, added to the customer's wallet on activation and each renewal. Tokens are spent on any model the plan lists, at that model's provider cost. (monthlyRequests, imageCredits and videoCredits may still appear on older plans; the token wallet ignores them.)
Cost, margin & the economics panel
The Plans page shows, per plan, a live cost-to-serve breakdown next to the price:
Net margin = price − provider cost − gateway − VATProvider cost = the plan's tokens valued at the token value from Credit pricing (default ৳18 per 1M), which is exactly what those tokens cost when spent. Gateway and VAT are the credit pricing percentages. The seeded packages clear 40% at full use.
Use Recommend (40%) in the plan editor to back-solve the token allowance for a 40% net margin from the price. The Top-up builder simulator shows what a top-up costs at a token value you are trying, before you save it.
Creating a tier
Plans → New plan → set the price and token allowance (the live margin updates as you type) → Create. It appears at checkout ordered by sortOrder. Archive (trash icon) hides a plan from new purchases — existing subscribers keep it until expiry.
Current packages
Subscription-only. Defined in src/modules/plans/plan-catalog.ts and installed with npm run plans:apply (add -- --dry-run first) — that upserts these and permanently deletes every other plan (including ones made in the admin). Top-ups are not affected. Live subscribers on a deleted plan move to pay-as-you-go; their payments, ledger and usage history are kept. npm run seed installs the same list.
| Package | Slug | Price | Tokens per cycle |
|---|---|---|---|
| Free Trial | free-trial | Free, 7 days, once | 1,000,000 |
| Basic | basic-weekly | ৳99 / week | 1,008,240 |
| Beginner | beginner-monthly | ৳499 / month | 10,079,920 |
| Creator (popular) | creator-monthly | ৳999 / month | 21,169,200 |
| Pro | pro-monthly-v2 | ৳1,999 / month | 43,343,520 |
Tokens land in the one wallet and are spent on any listed model at its provider cost — see Credits, tokens & top-ups for the pricing and margins.
Free Trial (free-trial) is the minimum package, at ৳0: every new account gets it once, automatically — 7 days, 1,000,000 tokens, on Nano Banana 2 Lite, Qwen Audio 3.0 TTS Flash and Gemma 4 31B (no video). When the 7 days end it simply expires: it doesn't renew, it can't be bought at checkout, it can't be switched or scheduled to, and it can't be claimed again. Leftover tokens stay in the wallet.
There is no pay-as-you-go plan. A customer without a package can still generate: they spend tokens (leftover or topped up) on any available model.
Each plan carries its storefront card as data in features: tagline, badge (POPULAR on Creator), cta, the five includes lines (the last is the token allowance), and modelAccess — the Image / Video / Audio / Text groups with each model named exactly as the package names it. Where a package names a model that is not offered, the entry's slug is the model that serves it and note says so (Gemma 4 12B and 27B → Gemma 4 31B, Gemini 3.1 Flash → Gemini 3.5 Flash, Qwen Audio 3.0 TTS Flash / Plus → Qwen3 TTS Flash / Instruct Flash). The Plans page shows the full card with its unit economics.
Which models a package includes is decided by price (features.modelRule: "price"). A package includes:
- the models it is sold with (
features.modelSlugs, the names on its card), whatever they cost, and - every model on sale that its own token allowance can pay for a sensible amount of:
| Kind | The package's tokens must buy at least |
|---|---|
| Image | 4 images |
| Video | 3 five-second clips (or 3 videos) |
| Audio | 3 minutes, 2 generations, or 3,000 characters |
| Text | 200,000 characters |
So a bigger package unlocks pricier models by itself. When a model is switched on or priced, it joins every package that can afford it within 15 minutes (the registry cron); npm run plans:apply recalculates at once. The rule lives in src/modules/plans/price-tier.ts.
On the pricing page each kind lists every model the package includes, under a count — the ones the package is sold with first, then the priciest. A model whose provider is switched off is not shown and unlocks when the provider does.
Top-ups
One-off buying is a top-up the customer builds — so many credits (and, if switched on, images or videos) — priced by the top-up rules and tested on the Monetization → Top-up builder playground. See Credits, tokens & top-ups.
Building a reseller package
A "reseller package" is a plan tailored to a partner who resells access under their own brand:
- Create a dedicated plan — e.g.
partner-acme-monthly, interval MONTHLY, negotiated price, generous limits,apiAccess: true(the reseller integrates via API keys). - Restrict the model list to what the deal covers (only cheap image models, for example).
- Grant it manually — Users → the partner's account → Grant plan → pick the plan + duration. No card required. Repeat on renewal or script it via
POST /v1/admin/users/:id/grant-subscription. - Enterprise teams — create a Workspace for the partner, invite their staff; attach the subscription to the workspace so all members share the pool.
- Watch consumption — Analytics → top users; per-user detail shows recent usage.
For carrier-billed consumer packages (Bangladesh DCB via Hullor): create a BDT plan, and the checkout flow handles carrier consent SMS. Amounts must match a plan configured on the Hullor side (keyword + amount pair).
Changing plan
Customers move between plans from your storefront, and the direction decides what happens:
- Upgrading takes effect immediately and is prorated — the unused remainder of the plan they are on comes off the new plan's price, so they are not billed twice for days they already paid for. A customer a full month into an unused ৳999 Pro cycle moving to the ৳9,999 yearly plan pays ৳9,000.01.
- Downgrading (or moving sideways to an equally-priced plan) is bought now and applied later. The customer pays the new plan's full price, keeps the tier they already paid for until its cycle ends, and the cheaper plan starts then. It is not prorated — the payment buys the next cycle, not the rest of this one — and nothing is refunded. Moving to the free plan is the one change with nothing to pay, so it simply schedules.
Either way unused credits carry over. The wallet is append-only, so whatever is left is still there and the new plan's allowance is added on top.
The payment record keeps both the list price and the discount, so support can always answer "why was I charged this" from the Payments page rather than from a log.
Renewal and what happens when a plan lapses
Only carrier billing (DCB) renews itself — the carrier deducts each cycle and reports it back. Card and wallet channels store nothing reusable, so those customers have to buy the next cycle themselves. The system reflects that:
- 3 days and 1 day before the cycle ends, the customer is emailed. A carrier-billed customer is told it renews automatically and to do nothing; a card or wallet customer is told it ends and given a link to renew. Sending both the same message either invites a double payment or loses a customer who meant to stay.
- At the cycle end, a plan that has not been paid for enters a 3-day grace period — and access continues through it. For a carrier-billed customer this is the cushion for a rebill that lands late; for everyone else it is time to renew. No new allowance is granted; they are spending down what is left.
- If grace ends unpaid, the plan expires. The account does not lose its wallet: leftover tokens, including top-ups the customer paid cash for, stay spendable on any available model without a package.
Payment channels
Settings → Payment channels controls what customers can pay with. Disabling a channel takes effect immediately — checkout refuses it, so this stops payments through a gateway that is having a bad day rather than just hiding the button.
A channel can also be blocked: switched on, but missing the server configuration it needs. Customers are not shown it, and the page names the missing setting. This is worth watching after a deploy — a gateway can be enabled and still be incapable of taking a payment.
| Channel | Renews itself | Notes |
|---|---|---|
| Cards & Mobile Banking (SSLCommerz) | No | Visa, Mastercard, bKash, Nagad, Rocket, internet banking |
| bKash | No | Direct from the customer's bKash wallet |
| Mobile Carrier Billing (DCB) | Yes | Charged to the mobile balance; amounts must match a plan configured on the Hullor side (keyword + amount pair) |
Stripe, PayPal and Nagad-direct are not live channels for this product.
Promotions
Coupons → New coupon. A code is either percent-off or a fixed amount — never both — and can carry any of:
| Setting | What it does |
|---|---|
| Max discount | Ceiling on a percentage code — "50% off, up to ৳500". Without it, a percentage aimed at the monthly plan gives away twelve times as much on the yearly one |
| Minimum order | Floor on the purchase it may be used against |
| Applies to | Subscription plans — and can be narrowed to specific plans. ("Credit packs" is a legacy option: top-ups take no codes; use a promotion on the Top-up builder instead) |
| Valid from / until | The window it works in |
| Max redemptions | Total uses across the campaign |
| Max per customer | Uses by any one customer — a campaign can allow 1,000 uses but only one each |
Codes are entered at a plan checkout. Top-ups don't take codes — their discounts and bonuses are top-up promotion rules, applied automatically under the profit floor. A code is spent only when the payment succeeds, so an abandoned checkout does not consume a use. A code that covers the whole price is fulfilled straight away with no gateway step.
The coupon list shows how many times each code has been used and how much discount it has given away, plus whether it is live right now — which is the quickest way to answer "why is my code not working" without reading the rules back one at a time. The detail view lists who redeemed it and what each redemption cost.
Ad-hoc credits
For goodwill / sales trials: Users → user → Grant credits (text requests, tokens, image credits, video credits — with an internal note). Instant, no payment involved.