Skip to content

How Trile works

This page walks the whole flow once, so the rest of the docs have a shared map.

Product ──has many──> Price ──referenced by──> Subscription ──generates──> Invoice
Customer ──owns──> Wallet ──funds──────────────────-┘ (deducted each cycle)
  • Product — the thing you sell (e.g. “Pro plan”).
  • Price — a recurring amount + interval on a product (e.g. NPR 499 / month).
  • Customer — who you bill.
  • Wallet — the customer’s prepaid balance. Funded via eSewa, Khalti, bank transfer, IME Pay.
  • Subscription — a customer committed to a price. Drives billing.
  • Invoice — a statement generated each cycle and paid from the wallet.

See Object IDs for the full prefix list.

  1. Set up your catalog. Create a product and a recurring price.
  2. A customer subscribes. Either you call the API directly, or you send them to a hosted checkout session where they top up and authorize.
  3. The first cycle charges immediately (unless the price has a trial). The amount is deducted from the customer’s wallet. If the wallet is short, creation fails with insufficient_funds.
  4. Each renewal, the billing engine deducts the next cycle from the wallet and generates an invoice. On success the invoice is paid; on a short wallet the subscription goes past_due.
  5. Your system stays in sync via webhooks (subscription.created, invoice.paid, invoice.payment_failed, …) and the event log.

The billing engine doesn’t run inside the HTTP request. Trile runs three process roles:

ProcessResponsibility
apiServes the /v1 HTTP API — what your integration talks to. Enqueues jobs, never blocks on them.
schedulerFires the daily billing tick, reconciliation, and idempotency-key cleanup.
workerExecutes billing charges, webhook deliveries, and reconciliation jobs from the queue.

You only ever talk to api. The async split is why webhook delivery and renewals are eventually-consistent — design your integration to be webhook- and event-driven, not synchronous-only.

Go build it: Quickstart.