Usage-based API
import { Access, Billing, Offer, Purchase } from "@byfungsi/sapa";import { Effect } from "effect";
export const meteredApi = Effect.gen(function* () { const access = yield* Access.entitlements({ entitlements: ["api.use"], duration: "purchased_period", }); const purchase = yield* Purchase.parse({ key: "api.metered.access", revision: 1, provides: [access], }); const billing = yield* Billing.meteredSubscription({ family: "api", interval: "month", meter: { key: "api.request", revision: 1 }, rate: { currency: "IDR", amount: 25n, perUnits: 10n, rounding: "trunc", }, accessPolicy: { key: "api.postpaid_access", revision: 1 }, }); return yield* Offer.parse({ key: "api.metered", revision: 1, purchase, billing, });});This charges IDR 25 per ten requests after period aggregation. For 99 accepted
units, the line amount is trunc(99 × 25 / 10) = 247 IDR.
Runtime installation
Section titled “Runtime installation”The composition root must install:
- meter
api.requestrevision 1; - merchant access policy
api.postpaid_accessrevision 1; - a provider for invoice checkout;
- storage supporting enrollment, usage, invoice, and payment history.
The access policy has an explicit grace period. Zero means immediate suspension when payment becomes overdue. Full refunds create debt at refund time; payment can reinstate access according to retained policy history.
Follow the complete operation order in metered billing.