LedgerBee Developer
  • Getting started
  • Conventions
  • Products
  • Advisor firms
  • Configuration
  • API Reference
Information
Accounts
    List accountsgetCreate an accountpostGet an accountgetDelete an accountdeleteUpdate an accountpatch
Advisor Authority Extracts
    Submit authority extract data for an advisor firm's clientspost
Advisor Clients
    List the advisor firm's clientsget
API Key
    Get current API keyget
Authority Extracts
    Submit authority extract datapost
Bank Reconciliations
    Reconcile bank lines against entriespostUndo a bank reconciliationpostCheck what undoing a reconciliation would dopostReconcile a batch of matchespostCheck what reconciling a batch of matches would dopostCheck what reconciling bank lines against entries would dopost
Bank Transactions
    List bank linesgetGet a bank linegetDismiss bank lines from reconciliationpostCheck which bank lines a dismiss would changepostRestore dismissed bank lines to reconciliationpostCheck which bank lines a restore would changepost
Billing Groups
    Form a billing grouppostGet a billing groupgetAdd members to a billing grouppostRemove a member from a billing groupdeleteCheck billing group eligibilitypost
Budgets
    List budgetsgetGet a budgetgetGet the budget vs actuals comparisongetExport a budget's Excel workbookgetOverwrite a budget's figures from an edited workbookpostList a budget's frozen baselinesgetGet a frozen baseline with its snapshot cellsgetList a budget's re-baseline proposalsgetList a budget's scenariosgetResolve a budget's grid under a scenariogetGet the variance report vs a frozen baselinegetGet the runway headlineget
Checkout
    Confirm the checkoutpostQuote a first periodpostIntegration readinessgetMint a checkout sessionpostRehydrate a sessiongetRelease the card hold (edit-after-card)postPoll card statusgetOpen the card windowpostOpen a card window for a live subscriptionpost
Company
    Get company detailsget
Connected app OAuth
    JSON Web Key Set used to verify OAuth access-token signaturesgetRFC 8414 authorization-server metadata for the connected-app OAuth servergetRFC 9728 protected-resource metadata for an MCP resourcegetRFC 9728 protected-resource metadata for an MCP resourcegetOpenID Connect discovery document for the connected-app OAuth serverget
Credit Note Links
    Link a credit note to the invoice it creditspostCheck a credit note’s links and the invoices it can be linked topostDetach a credit note from the invoices it is applied topost
Credit Notes
    List credit notesgetCreate a credit notepostGet a credit notegetGet the delivery status of a credit notegetDownload the credit note PDFgetSend a credit note to the customerpostCredit a whole invoicepost
Customers
    List customersgetCreate a customerpostGet a customergetDelete a customerdeleteUpdate a customerpatchList a customer's contactsgetList a customer's departmentsgetList customer groupsget
Dimensions
    List all dimensionsgetCreate a new dimension categorypostGet a dimensiongetUpdate a dimension categoryputDelete a dimension categorydeleteList distribution keys (paginated)getCreate a distribution keypostGet a distribution keygetList dimension values (paginated)getCreate a new dimension valuepostUpdate a dimension valueputDelete a dimension valuedelete
Discounts
    List discountsgetCreate a discountpostGet a discountgetDelete a discountdeleteUpdate a discountpatchSet a discount's amount in one currencyputRemove a discount's amount in one currencydeleteCheck whether a discount applies to a product for a customer on a daygetAssign a discountpostRemove an assignmentdeleteUpdate an assignmentpatchList a discount's codesgetAdd a code to a discountpostDelete a codedeleteUpdate a codepatchList the discounts that apply to a product for a customer on a daygetCheck a cartpostLook up a discount codeget
Document Templates
    List document templatesget
Document Upload Links
    Upload a file through a minted linkpost
Download Links
    Mint a download link for a document PDFgetDownload a minted linkget
Draft Journal Entries
    Create multiple draft journal entries in batchpostList draft journal entriesgetCreate a draft journal entrypostGet a draft journal entrygetDelete a draft journal entrydeleteBook a draft journal entrypost
Draft Journal Entries (v2)
    Create draft journal entries in batch (v2)postList draft journal entries (v2)getCreate a draft journal entry (v2)postGet a draft journal entry (v2)getDelete a draft journal entry (v2)deleteUpdate a draft journal entry (v2)patchGet attachments for a draft journal entry (v2)getAdd a document to a draft journal entry (v2)postRemove a document from a draft journal entry (v2)deleteBook a draft journal entry (v2)post
