LedgerBee Developer
  • Getting started
  • Conventions
  • Products
  • Configuration
  • API Reference
Subscriptions
Payment flowCard paymentsProducts & PricingProduct Entitlements
Billing documents
Accounting
WebhooksPartner-Hosted Checkout
Customer Portal
Products

Products & Pricing

Manage the product catalogue over the LedgerBee public API (base URL https://api.ledgerbee.com/api/v1). A product price is what an invoice, quote, or order-confirmation line references through its priceId to bill a real catalogue product. Authenticate with the x-api-key header; the key carries the tenant, and every :id path segment is a UUID.

The catalogue is three resources, all under one scope pair:

  • products-read — list and get products, prices, and product groups.
  • products-write — create, update, and delete products, prices, and product groups, and run price lifecycle actions.

A product belongs to a product group, and a product has one or more prices. Create them in that order: group, then product, then price.

Product groups

A product group maps a product's sales to ledger accounts per VAT zone (domestic, EU, abroad, domestic-without-VAT) and is required on every product.

OperationEndpointScope
ListGET /v1/product-groupsproducts-read
GetGET /v1/product-groups/{id}products-read
CreatePOST /v1/product-groupsproducts-write
UpdatePATCH /v1/product-groups/{id}products-write
DeleteDELETE /v1/product-groups/{id}products-write

All four account fields are required: domesticAccountId, euAccountId, abroadAccountId, and domesticWithoutVatAccountId. The domestic, EU, and abroad accounts must each reference a ledger account carrying a VAT code valid for sales; the domestic-without-VAT account has no VAT requirement. Ledger accounts and VAT codes are available over the public API. See the create operation.

TerminalCode
curl -X POST 'https://api.ledgerbee.com/api/v1/product-groups' \ -H 'x-api-key: <your-key>' \ -H 'Content-Type: application/json' \ -d '{ "number": "PG001", "name": "Services", "domesticAccountId": "0197a943-2325-7829-b835-b6c71a293010", "euAccountId": "0197a943-2325-7829-b835-b6c71a293011", "abroadAccountId": "0197a943-2325-7829-b835-b6c71a293012", "domesticWithoutVatAccountId": "0197a943-2325-7829-b835-b6c71a293013" }'

Products

A product is a catalogue item belonging to a product group. GET /v1/products/{id} returns the product with its prices array, so the get response is where you read the priceId for a billing-document line. The list (GET /v1/products) is a lean index and omits the prices array; get a single product to read its prices.

OperationEndpointScope
List (no prices)GET /v1/productsproducts-read
Get (with prices)GET /v1/products/{id}products-read
CreatePOST /v1/productsproducts-write
UpdatePATCH /v1/products/{id}products-write
ArchivePOST /v1/products/{id}/archiveproducts-write
DeleteDELETE /v1/products/{id}products-write

Archive a product once it is in use: the product and every price on it go archived, nothing new can be sold against it, and the subscriptions and documents already referencing it keep resolving. Delete is for a product nothing references — one that is locked cannot be deleted. There is no unarchive.

productGroupId is required and must reference an existing group. productNumber is unique per company. An optional initialPrice creates, activates, and sets-default a first price in the same call. See the create operation.

TerminalCode
curl -X POST 'https://api.ledgerbee.com/api/v1/products' \ -H 'x-api-key: <your-key>' \ -H 'Content-Type: application/json' \ -d '{ "productNumber": "P001", "name": "Web hosting", "unit": "pcs", "productGroupId": "0197a943-2325-7829-b835-b6c71a293020" }'

Product prices

A price belongs to a product. Its id is the priceId used on invoice, quote, and order-confirmation lines.

OperationEndpointScope
CreatePOST /v1/product-pricesproducts-write
GetGET /v1/product-prices/{id}products-read
UpdatePATCH /v1/product-prices/{id}products-write
DeleteDELETE /v1/product-prices/{id}products-write
ActivatePOST /v1/product-prices/{id}/activateproducts-write
DisablePOST /v1/product-prices/{id}/disableproducts-write
ArchivePOST /v1/product-prices/{id}/archiveproducts-write
Set defaultPOST /v1/product-prices/{id}/set-defaultproducts-write

A price is created active and is usable on a document immediately; pass status: "draft" to stage it instead and activate it later. The default price of a product cannot be disabled, archived, or deleted. A price already used on a subscription or invoice is locked and only a limited field set can change. See the create operation.

TerminalCode
curl -X POST 'https://api.ledgerbee.com/api/v1/product-prices' \ -H 'x-api-key: <your-key>' \ -H 'Content-Type: application/json' \ -d '{ "productId": "0197a943-2325-7829-b835-b6c71a293030", "billingPeriodType": "one_time", "pricingModel": "flat_rate", "unitAmount": "199.00", "currency": "DKK" }'

Pricing models

billingPeriodType and pricingModel together describe how a price bills.

FieldValueMeaning
billingPeriodTypeone_timeA one-off charge. No billing interval.
billingPeriodTyperecurringBills each interval. Requires billingInterval and a Subscription license.
billingPeriodTypeusageMetered. Requires meterId, a billing interval, and the Subscription license.
pricingModelflat_rateOne unitAmount. No tiers.
pricingModelpackageExactly one tier.
pricingModelvolume / graduatedOne or more tiers; the last tier must be open-ended (omit its toQuantity).

A recurring or usage price requires the matching license. A request without it is rejected with LICENSE.REQUIRED. Meters are available over the public API.

Errors

ConditionError codeFix
Group number already usedPRODUCT_GROUP_NUMBER_EXISTSUse a unique number.
Account missing / wrong typePRODUCT_GROUP_INVALID_ACCOUNT_IDReference an existing sales account.
Sales account has no VAT codePRODUCT_GROUP_ACCOUNT_MUST_HAVE_VAT_CODEPick a domestic/EU/abroad account with a VAT code.
Product number already usedPRODUCT_NUMBER_EXISTSUse a unique productNumber.
Product group not foundPRODUCT_GROUP_NOT_FOUNDCreate the group first, then reference its id.
Recurring/usage price without the licenseLICENSE.REQUIREDThe tenant needs the Subscription license.
Disabling, deleting, or editing a restricted field on a price already referenced by an invoice, credit note, subscription, or planPRODUCT_PRICE_IS_LOCKEDA locked price only allows nickname, amount, currency, tiers, and archiving to change. Create a new price and set it as default instead.
Last modified on September 13, 2026
Card paymentsProduct Entitlements
On this page
  • Product groups
  • Products
  • Product prices
    • Pricing models
  • Errors