Subscriptions and entitlements
An account has one subscription with one item per enrolled paid product: your account can be on Free for Flags, Standard for Logging, and Pro for Config at the same time. Products on Free are simply absent from the subscription — paid products show up as items. Each plan publishes a set of entitlement keys (numerical limits) that the platform enforces on writes. When you hit a limit, the API returns 402 Payment Required.
A concrete example
Your team is starting out. You sign up — every product begins on the implicit Free plan, and your account has no subscription yet. You stay on Free Flags forever (your usage fits within the Free limits) but find yourself wanting more managed loggers than Free Logging allows. You enroll Logging at Standard — the platform creates your subscription with one item for Logging. Three months later, configs grow — you add a Config item at Standard too. Flags stays implicit Free with no item on the subscription.
The same subscription now has two paid items (Logging and Config), each at its own plan. Both bill on the same monthly cycle.
Plans
Each product has four plans:
- Free — the default. No card required. Generous-but-limited entitlements.
- Standard — paid monthly. Bigger limits, suited to teams shipping to production.
- Pro — paid monthly. Larger limits built for scale.
- Enterprise — paid monthly. Largest limits, plus governance, security, and SSO controls for whole-org rollouts.
Plans are defined per product in the platform's catalog. The exact entitlement values live in the catalog and are surfaced via GET /api/v1/products (the public products endpoint, also powering the pricing page).
curl https://app.smplkit.com/api/v1/productsReturns each product's plans, prices, limits, and marketing copy. Fully cacheable; no auth required.
Entitlement keys
Every plan publishes limits keyed by entitlement key. A value of -1 in any limit means unlimited. The keys with finite values today:
| Key | Meaning | Bundled / Free | Standard | Pro | Enterprise |
|---|---|---|---|---|---|
logging.managed_loggers | Loggers with managed = true | 10 | 100 | 1000 | unlimited |
logging.groups | Log groups | 3 | 25 | 100 | unlimited |
config.items | Configs per account | 10 | 50 | 250 | unlimited |
config.keys | Items per config (per write) | 25 | 250 | 2500 | unlimited |
config.value_size_bytes | Per-item value byte size | 1024 | 10240 | 102400 | 1048576 |
config.inheritance_depth | Max parent chain depth | 2 | 5 | 10 | unlimited |
flags.items | Flags with managed = true | 10 | 50 | 250 | unlimited |
flags.rules | Rules per flag (per write) | 5 | 25 | 100 | unlimited |
audit.events_per_month | Customer-emitted audit events per month | 1,000 | 100,000 | 1,000,000 | 10,000,000 |
audit.retention_days | Days customer audit events are retained | 30 | 365 | 1825 | 3650 |
audit.siem_streaming | SIEM streaming (forwarders) enabled | 0 | 0 | 0 | 1 |
Smpl Audit's "Bundled" tier ships free with any other smplkit product subscription — there's no separate audit subscription at that level. smplkit-emitted audit events (resource types prefixed smpl.) are unlimited at every tier and never count toward audit.events_per_month.
audit.siem_streaming is enforced at the fan-out path (POST /api/v1/events), not at the management surface. Forwarder configuration is plan-agnostic on every plan — you can create, list, update, retry, and delete forwarders regardless of subscription. When the entitlement is 0, the audit service short-circuits before any forwarder lookup: no HTTP delivery is attempted and no delivery records are written. See SIEM streaming for the full delivery-status semantics.
Other keys (config.environments, config.servers, config.users, flags.environments, flags.servers, flags.users, logging.environments, logging.servers, logging.users) are defined and may be enforced in the future, but ship -1 (unlimited) or 0 on every plan today. Authoritative values come from GET /api/v1/products.
How counting differs across products
Logging charges you only for managed loggers — auto-discovery is free, so a service that imports thousands of library loggers doesn't fill your quota. Logging groups count separately and are always managed.
Flags has the same managed/discovered split as Logging: only flags with managed = true (typically created via POST /api/v1/flags) count toward flags.items. Auto-discovery via POST /api/v1/flags/bulk is exempt from governance entirely, so a service that imports thousands of flag references doesn't fill your quota.
Config has no managed/discovered split; every config is explicit and counts toward config.items.
What happens at quota
When a write would push you past a limit, the platform returns:
HTTP/1.1 402 Payment Required
Content-Type: application/vnd.api+json{
"errors": [{
"status": "402",
"code": "entitlement_limit_reached",
"title": "Subscription limit reached",
"detail": "Your free plan allows a maximum of 15 managed loggers. Upgrade your subscription to increase this limit.",
"meta": {
"limit_key": "logging.managed_loggers",
"current": 15,
"maximum": 15,
"plan": "free"
}
}]
}The meta.limit_key tells you exactly which limit blocked you. Existing resources keep working — only the write that would exceed the limit fails. Reads, evaluations, and metric ingestion are unaffected.
The console surfaces these as inline upgrade prompts when you click an action that would fail.
Subscription statuses
Stripe-aligned. The status field on the subscription resource takes one of:
ACTIVE— the customary good state.PAST_DUE— last invoice failed; Stripe is retrying. Functionality continues during the retry window.CANCELED— subscription ended. Functionality continues untilcurrent_period_end, after which all items are dropped and the account reverts to implicit Free across the board.null— fully discounted: an administrator has setdiscount_source = OVERRIDEat 100%, and Stripe is not involved. All paid items are honored without billing.
Until you enroll your first paid item the account has no subscription row at all — GET /api/v1/accounts/current/subscription returns 404. Free state is derived from the absence of a subscription, or from a subscription that simply has no item for a given product.
Subscription lifecycle
The whole subscription is one resource you replace with a PUT. Each call to PUT /api/v1/accounts/current/subscription sends the desired items list — the server diffs against your current state and reconciles. Mechanically, that produces five kinds of per-item transition:
- New item — a product not currently on the subscription is added. Takes effect immediately; Stripe creates prorations for the remainder of the current period.
- Upgrade — an existing item moves to a higher plan. Takes effect immediately; prorated charge today.
- Downgrade — an existing item moves to a lower paid plan. Scheduled for
current_period_end; the higher plan continues until then. The item showspending_plan_changeandscheduled_change_effective_atuntil the change takes effect. - Drop — a product currently on the subscription is omitted from the request. Scheduled for
current_period_end; reverts to implicit Free then. - Unchanged — an item already at the requested plan is left as-is.
To reverse a pending downgrade or drop before period end, send another PUT with the item back at its current paid plan — the diff classifies it as UNCHANGED and clears the pending change. Cancellation of the whole subscription is just a PUT with an empty items list; if no paid items remain, Stripe schedules cancellation at period end.
Before committing a change you can call POST /api/v1/accounts/current/subscription/actions/preview with the same body to project per-item effects, prorated charges due today, and the next-invoice total without mutating anything.
The first paid item requires a payment method. Subsequent changes reuse the account's default payment method unless you specify another. See Manage subscriptions.
Cross-product platform limits
Some platform-wide capabilities are plan-resolved entitlements — they vary by the highest plan you hold across any paid product and return 402 Payment Required when exceeded. The rest are flat operational caps that are the same on every plan and return 409 Conflict.
Plan-resolved (platform.*)
The platform pseudo-product resolves at the highest plan held across your paid products (config/flags/logging/audit). If you're on Flags Pro and Logging Free, your platform.* entitlements come from the Pro tier. See GET /api/v1/products for the exact values per plan.
| Key | What it gates | Free | Standard | Pro | Enterprise |
|---|---|---|---|---|---|
platform.managed_environments | Environments with managed = true (only managed environments count) | 2 | 3 | 10 | unlimited |
platform.writers | Account members whose role is OWNER, ADMIN, or MEMBER. Pending non-VIEWER invitations also count. | 1 | unlimited | unlimited | unlimited |
platform.readers | Account members whose role is VIEWER | unlimited | unlimited | unlimited | unlimited |
Two new error codes carry context for the most common 402s and 400s on these surfaces:
environment_unmanaged(400) — a write to flags / config / logging tried to set a per-environment value on an unmanaged environment. Promote it first viaPUT /api/v1/environments/{id}withmanaged: true.environment_not_found(400) — the referenced environment doesn't exist for this account.
Flat operational caps (409 Conflict)
These remain the same on every plan; they exist to bound platform resource usage. Contact support if you legitimately need more.
- 50 API keys per account
- 50 context types per account
- 10,000 context instances per account (includes services)
- 100 pending invitations per account
Who can do what
| Action | OWNER | ADMIN | MEMBER | VIEWER |
|---|---|---|---|---|
| Read subscription, products | ✓ | ✓ | ✓ | ✓ |
| Read invoices, billing history | ✓ | ✓ | ||
| Replace subscription (add, upgrade, downgrade, drop items) | ✓ | |||
| Manage payment methods | ✓ |
Related
- Multi-product pricing — automatic discount when you subscribe to more than one product
- Manage subscriptions
- Manage payment methods
- Discovered vs managed — how managed-vs-discovered interacts with quota
- API Reference — Platform: Subscriptions