Entitlements
    List entitlementsgetCreate an entitlementpostGet an entitlementgetDelete an entitlementdeleteUpdate an entitlementpatch
Invoices
    List invoicesgetCreate a draft invoicepostGet an invoicegetDelete a draft invoicedeleteUpdate an unsent invoicepatchGet the delivery status of an invoicegetDownload the invoice PDFgetSend an invoice to the customerpost
Journal Categories
    List journal categoriesgetCreate a journal categorypostUpdate a journal categoryputDelete a journal categorydelete
Journal Entries
    List journal entriesgetGet a journal entrygetUpdate a journal entry — correct the reference and/or set your external system idpatchGet attachments for a journal entrygetAdd a document to a journal entrypostRemove a document from a journal entrydeletePreview a correction without posting itpostMove postings to different accounts, keeping the document intactpostRebuild the entry a reversal undid, as a draftpostPreview rebuilding the entry a reversal undidpostReverse a posted entry and open a draft to re-enter itpostReverse posted journal entries in batchpostPreview reversing posted journal entries in batchpostReverse a posted journal entrypostPreview reversing a posted journal entrypost
Journal Entries (v2)
    Create a journal entry (v2)postCreate journal entries in batch (v2)post
MCP
    LedgerBee Developer MCP Serverpost
Meters
    List meter subscriptions by IDgetReport usagepostList meter subscriptions by nameget
Open Entries
    List a counterparty’s open entriesget
Order Confirmations
    List order confirmationsgetCreate a draft order confirmationpostGet an order confirmationgetUpdate a draft order confirmationpatchConvert an order confirmation into an invoicepostDownload an order confirmation as PDFgetSend an order confirmationpost
Payment Methods
    List saved payment methods for a customergetCancel a saved card on the payment providerdeleteUnassign a payment method from a customerdeleteGenerate a link for the customer to save a card for future paymentspostSet a saved payment method as the customer defaultput
Portal Plans
    List the full plan cataloguegetGet a plangetResolve the gated pricing catalogue for an identified buyer (partner display)post
Portal SSO
    Get a tenant's SSO signing keys (JWKS)getMint a checkout-vouch token (partner-vouched anonymous checkout)postMint a customer-portal SSO handoff referencepostProvision a customer + grant portal access (partner JIT provisioning)postRevoke (force-refresh) a user's customer-portal sessionspost
Product Groups
    List product groupsgetCreate a product grouppostGet a product groupgetDelete a product groupdeleteUpdate a product grouppatch
Product Prices
    Create a product pricepostGet a product pricegetDelete a product pricedeleteUpdate a product pricepatchActivate a product pricepostArchive a product pricepostDisable a product pricepostSet a price as the product defaultpost
Products
    List productsgetCreate a productpostGet a productgetDelete a productdeleteUpdate a productpatchArchive a productpost
Projects
    List all projectsgetCreate or update a project by external referenceputCreate a projectpostGet a projectgetUpdate a projectputGet project profitgetAdd a subprojectpostUpdate a subprojectputDelete a subprojectdelete
Quotes
    List quotesgetCreate a draft quotepostGet a quotegetUpdate a draft quotepatchConvert a quotepostDownload a quote as PDFgetSend a quotepost
Settlements
    List a counterparty’s settlementsgetSettle open entries against each otherpostGet a settlementgetUndo a settlementpostCheck what undoing a settlement would dopostCheck what settling these entries would dopost
Shipments
    List shipmentsgetCreate a shipment from an orderpostGet a shipmentgetCancel a shipmentpostDispatch a shipmentpost
Stock
    List stock movementsgetList on-hand stockgetOn-hand for one productget
Subscriptions
    List customer subscriptionsgetAssign a subscription to a customerpostGet a customer subscription by its stable idgetUpdate a customer subscriptionpatchAdd an add-on to a customer subscriptionpostAttach existing subscriptions as add-onspostCheck whether subscriptions can become add-onspostChange the products on a customer subscriptionpostRetry a failed card paymentpostList a subscription's pending scheduled changesgetCancel a single pending scheduled changedeleteGet a subscription's unbilled usagegetCancel a customer subscriptionpostList subscription plansgetCreate a subscription planpostArchive a subscription planpost
