Reference

Licenzy API reference

Reference the Licenzy /v1 runtime API for checkout, access checks, entitlements, and usage consumption. Configure projects, API keys, Stripe setup, outbound Licenzy webhooks, and billing from the Licenzy portal.

Start free in test mode. Go live when you're ready.

Category: Reference5 sections

Runtime API reference

Use these /v1 endpoints from server-side code. Try It examples are local previews only.

Runtime API

API key authenticated /v1 reference

Use these endpoints from server-side code. API keys select the account and mode, test mode remains available for setup, and live writes require an active or trial commercial subscription.

Global API key auth

Send Authorization: Bearer lz_test_... or lz_live_....

Modes

Data is scoped by account_id and API key mode. Runtime request bodies do not switch modes.

Common auth errors

missing_bearer_token, invalid_api_key, and plan_mode_not_allowed.

This reference intentionally excludes /portal/* cookie/session routes and Stripe inbound plus outbound operational webhook surfaces that are not part of the public tenant-facing runtime API. Documented endpoints: 5.

Outbound payload glossary

Outbound Licenzy payloads are source-aware and reason-aware. Nullable fields are expected when a field is not relevant to the current event.

  • Common fields may include subject_ref, project_id, mode, product_code, kind, status, reason, source, entitlement_id, attempt_id, units, usage_remaining, amount_total, currency, stripe_checkout_session_id, stripe_payment_intent_id, stripe_subscription_id, current_period_end, expires_at, canceled_at, actor_user_id, metadata, created_at, and updated_at.
  • status describes the runtime entity state relevant to the current event, not the HTTP delivery status in the portal.
  • source describes where the runtime state change originated: Stripe lifecycle processing, a portal operator action, or a runtime API operation.
  • reason is operational context for why the event exists. Treat it as descriptive context, not a closed enum or the only source of truth.
  • attempt_id identifies the checkout attempt when the event still has current checkout-attempt context.
  • entitlement_id identifies the runtime entitlement row involved in the change when one exists.
  • amount_total is the billing amount for the current event snapshot when billing context is relevant.
  • metadata carries the current event-specific metadata snapshot. It can differ across Stripe, portal, and runtime sources.
  • current_period_end, expires_at, and canceled_at are lifecycle timestamps that appear only when the event needs them.
  • created_at and updated_at belong to the payload snapshot emitted by Licenzy. Treat portal delivery history timestamps separately from payload entity timestamps.
  • source=stripe includes Stripe and checkout-attempt context only when it is current and relevant.
  • source=portal includes actor_user_id for manual operator events and does not backfill stale Stripe fields.
  • source=runtime includes runtime usage context and does not backfill stale Stripe or portal fields.
  • Nullable fields are expected whenever the current event does not need billing, operator, or usage-specific context.
Stripe-sourced outbound payload exampleConcrete integration example
JSON
{
  "subject_ref": "user_123",
  "project_id": "proj_123",
  "mode": "live",
  "product_code": "PRO_MONTHLY",
  "kind": "subscription",
  "status": "active",
  "reason": "<stripe-derived reason>",
  "source": "stripe",
  "entitlement_id": "ent_123",
  "attempt_id": "att_123",
  "amount_total": 7900,
  "currency": "usd",
  "stripe_checkout_session_id": "cs_test_123",
  "stripe_payment_intent_id": "pi_123",
  "stripe_subscription_id": "sub_123",
  "current_period_end": "2026-06-01T00:00:00.000Z",
  "expires_at": null,
  "canceled_at": null,
  "metadata": {},
  "created_at": "2026-05-18T09:00:00.000Z",
  "updated_at": "2026-05-18T09:00:00.000Z"
}
Portal-sourced outbound payload exampleConcrete integration example
JSON
{
  "subject_ref": "user_123",
  "project_id": "proj_123",
  "mode": "live",
  "product_code": "PACK_1000",
  "kind": "usage_pack",
  "status": "active",
  "reason": "<portal operation reason>",
  "source": "portal",
  "entitlement_id": "ent_123",
  "usage_remaining": 1000,
  "actor_user_id": "usr_123",
  "metadata": {},
  "created_at": "2026-05-18T09:15:00.000Z",
  "updated_at": "2026-05-18T09:15:00.000Z"
}
Runtime-sourced outbound payload exampleConcrete integration example
JSON
{
  "subject_ref": "user_123",
  "project_id": "proj_123",
  "mode": "live",
  "product_code": "PACK_1000",
  "kind": "usage_pack",
  "status": "active",
  "reason": "<runtime usage reason>",
  "source": "runtime",
  "entitlement_id": "ent_123",
  "units": 10,
  "usage_remaining": 990,
  "metadata": {},
  "created_at": "2026-05-18T09:20:00.000Z",
  "updated_at": "2026-05-18T09:20:00.000Z"
}

Error glossary

These are the most common runtime error codes you should handle explicitly in backend integrations:

  • missing_idempotency_key: checkout or usage write was sent without the required Idempotency-Key header.
  • idempotency_conflict: the same idempotency key was reused with different request parameters.
  • product_not_found: the supplied product_code does not exist in the selected project and mode.
  • invalid_product_kind: the target product cannot be used for the requested runtime flow.
  • stripe_connection_not_configured: Stripe is not configured for the selected project and mode.
  • plan_mode_not_allowed: the current Licenzy plan does not allow that mode, usually live.
  • insufficient_usage: the subject does not have enough remaining usage units to fulfill the request.
  • plan_limit_exceeded: the account hit a commercial or plan-level usage limit.
Operational note
Runtime errors belong in backend retry, purchase, or upgrade logic. Support/debug investigation and manual recovery belong in the Licenzy portal.

Common integration sequence

Most product integrations use the APIs in this order:

  1. Configure Stripe credentials, products, API keys, and any outbound Licenzy webhooks in the Licenzy portal.
  2. Make sure the API keys, products, Stripe setup, and outbound Licenzy webhooks you use all belong to the same project context.
  3. Start checkout from your backend with POST /v1/checkout/session.
  4. Redirect the user to the returned Stripe Checkout URL.
  5. Register the Stripe inbound webhook in Stripe so Stripe can call /v1/webhooks/stripe/tenant. Your app should not call that inbound Stripe route directly.
  6. Read access with POST /v1/access/check or inspect entitlements after webhook processing.
  7. For usage packs, consume units with POST /v1/usage/consume from your backend.
  8. Use the Licenzy portal for support/debug operations, outbound webhook delivery inspection, and manual entitlement recovery.

The full integration example shows the same sequence as an end-to-end implementation.

Key guides