Authentication
The Public API supports two authentication methods. Pick based on the caller.
API key
Send your key in the x-api-key header on every request:
Code
Best for server-to-server integrations you control. Keys are scoped and can be revoked from the LedgerBee app.
- Never send an API key as a Bearer token.
Authorization: Bearer <key>is rejected with401— that header carries OAuth access tokens only. - The key can also be passed as an
?x-api-key=query parameter; prefer the header — query strings leak into access logs. - A key can carry an IP allowlist. Requests from other IPs get
401withdetails.reason: "ip_whitelist_mismatch". - Inspect a key's own scopes, allowlist, and expiry with
GET /v1/api-key, authenticated with the key itself.
OAuth2 client credentials
For machine-to-machine clients that prefer short-lived bearer tokens. Request a
token from the token endpoint, then send it as a Bearer token.
Code
Scopes are configured per client under Marketplace → OAuth Clients — scopes requested in the token call are ignored in favour of the client's configured set.
- The
client_secretis shown once at creation; store it securely. - Tokens expire after 3600 seconds — re-request when one expires.
- Revoking the client, or changing its scopes or IP allowlist, invalidates outstanding tokens; mint a fresh one.
- The partner provisioning scopes (
portal-provision,portal-sso-mint) are API-key only — they can never be granted to an OAuth or MCP client. See Portal SSO.
Connected apps (partner OAuth)
For a partner integration that acts on a company's data with that company's consent, LedgerBee registers your app and you run the OAuth 2.1 authorization-code flow (PKCE, user consent, refresh tokens) rather than client credentials. See the Connected Apps guide for registration, the authorize URL, token exchange, and revocation.
The same flow connects your app to an accounting firm's client list when a firm admin approves it; see Advisor firms.
Common errors
| Symptom | Cause | Fix |
|---|---|---|
401 with Authorization: Bearer <api-key> | A raw API key sent as a Bearer token | Use the x-api-key header; Bearer is for OAuth tokens |
401 invalid_token with a real OAuth token | Token expired, or its client/grant was revoked | Mint a fresh token |
401 with reason: ip_whitelist_mismatch | Request IP not on the key's allowlist | Add the IP, or clear the allowlist |
403 INSUFFICIENT_PERMISSIONS | Key/token lacks the required scope | Add the scope to the key or client — see Errors |
403 PUBLIC_API_HOLDER_MISMATCH | A company credential on an advisor firm endpoint, or a firm token on a company endpoint (details.required, details.actual) | Use the credential the endpoint names — see Choose your integration |
403 LICENSE.REQUIRED | The company lacks the module's license (details.licenseKey) | Enable the module — see Licenses |
Dynamic Client Registration (DCR)
For agent/MCP clients that self-register, the API exposes RFC 7591 Dynamic Client Registration. An MCP client is a DCR-registered connected app — the same record backs both terms.
Code
Discovery (.well-known)
The authorization server and protected-resource metadata are published for automatic client configuration:
/.well-known/oauth-authorization-server/.well-known/oauth-protected-resource/.well-known/openid-configuration/.well-known/jwks.json
These power the OAuth 2.1 / MCP authorization flows described in the MCP guide.