Suppliers
    List suppliersgetCreate a supplierpostDelete a supplierdeleteList supplier contactsgetList supplier departmentsgetList supplier groupsget
VAT Codes
    List VAT codesgetCreate a VAT codepostGet a VAT codegetDelete a VAT codedeleteUpdate a VAT codepatch
VAT periods
    Record a VAT return filed outside LedgerBeepostPreview recording a VAT return filed outside LedgerBeepostSettle a filed VAT periodpostPreview a VAT period settlementpost
Vendors
    List vendorsgetCreate a vendorpostList vendor contactsgetList vendor departmentsgetList vendor groupsget
Webhook Endpoints
    List webhook endpointsgetCreate a webhook endpointpostRetrieve a webhook endpointgetUpdate a webhook endpointputDelete a webhook endpointdeleteRoll the signing secretpostSend a test eventpost
Schemas
LedgerBee Public API
LedgerBee Public API

Portal SSO

Download schema

Get a tenant's SSO signing keys (JWKS)

GET
https://api.ledgerbee.com/api
/.well-known/portal-sso/{slug}/jwks.json

The jwks_uri a partner registers at their OpenID Provider so it can verify our private_key_jwt client assertions. Returns an RFC 7517 JWK Set of the tenant's current signing key plus — during a rotation grace window — the immediately-previous key, each keyed by kid. Public key material only; no authentication required. Never returns a 404: a slug with no configured signing key — unknown, or a real tenant that has not set up portal SSO — returns a single well-formed decoy key rather than an empty set, so a 200 does not confirm the tenant exists. Only a slug that is not a valid DNS label returns the empty set. Cached for 5 minutes; OPs re-fetch on an unknown kid.

Get a tenant's SSO signing keys (JWKS) › path Parameters

slug
​string · required

The tenant's public portal slug.

Example: acme

Get a tenant's SSO signing keys (JWKS) › Responses

200
PublicPortalSsoJwks
​object[] · required

The published public JWK(s). Public key material only — never any private component.

Example: [{"kty":"RSA","use":"sig","alg":"RS256","kid":"abc123","n":"…","e":"AQAB"}]
GET/.well-known/portal-sso/{slug}/jwks.json
curl https://api.ledgerbee.com/api/.well-known/portal-sso/:slug/jwks.json
Example Responses
{ "keys": [ { "kty": "RSA", "use": "sig", "alg": "RS256", "kid": "abc123", "n": "…", "e": "AQAB" } ] }
json
application/json

Mint a checkout-vouch token (partner-vouched anonymous checkout)

POST
https://api.ledgerbee.com/api
/v1/portal-checkout/vouch
x-api-key (header)
or
OAuth 2.0

Credential: a company's API key or OAuth token.

Vouches for a buyer you have already authenticated, so the embedded checkout can write their customer record at the moment they confirm — instead of you provisioning one up front.

Compared with the bound flow (portal-sso/provision + mintCheckoutBindToken):

  • The Details step stays editable, so the buyer corrects anything you pre-filled imprecisely. Only email is locked, because it becomes their portal login.
  • Nothing is written for an abandoned checkout. The customer, portal user and organization are written at confirm.
  • The buyer never leaves your page — no magic-link email, unlike a plain anonymous checkout.

Returning buyers

Omit customerId and the confirm creates a customer, emitting customer.created.

Pass customerId and it updates that customer instead, so a buyer who resubscribes keeps one record rather than accumulating a duplicate per purchase. The customer number is preserved; the buyer's Details submission overwrites the billing fields the form covers, and no customer.created fires.

Reuse is allowed only for a customer the vouched email already holds an active portal membership on, or one no portal user holds yet. Anything else is refused: 403 PORTAL_CHECKOUT_VOUCH_CUSTOMER_NOT_THEIRS when it belongs to someone else — omit customerId and let a colleague get their own record — and 403 PORTAL_CHECKOUT_VOUCH_CUSTOMER_ACCESS_REVOKED when the buyer's own portal access has been switched off, which the tenant restores from the gated app.

Pass clientReferenceId either way: it reaches the created subscription, every subscription webhook, and the customer.created event, and it is the only field that maps a new customer back to your order.

Discount code

