LedgerBee Developer
  • Getting started
  • Conventions
  • Products
  • Advisor firms
  • Configuration
  • API Reference
ErrorsVersioning & DeprecationRate limitsPaginationIdempotencyMetadata
Conventions

Metadata

Metadata is a map of string keys to string values you attach to a record for your own purposes: an id in your CRM or ERP, a segment, an owner, a flag your integration reads. LedgerBee stores the map with the record, returns it on every read, and lets you filter list endpoints on it. LedgerBee does not interpret the values.

The map

Code
{ "crmSegment": "enterprise", "accountOwner": "jane" }
LimitValue
Entries per record50
Key length128 characters
Value length500 characters
Filter pairs per list request10

Keys are trimmed before they are stored, and a key must not be empty after trimming. Keys are compared case-insensitively: Tier and tier are the same key, and a request that carries both is rejected with METADATA_DUPLICATE_KEY. Values are stored as sent, including an empty string.

Where metadata is available

ResourceWriteReadFilter
CustomersPOST /v1/customers, PATCH /v1/customers/{id}GET /v1/customers, GET /v1/customers/{id}GET /v1/customers
Customer groupsIn the LedgerBee appGET /v1/customers/groupsGET /v1/customers/groups
SuppliersPOST /v1/suppliersGET /v1/suppliersGET /v1/suppliers
Vendors (deprecated alias of suppliers)POST /v1/vendorsGET /v1/vendorsGET /v1/vendors
ProductsPOST /v1/products, PATCH /v1/products/{id}GET /v1/products, GET /v1/products/{id}GET /v1/products

Reads and filters use the resource's read scope (customers-read, suppliers-read, products-read); writes use its write scope (customers-write, suppliers-write, products-write). See the API Reference for each operation.

Suppliers and vendors are the same records under two route families, so metadata written through one is returned by the other, under the same metadata field name. Supplier metadata is also editable in the LedgerBee app.

A customer group's metadata is set in the LedgerBee app and is read-only over the API. A key holding only the checkout scope receives each group slimmed to id, number, and name; the metadata requires customers-read.

Writing metadata

Send metadata on a create request to store the map with the new record.

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", "metadata": { "sku": "WH-100", "catalogSection": "hosting" } }'

The map is validated before the record is created, so an invalid map is rejected and no record exists. The key __proto__ is reserved and cannot be written. The create responses for customers, suppliers and vendors carry only the new record's id and number; read the metadata back through the single-record or list endpoint. The product create response carries the map.

On an update, metadata replaces the stored map wholesale. Send the complete map you want to end up with; a key you leave out is removed. An empty object clears every entry. Omit the field to leave the metadata unchanged.

TerminalCode
curl -X PATCH 'https://api.ledgerbee.com/api/v1/customers/0197a943-2325-7829-b835-b6c71a293040' \ -H 'x-api-key: <your-key>' \ -H 'Content-Type: application/json' \ -d '{ "metadata": { "crmSegment": "enterprise" } }'

To change one key, read the current map, change the key, and send the whole map back.

Reading metadata

Every response that returns the full record carries its metadata map: the single-record read, the product create and update responses, and the customer update response. List endpoints return it on each item, so a sync can read the map without a per-record request. A record with no metadata returns {}. The customer, supplier and vendor create responses return only the id and number, so read the record afterwards for its map.

Filtering a list

Pass one or more metadata[key]=value query parameters to a list endpoint. A record matches only when its metadata carries every given key with exactly the given value: matching is exact on both key and value, and several pairs combine with AND. At most 10 pairs per request; more returns 400 METADATA_TOO_MANY_FILTERS.

TerminalCode
curl -G 'https://api.ledgerbee.com/api/v1/suppliers' \ -H 'x-api-key: <your-key>' \ --data-urlencode 'metadata[erpVendorId]=V-10042' \ --data-urlencode 'metadata[tier]=preferred'

On GET /v1/products the filter composes with search and productGroupId, and total counts the filtered set. On GET /v1/customers it composes with customerNumber, externalSystemId, and parentCustomerId.

The unfiltered customer, customer group, supplier, and vendor lists are cached for 5 seconds. A filtered list is never cached, so a metadata write is visible on the next filtered read. The product list is not cached.

Lifecycle

Archiving a product keeps its metadata, and the archive response carries it. Deleting a product deletes its metadata with it. A customer or supplier deleted in the LedgerBee app loses its metadata the same way.

Errors

ConditionError codeFix
A key is empty after trimmingMETADATA_KEY_REQUIREDGive every entry a non-empty key.
A key is longer than 128 charactersMETADATA_KEY_TOO_LONGShorten the key.
A value is longer than 500 charactersMETADATA_VALUE_TOO_LONGShorten the value, or store a reference to it.
More than 50 entriesMETADATA_TOO_MANY_ENTRIESKeep the map to 50 entries.
Two keys are the same after trimming and case-foldingMETADATA_DUPLICATE_KEYSend each key once.
More than 10 metadata[key] pairs on a list requestMETADATA_TOO_MANY_FILTERSFilter on at most 10 pairs and narrow further client-side.
A __proto__ key in a create or update metadata map, or a metadata[__proto__] filter pairMETADATA_KEY_RESERVEDUse another key; this one cannot be a property of a JSON object.

All are returned as 400 in the error envelope described in Errors.

Last modified on November 6, 2026
Idempotency
On this page
  • The map
  • Where metadata is available
  • Writing metadata
  • Reading metadata
  • Filtering a list
  • Lifecycle
  • Errors
JSON