# Licenses

Most of the Public API is available to every LedgerBee company. A few modules
are licensed separately and gated by a per-tenant **license** — an entitlement
the company holds — in addition to the API-key scope. A call to a licensed
module succeeds only when both gates pass: the credential carries the required
scope, and the company holds the required license.

## Scopes and licenses are independent gates

Scope and license answer different questions, and granting one never grants the
other.

| Gate | Lives on | Controls | Missing → | `details` |
| --- | --- | --- | --- | --- |
| Scope | the API key / OAuth client | which operations the credential may perform | `403 INSUFFICIENT_PERMISSIONS` | `requiredScopes` |
| License | the company (resolved from the credential's tenant) | whether the company has the module at all | `403 LICENSE.REQUIRED` | `licenseKey` |

Scopes are configured per key/client under **Marketplace** — see
[Authentication](/guides/authentication). A license is held by the company and
resolved server-side from the credential; it is never set per request.

## Licensed modules

These Public API areas require the company to hold a license. The value in
`details.licenseKey` on a `403 LICENSE.REQUIRED` is the license to enable.

| Module | Endpoints | `details.licenseKey` |
| --- | --- | --- |
| Subscriptions | `/v1/subscriptions`, `/v1/subscriptions/*` | `Subscription` |
| Projects | `/v1/projects`, `/v1/projects/*` | `Projects` |
| Customer Portal — pricing catalogue | `/v1/portal/plans`, `/v1/portal/plans/resolve`, `/v1/portal/plans/{planId}` | `CustomerPortal` |
| Customer Portal — provisioning & SSO | `/v1/portal-sso/provision`, `/v1/portal-sso/handoff/mint`, `/v1/portal-sso/sessions/revoke` | `CustomerPortal` |
| MCP (AI agents) | `/v1/mcp`, `/v1/mcp/c/{appCompanyId}` | `MCP` |

Every other endpoint — company, accounts, customers, products, invoices, credit
notes, quotes, order confirmations, journal entries, dimensions, VAT codes,
meters, document templates, webhooks — is available to every company and needs
no license. Each licensed operation also names its license under **Required
License** in the [API Reference](/api).

The MCP servers are described in the [MCP guide](/guides/mcp); the
unauthenticated developer endpoint `/v1/mcp/developer` needs no license. The
licensed Customer Portal flows are covered in
[Portal SSO](/guides/portal-sso) and
[Embedded checkout](/guides/embedded-checkout/overview), and subscription
billing in [Subscriptions](/guides/subscriptions/overview).

## When a license is missing

A request to a licensed module the company doesn't hold returns `403 Forbidden`
with `code: "LICENSE.REQUIRED"` and the missing license in `details.licenseKey`:

```json
{
  "statusCode": 403,
  "timestamp": "2026-06-16T12:34:56.789Z",
  "path": "/v1/subscriptions",
  "message": "Forbidden Exception",
  "code": "LICENSE.REQUIRED",
  "details": { "licenseKey": "Subscription" }
}
```

Branch on `code`, never on `message`. `LICENSE.REQUIRED` (the company lacks the
module) and `INSUFFICIENT_PERMISSIONS` (the credential lacks a scope) are both
`403` but need different fixes — enable the module versus add the scope. The
full error envelope is in [Errors](/guides/errors).

## Enabling a module

Licenses are managed inside the LedgerBee app, not through the API — a company
enables or removes a module with LedgerBee. Once the company holds the license,
the same key and scope start working; no credential change is required.