Pass discountCode to open the checkout with a code applied. It is checked when you mint: an unknown, switched-off, expired or used-up code is refused with its DISCOUNT_* code (DISCOUNT_CODE_INVALID, DISCOUNT_NOT_APPLICABLE, DISCOUNT_REDEMPTION_LIMIT_REACHED, DISCOUNT_CODE_REDEMPTION_LIMIT_REACHED, DISCOUNT_CUSTOMER_REDEMPTION_LIMIT_REACHED), and a mint that names a code spends one use of the code-attempt budget your key shares with the discount cart check and code lookup. The checkout prices the code onto the plan the buyer picks, shows what it takes off and when the regular price starts, and judges it again when the subscription is created. A code that does not cover that plan, or has run out by then, is left off and the regular price is shown.

Required Scope

  • checkout — the documented forward scope for every partner checkout capability, OR
  • portal-provision — accepted for compatibility: existing integrations minted against the provisioning scope keep working unchanged.

Tenant preconditions

  • Partner-vouched checkout must be enabled on the tenant's portal settings, or the request returns 403 PORTAL_CHECKOUT_VOUCH_DISABLED. The scope proves who is calling; the switch proves the tenant turned the rail on.
  • Some self-service rail must be reachable by the buyer afterwards — a served portal a new buyer can log into, or the manage-link shell. A tenant with neither returns 403 PORTAL_CHECKOUT_VOUCH_TENANT_PORTAL_UNREACHABLE — a vouched confirm mints no session, so the buyer needs a way to manage or cancel the subscription.

Mint a checkout-vouch token (partner-vouched anonymous checkout) › Headers

x-api-idempotency-key
​string · maxLength: 255

Optional idempotency key for safely retrying mutating requests.

Mint a checkout-vouch token (partner-vouched anonymous checkout) › Request Body

PublicMintCheckoutVouchRequest
email
​string · required

The buyer you are vouching for. This becomes their portal login identity, so the embedded checkout pre-fills it and LOCKS it — a buyer who is not this person uses the checkout's own escape rather than typing over it, and a confirm carrying a different address is refused. Distinct from contactEmail below, which is only where the paperwork goes.

Example: alice@acme.example
contactEmail
​string

Where invoices and receipts should go, when that differs from the login identity above. Written to the customer's default contact. Omit and billing follows email.

Example: billing@acme.example
customerId
​string

A customer you already hold the LedgerBee id for - typically one whose earlier subscription ended and who is now buying again. The purchase lands on that record instead of a second one, so a returning buyer does not accumulate duplicates. The customer must exist, be active, and belong to the API key's tenant; otherwise the mint returns 404 CUSTOMER_NOT_FOUND and nothing is minted.

This does not make the checkout read-only: the Details step still shows only what you prefilled, never the stored record, and whatever the buyer submits is written over the record at confirm. Omit for a first-time buyer - creating the customer at confirm is the default.

Example: 550e8400-e29b-41d4-a716-446655440010
​object

Optional starting values for the checkout Details step. Every field stays EDITABLE — this is a convenience for the buyer, never an assertion of fact, and whatever they submit is what we persist. Anything you omit renders empty.

allowIdentityChange
​boolean

Whether the buyer may reject the vouched identity and continue as an anonymous buyer (the checkout shows a "Not you?" escape). It does NOT let them type a different address - the vouch is dropped and the checkout restarts unvouched, because we cannot vouch for someone we were not told about. Defaults to true: a buyer who genuinely is not the person you named has no other way out, and stranding them is worse than showing a link. Set false when your authentication makes a wrong identity impossible.

Example: true
Default: true
clientReferenceId
​string

Your own opaque reference for this order (Stripe client_reference_id parity). It rides onto the created subscription (as partnerReferenceId), into every later subscription webhook, AND onto the customer.created event — which is the only field that maps a brand-new customer back to the cart that created it. Pass it. Server-to-server only; it never reaches a client/iframe surface. Max 200 chars, [A-Za-z0-9_-] only.

Example: order_7f3a9c21
discountCode
​string · maxLength: 64

A discount code to apply for this buyer, matched without regard to case or surrounding spaces. It is checked when you mint: a code that is unknown, switched off, expired, for another customer or with no use left is refused with its DISCOUNT_* code, and spends one use of the code-attempt budget this API key shares with the cart check and code lookup (429 DISCOUNT_CHECK_RATE_LIMITED). The embedded checkout then opens with the code applied to the plan the buyer picks; the buyer can remove it. A code that does not cover that plan, or has run out by then, is left off and the regular price shown.

Example: WELCOME10

