The entitlement engine that translates subscriptions into feature access.
An open-source TypeScript entitlement library for plan-based feature access, limits, subscriptions, customer overrides, and optional Stripe event processing.
See the Subscrio hub README for concepts, architecture, and feature resolution.
- Feature entitlements: toggles, numeric limits, text values, and customer overrides
- Plans and billing cycles: model packages and subscription timing without processing payments
- Subscription lifecycle: trials, renewals, cancellations, and effective access dates
- Stripe integration: process supported, verified Stripe subscription events
- PostgreSQL: Drizzle ORM with a published type-safe npm package. Schema install/drop/migrate SQL is also generated for SQL Server; the TypeScript query runtime is PostgreSQL.
- Hooks: before/after events for customers, subscriptions, and inbound Stripe payloads
- Config sync: file or JSON catalog sync for products, features, plans, and billing cycles
npm install subscrioPrerequisites
- A TypeScript or JavaScript application
- PostgreSQL (create an empty database first; Subscrio installs schema inside it)
Set DATABASE_URL, then construct Subscrio and run the schema installer once.
loadConfig() reads environment variables into a SubscrioConfig object. The only required value is DATABASE_URL (the PostgreSQL connection string). Pass that object to new Subscrio(config). You can also build SubscrioConfig in code instead of using loadConfig(). See Configuration and the core overview for the full object.
import { Subscrio, loadConfig } from 'subscrio';
const config = loadConfig();
const subscrio = new Subscrio(config);
await subscrio.installSchema('your-admin-passphrase');
const product = await subscrio.products.createProduct({
key: 'my-saas',
displayName: 'My SaaS Product'
});
const feature = await subscrio.features.createFeature({
key: 'max-users',
displayName: 'Maximum Users',
valueType: 'numeric',
defaultValue: '10'
});
await subscrio.products.associateFeature(product.key, feature.key);
const plan = await subscrio.plans.createPlan({
productKey: product.key,
key: 'pro-plan',
displayName: 'Pro Plan'
});
await subscrio.plans.setFeatureValue(plan.key, feature.key, '100');
const billingCycle = await subscrio.billingCycles.createBillingCycle({
planKey: plan.key,
key: 'monthly',
displayName: 'Monthly',
durationValue: 1,
durationUnit: 'months'
});
const customer = await subscrio.customers.createCustomer({
key: 'customer-123',
displayName: 'Acme Corp'
});
await subscrio.subscriptions.createSubscription({
key: 'sub-001',
customerKey: customer.key,
billingCycleKey: billingCycle.key
});
const maxUsers = await subscrio.featureChecker.getValueForCustomer(
customer.key,
product.key,
'max-users'
);Public APIs use string keys, not internal IDs. DTOs and types are exported from subscrio.
SubscrioConfig is the object passed to new Subscrio(config). Only database.connectionString is required. Everything else is optional: SSL, pool size, Stripe, logging, hooks, and initial catalog sync.
loadConfig() fills that object from environment variables:
| Variable | Required | Description |
|---|---|---|
DATABASE_URL |
Yes | PostgreSQL connection string |
DATABASE_SSL |
No | true to enable SSL |
DATABASE_POOL_SIZE |
No | Connection pool size (default: driver preset) |
STRIPE_SECRET_KEY |
No | Stripe secret key for billing helpers |
STRIPE_WEBHOOK_SECRET |
No | Stripe webhook endpoint secret (whsec_...) for constructStripeEvent |
ADMIN_PASSPHRASE |
No | Default admin passphrase for schema install and drop |
LOG_LEVEL |
No | debug, info, warn, or error |
Connection string example: postgresql://postgres:password@localhost:5432/subscrio
To define products, features, plans, and billing cycles in JSON and apply them with configSync or initialConfig, see configuration sync.
The full SubscrioConfig shape is in the core overview.
- Create an empty PostgreSQL database.
- Point Subscrio at it with
DATABASE_URLorSubscrioConfig.database. - On first run, call
installSchema(adminPassphrase). - After upgrading the package, call
migrate().
const version = await subscrio.verifySchema();
if (version == null) {
await subscrio.installSchema('your-admin-passphrase');
}
await subscrio.migrate();Other instance methods: dropSchema(adminPassphrase) (destructive; tests/dev only — the passphrase is required when a hash was stored at install), runInitialConfigSync() (when SubscrioConfig.initialConfig is set), and close().
Stripe support is optional. You only need it if you want Subscrio to apply verified Stripe subscription events to local customers and subscriptions. You can create and manage subscriptions through the API without Stripe.
Subscrio does not charge cards. Verify webhook signatures in your app (or via constructStripeEvent when stripe.webhookSecret is set), then pass events to processStripeEvent. Create subscriptions through Checkout or your own Stripe API calls, not a placeholder create helper.
const event = subscrio.stripe.constructStripeEvent(rawBody, signatureHeader);
await subscrio.stripe.processStripeEvent(event);
const { url } = await subscrio.stripe.createCheckoutSession({
customerKey: customer.key,
billingCycleKey: billingCycle.key,
successUrl: 'https://example.com/success',
cancelUrl: 'https://example.com/cancel'
});See Stripe integration and the hub overview.
Full API reference, hooks, and extension guides live on docs.subscrio.com:
Services on Subscrio: products, features, plans, billingCycles, customers, subscriptions, featureChecker, stripe, configSync, hooks.
Handle ValidationError, NotFoundError, ConflictError, DomainError, and ConfigurationError from subscrio.
From this repository root:
npm install
npm run typecheck
npm run build
npm testnpm test runs tests against PostgreSQL. Set TEST_DATABASE_URL or configure .env (see tests/README.md). Extension packages (subscrio-audit-log, subscrio-payments) live in subscrio-extensions-audit-log and subscrio-extensions-payments.
MIT. See LICENSE.
Issues and pull requests welcome in this repo. See CONTRIBUTING.md. Org-wide guidelines: CONTRIBUTING.
- Subscrio hub
- Report issues
- Discussions (org-wide)
- Testing guide
Maintained by Jasen Fici · Part of the Subscrio org
Subscrio supports product-owned add-ons and composition, atomic metered quotas, shared credit wallets with scheduled grants and a ledger, and timed subscription overrides. Existing feature-checker calls resolve add-ons and active overrides automatically. Configure feature resolution on product-feature associations. Define add-on contributions through add-on create/update, configure meters through feature create/update, and read usage through the metering object.
These capabilities require schema 1.4.0 and compatible library/server versions. See the entitlement guide and the console sample for the TypeScript walkthrough. The documentation repository includes runnable TypeScript and .NET examples. Back up and migrate existing databases before upgrading all writers together.