Mint a checkout-vouch token (partner-vouched anonymous checkout) › Responses

PublicMintCheckoutVouchResponse
checkoutVouchToken
​string · required

Opaque, single-use, 60-second vouch reference. Return it from your page's fetchBindToken provider at checkout-start; the embedded checkout redeems it server-side. Mint it just-in-time — the TTL is deliberately shorter than a page's lifetime, and the provider is re-invoked per checkout.

Example: k7Fq2mZ8x1vN4pQ...
expiresAt
​string · required

ISO 8601 expiry of the reference above.

Example: 2026-08-07T12:01:00.000Z
POST/v1/portal-checkout/vouch
curl https://api.ledgerbee.com/api/v1/portal-checkout/vouch \ --request POST \ --header 'Content-Type: application/json' \ --header 'x-api-key: <api-key>' \ --data '{ "email": "alice@acme.example", "contactEmail": "billing@acme.example", "customerId": "550e8400-e29b-41d4-a716-446655440010", "prefill": { "customerType": "BUSINESS", "companyName": "Acme ApS", "firstName": "Alice", "lastName": "Jensen", "vatNumber": "12345678", "address": "Vestergade 1", "postalCode": "8000", "city": "Aarhus", "countryCode": "DK" }, "allowIdentityChange": true, "clientReferenceId": "order_7f3a9c21", "discountCode": "WELCOME10" }'
Example Request Body
{ "email": "alice@acme.example", "contactEmail": "billing@acme.example", "customerId": "550e8400-e29b-41d4-a716-446655440010", "prefill": { "customerType": "BUSINESS", "companyName": "Acme ApS", "firstName": "Alice", "lastName": "Jensen", "vatNumber": "12345678", "address": "Vestergade 1", "postalCode": "8000", "city": "Aarhus", "countryCode": "DK" }, "allowIdentityChange": true, "clientReferenceId": "order_7f3a9c21", "discountCode": "WELCOME10" }
json
application/json
Example Responses
{ "checkoutVouchToken": "k7Fq2mZ8x1vN4pQ...", "expiresAt": "2026-08-07T12:01:00.000Z" }
json
application/json

Mint a customer-portal SSO handoff reference

POST
https://api.ledgerbee.com/api
/v1/portal-sso/handoff/mint
x-api-key (header)
or
OAuth 2.0

Credential: a company's API key or OAuth token.

Back-channel single sign-on into the LedgerBee customer portal. A partner's backend calls this to mint an opaque, single-use, 60-second reference for a customer-portal user; the user's browser then redeems that reference at the portal-API host (.portal-api.ledgerbee.com/api/auth/sso/handoff/redeem?ref=) to establish a portal session — NOT the portal SPA host (.portal.ledgerbee.com), which serves the static app and silently ignores the ref. The reference carries no identity — it is a server-resolved pointer. The tenant is resolved from the API key, never the request body, and every asserted organization is validated against that tenant. At least one membership must be asserted: the portal user, organization, and membership are all created at redeem from the asserted customers (no prior provision call is required), and a handoff with no membership cannot establish a session and is rejected with a 400.

Required Scope

  • portal-sso-mint

Required License

  • Customer Portal — the tenant must also hold this module license, or the request returns 403 LICENSE.REQUIRED.

Mint a customer-portal SSO handoff reference › Request Body

PublicHandoffMintRequest
email
​string · required

Email of the partner-provisioned user. Links a first-time SSO login to an existing invited customer-portal user.

Example: jane.doe@partner-customer.com
sub
​string · required

The partner's stable, unique identifier for the user. Keyed together with the per-tenant handoff issuer to resolve the portal user across logins.

Example: partner-user-7f3a9c21
​PublicHandoffMembership[] · required

At least one customer membership to grant this user — required. The customer's portal organization (an opaque internal container) and the membership are created automatically server-side at redeem, so a prior provision call is NOT needed; you only ever reference customers, never organizations. Validated at mint: a customerId that isn't a customer of the API key's tenant, or an unknown role, is rejected with a 400 (rather than failing the user's browser redirect). A handoff with no membership can't establish a portal session, so an empty/omitted array is rejected here rather than minting a ref that would fail at redeem.

Example: [{"customerId":"550e8400-e29b-41d4-a716-446655440010","role":"OWNER"}]
name
​string

Display name of the user; used to populate the customer-portal user's name on first login.

Example: Jane Doe

Mint a customer-portal SSO handoff reference › Responses

PublicHandoffMintResponse
ref
​string · required

Opaque, single-use, short-TTL reference. Carries NO identity — the identity lives only in server-side storage keyed by this reference until it is redeemed once at the customer portal.

Example: Yk3pQ9sV2nR7tW1xZ4cB8mL6dF0aH5jE2gN9uK3pQ7s
expiresAt
​string · required

ISO-8601 timestamp after which the reference can no longer be redeemed (60 seconds after minting).

Example: 2026-06-03T12:34:56.000Z
POST/v1/portal-sso/handoff/mint
curl https://api.ledgerbee.com/api/v1/portal-sso/handoff/mint \ --request POST \ --header 'Content-Type: application/json' \ --header 'x-api-key: <api-key>' \ --data '{ "email": "jane.doe@partner-customer.com", "sub": "partner-user-7f3a9c21", "name": "Jane Doe", "memberships": [ { "customerId": "550e8400-e29b-41d4-a716-446655440010", "role": "OWNER" } ] }'
Example Request Body
{ "email": "jane.doe@partner-customer.com", "sub": "partner-user-7f3a9c21", "name": "Jane Doe", "memberships": [ { "customerId": "550e8400-e29b-41d4-a716-446655440010", "role": "OWNER" } ] }
json
application/json
Example Responses
{ "ref": "Yk3pQ9sV2nR7tW1xZ4cB8mL6dF0aH5jE2gN9uK3pQ7s", "expiresAt": "2026-06-03T12:34:56.000Z" }
json
application/json

Provision a customer + grant portal access (partner JIT provisioning)

POST
https://api.ledgerbee.com/api
/v1/portal-sso/provision
x-api-key (header)
or
OAuth 2.0

Credential: a company's API key or OAuth token.

Ensures a customer (referenced by customerId, or upserted idempotently by customer.customerNumber within the API key's tenant), bootstraps its portal organization, and grants a credential-less portal user an active membership — so a net-new end-customer can sign in via SSO/handoff. No invitation email is sent. Set mintHandoff=true (and carry the portal-sso-mint scope) to also receive a one-time handoff reference in the response for a single round-trip 'Go to portal'. Set mintCheckoutBindToken=true (also requires the portal-sso-mint scope) to receive a one-time checkout-bind reference the partner embeds so the embedded checkout subscribes directly against this customer.

Required Scope

  • portal-provision

Required License

  • Customer Portal — the tenant must also hold this module license, or the request returns 403 LICENSE.REQUIRED.

Provision a customer + grant portal access (partner JIT provisioning) › Headers

x-api-idempotency-key
​string · maxLength: 255

Optional idempotency key for safely retrying mutating requests.

Provision a customer + grant portal access (partner JIT provisioning) › Request Body

PublicProvisionCustomerRequest
email
​string · required

Email of the portal user to grant access to. A credential-less portal user is created if none exists.

Example: jane.doe@acme.example
customerId
​string

The customer's LedgerBee id. The customer must already exist in the API key's tenant; this endpoint never creates one from an id (a 404 CUSTOMER_NOT_FOUND is returned if it doesn't). Supply either customerId or a customer payload.

Example: 550e8400-e29b-41d4-a716-446655440010
​object

A customer to upsert, identified idempotently by its customerNumber: an existing customer of the API key's tenant with that number is reused, otherwise a new one is created with this payload. Same shape as the gated POST /customers request (so vatZone and countryCode are required here). If customer.email is omitted, the portal-user email below is used as the customer's contact email (and its auto-created default contact). Supply either this or customerId.

role
​string · enum

Membership role to grant. Defaults to USER; the org's first member is force-assigned OWNER regardless.

Enum values:
OWNER
ADMIN
BILLING_ADMIN
USER
Example: USER
userName
​string

Display name of the portal user (set on first creation).

Example: Jane Doe
organizationDisplayName
​string

Display name for the customer organization (first-invite bootstrap).

mintHandoff
​boolean

When true, also mint a back-channel handoff reference in the same call (one round-trip "Go to portal"). Requires the API key to ALSO carry the portal-sso-mint scope, and the tenant to have back-channel handoff enabled.

Example: false
sub
​string

The partner's stable, unique user identifier — required when mintHandoff is true; keys the handoff identity (with the per-tenant handoff issuer).

Example: partner-user-7f3a9c21
mintCheckoutBindToken
​boolean

When true, also mint a one-time CHECKOUT-BIND reference in the same call — an opaque token the partner's fetchBindToken provider returns to the embed at checkout-start so the embedded checkout subscribes directly against THIS customer instead of staging an anonymous magic-link signup. Requires the API key to ALSO carry the portal-sso-mint scope. Independent of mintHandoff (login): a checkout-bind ref can never mint a login session.

Example: false
clientReferenceId
​string

Your own opaque reference for this order (Stripe client_reference_id parity), e.g. your internal order or cart id. It rides the minted checkout-bind ref onto the resulting subscription (as partnerReferenceId) and into every later subscription webhook, so you can reconcile our subscription to your record. Server-to-server only — it never reaches a client/iframe surface. Max 200 chars, [A-Za-z0-9_-] only.

Example: order_7f3a9c21

Provision a customer + grant portal access (partner JIT provisioning) › Responses

PublicProvisionCustomerResponse
customerId
​string · required

Resolved customer id.

Example: 550e8400-e29b-41d4-a716-446655440010
customerCreated
​boolean · required

Whether a new customer was created (false = an existing one was reused).

Example: true
portalUserId
​string · required

Resolved portal user id.

Example: 550e8400-e29b-41d4-a716-446655440020
membershipId
​string · required

The active organization membership id.

Example: 550e8400-e29b-41d4-a716-446655440030
role
​string · enum · required

The granted membership role.

Enum values:
OWNER
ADMIN
BILLING_ADMIN
USER
Example: OWNER
handoffRef
​string | null

Opaque, single-use, 60s handoff reference — present only when mintHandoff was requested. Null otherwise.

Example: Yk3pQ9sV2nR7tW1xZ4cB8mL6dF0aH5jE2gN9uK3pQ7s
handoffExpiresAt
​string | null

ISO-8601 expiry of the handoff reference, when minted. Null otherwise.

Example: 2026-06-04T12:34:56.000Z
checkoutBindToken
​string | null

Opaque, single-use, 60s checkout-bind reference — present only when mintCheckoutBindToken was requested. Null otherwise. The partner's fetchBindToken provider returns this to the embed at checkout-start; the embedded checkout redeems it to subscribe directly against this customer.

Example: Yk3pQ9sV2nR7tW1xZ4cB8mL6dF0aH5jE2gN9uK3pQ7s
checkoutBindExpiresAt
​string | null

ISO-8601 expiry of the checkout-bind reference, when minted. Null otherwise.

Example: 2026-06-04T12:34:56.000Z
POST/v1/portal-sso/provision
curl https://api.ledgerbee.com/api/v1/portal-sso/provision \ --request POST \ --header 'Content-Type: application/json' \ --header 'x-api-key: <api-key>' \ --data '{ "customerId": "550e8400-e29b-41d4-a716-446655440010", "customer": { "customerType": "BUSINESS", "customerNumber": "1042", "name": "Acme Corporation", "vatZone": "domestic", "customerGroupId": "01HQ3Y1234567890ABCDEFGHIJ", "email": "contact@acme.com", "phone": "+45 12345678", "address": "123 Main Street", "city": "Copenhagen", "postalCode": "2100", "countryCode": "DK", "vatNumber": "DK12345678", "eanNumber": "5790000000001", "externalSystemId": "crm-12345", "website": "https://acme.com", "notes": "Key account customer", "locale": "da-DK", "language": "da", "creditLimit": 50000, "openingBalance": 1000, "paymentTerms": 30, "paymentTermType": "NET_DAYS", "defaultCashAccountId": "string", "defaultCurrency": "DKK", "poNumber": "PO-12345", "ourReference": "Jane Doe", "invoiceDeliveryTypePreference": "Email", "reminderConfigId": "string", "followsDefaultReminderConfig": true, "isActive": true, "invoiceTemplateId": "string", "creditNoteTemplateId": "string", "quoteTemplateId": "string", "orderConfirmationTemplateId": "string", "parentInvoiceTemplateId": "string", "includeChildDetailsPdf": true, "selfServiceDetailsEnabled": true, "parentCustomerId": "string", "billingRelationship": "self", "consolidationMode": "single_invoice", "billingDay": 0, "metadata": {} }, "email": "jane.doe@acme.example", "role": "USER", "userName": "Jane Doe", "organizationDisplayName": "string", "mintHandoff": false, "sub": "partner-user-7f3a9c21", "mintCheckoutBindToken": false, "clientReferenceId": "order_7f3a9c21" }'
Example Request Body
{ "customerId": "550e8400-e29b-41d4-a716-446655440010", "customer": { "customerType": "BUSINESS", "customerNumber": "1042", "name": "Acme Corporation", "vatZone": "domestic", "customerGroupId": "01HQ3Y1234567890ABCDEFGHIJ", "email": "contact@acme.com", "phone": "+45 12345678", "address": "123 Main Street", "city": "Copenhagen", "postalCode": "2100", "countryCode": "DK", "vatNumber": "DK12345678", "eanNumber": "5790000000001", "externalSystemId": "crm-12345", "website": "https://acme.com", "notes": "Key account customer", "locale": "da-DK", "language": "da", "creditLimit": 50000, "openingBalance": 1000, "paymentTerms": 30, "paymentTermType": "NET_DAYS", "defaultCashAccountId": "string", "defaultCurrency": "DKK", "poNumber": "PO-12345", "ourReference": "Jane Doe", "invoiceDeliveryTypePreference": "Email", "reminderConfigId": "string", "followsDefaultReminderConfig": true, "isActive": true, "invoiceTemplateId": "string", "creditNoteTemplateId": "string", "quoteTemplateId": "string", "orderConfirmationTemplateId": "string", "parentInvoiceTemplateId": "string", "includeChildDetailsPdf": true, "selfServiceDetailsEnabled": true, "parentCustomerId": "string", "billingRelationship": "self", "consolidationMode": "single_invoice", "billingDay": 0, "metadata": {} }, "email": "jane.doe@acme.example", "role": "USER", "userName": "Jane Doe", "organizationDisplayName": "string", "mintHandoff": false, "sub": "partner-user-7f3a9c21", "mintCheckoutBindToken": false, "clientReferenceId": "order_7f3a9c21" }
json
application/json
Example Responses
{ "customerId": "550e8400-e29b-41d4-a716-446655440010", "customerCreated": true, "portalUserId": "550e8400-e29b-41d4-a716-446655440020", "membershipId": "550e8400-e29b-41d4-a716-446655440030", "role": "OWNER", "handoffRef": "Yk3pQ9sV2nR7tW1xZ4cB8mL6dF0aH5jE2gN9uK3pQ7s", "handoffExpiresAt": "2026-06-04T12:34:56.000Z", "checkoutBindToken": "Yk3pQ9sV2nR7tW1xZ4cB8mL6dF0aH5jE2gN9uK3pQ7s", "checkoutBindExpiresAt": "2026-06-04T12:34:56.000Z" }
json
application/json

Revoke (force-refresh) a user's customer-portal sessions

POST
https://api.ledgerbee.com/api
/v1/portal-sso/sessions/revoke
x-api-key (header)
or
OAuth 2.0

Credential: a company's API key or OAuth token.

Immediately invalidates every active portal session of the partner-provisioned user (identified by the same sub used at mint), forcing re-authentication on their next request. Use for proactive offboarding — it tightens the residual window from the session TTL to immediate. Deprovisioning at the OP is what then prevents re-login.

Required Scope

  • portal-sso-mint

Required License

  • Customer Portal — the tenant must also hold this module license, or the request returns 403 LICENSE.REQUIRED.

Revoke (force-refresh) a user's customer-portal sessions › Request Body

PublicRevokeSessionsRequest
sub
​string · required

The partner's stable subject id for the user — the same sub used when minting their handoff. Every active portal session of that user is force-refreshed.

Example: partner-user-7f3a9c21

Revoke (force-refresh) a user's customer-portal sessions › Responses

PublicRevokeSessionsResponse
revoked
​number · required

Number of memberships whose sessions were force-refreshed (0 when the user has no active sessions).

Example: 2
POST/v1/portal-sso/sessions/revoke
curl https://api.ledgerbee.com/api/v1/portal-sso/sessions/revoke \ --request POST \ --header 'Content-Type: application/json' \ --header 'x-api-key: <api-key>' \ --data '{ "sub": "partner-user-7f3a9c21" }'
Example Request Body
{ "sub": "partner-user-7f3a9c21" }
json
application/json
Example Responses
{ "revoked": 2 }
json
application/json

Portal PlansProduct Groups