Price lists
Create customer-specific EUR prices, resolve catalog precedence and reprice draft documents without rewriting history.
Price lists override catalog sales prices for a company. They are tenant-scoped,
EUR-only and use four-decimal unit prices so measured products remain precise.
They belong to the Products plan module but use dedicated API-key scopes:
price_lists:read and price_lists:write.
Lifecycle and endpoints
| Operation | Endpoint | Scope |
|---|---|---|
| List / create | GET, POST /v1/price-lists | price_lists:read / price_lists:write |
| Compact selector options | GET /v1/price-lists/options | price_lists:read |
| Read / update / delete | GET, PUT, DELETE /v1/price-lists/{priceList} | read / write |
| List / upsert items | GET, POST /v1/price-lists/{priceList}/items | read / write |
| Delete an item | DELETE /v1/price-lists/{priceList}/items/{item} | price_lists:write |
| Resolve effective price | POST /v1/price-lists/resolve | price_lists:read |
| Resolve up to 100 selections | POST /v1/price-lists/resolve-many | price_lists:read |
| Reassign a retired item | POST /v1/price-lists/{priceList}/items/{item}/reassign | price_lists:write |
| Permanently purge a retired item | POST /v1/price-lists/{priceList}/items/{item}/purge | price_lists:write |
A list starts active; PUT can switch between active and inactive.
Inactive lists remain readable for history but cannot be selected for a new
client or document. A list cannot be deleted while assigned to any client or
draft. Both list and item deletion are irreversible.
curl -X POST https://api.factuarea.com/v1/price-lists \
-H "Authorization: Bearer $FACTUAREA_API_KEY" \
-H "Idempotency-Key: 01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a01" \
-H "Content-Type: application/json" \
-d '{"name":"Wholesale 2026"}'Names are unique within the company.
Add or replace one price
POST /v1/price-lists/{priceList}/items is an upsert. A target can be named in
three mutually exclusive forms:
- a stored commercial configuration (
configuration_id); - a normalized selection (
selection_signature, 64 hexadecimal characters); - the legacy product + optional variant/presentation crossing.
{
"product_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a20",
"configuration_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a21",
"unit_price": "79.5000",
"price_unit": "C62"
}Send an item's id to update that exact item. Reusing a conceptual target with
a different item id is rejected. price_unit must be compatible with the
target. Listing accepts search over the visible product, variant,
presentation, configuration and option-value labels, plus
status=active|retired.
Resolution precedence
For a new selection the resolver applies this stable order:
- price-list item targeting the stored configuration;
- price-list item targeting the selection signature;
- legacy price-list item (variant + presentation, variant, presentation, product, from most to least specific);
- configuration's own final commercial price;
- presentation's own commercial price;
- variant's own base-unit price;
- product base-unit price.
Every price-list entry wins over every own catalog price. Option adjustments are added only when the winning source has not already absorbed them.
POST /v1/price-lists/resolve{
"price_list_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a02",
"product_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a20",
"configuration_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a21",
"selection_signature": "b7293f69a30c36b77f6d5ba27f2bc4f1f68e97e447ab8776bf080531d0a1dcee",
"option_value_ids": ["01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a22"]
}The response identifies the source, effective unit_price, price_unit, base
unit and selected price-list snapshot. It also returns unit_semantics,
source_amount, option_adjustment_total and
option_adjustments_absorbed, so a preview can detect whether option
adjustments were absorbed or added. Omitting price_list_id falls back through
the own catalog prices. A base-unit source is converted once by a fixed
presentation; a commercial-unit source is never converted.
POST /v1/price-lists/resolve-many resolves up to 100 complete selections in
one read-only request and optionally compares each result with
current_unit_price. Match results by index, not response order. An invalid
target is attributed to targets.<n> so one bad line does not hide which
selection needs attention.
Retired targets
When a confirmed catalog deletion invalidates a target, its price-list entry is retired, not silently redirected to a broader product price. It retains its amount, retirement reason/date and frozen target snapshot, but is excluded from resolution, assignments and statistics.
Use .../{item}/reassign to create a new active entry for a live target;
the retired entry remains immutable history. .../{item}/purge permanently
deletes that retired history and requires confirm: true, an
Idempotency-Key, and an irreversible confirmation in clients that honor
x-irreversible. Active or unknown entries cannot be purged.
Contacts, drafts and repricing
Set a contact’s sales default through PUT /v1/contacts/{contact}/customer-profile
with default_price_list_uuid; new sales documents can carry
price_list_id. Invoices, quotes, pro-formas, delivery notes and recurring
templates return both the list id/name snapshot and the resolved catalog fields
on each line.
Changing the price list of a non-empty draft requires an explicit
reprice_strategy:
| Strategy | Effect |
|---|---|
existing_catalog_lines | Re-resolve existing lines whose source is price_list, variant or product. |
future_lines_only | Preserve every existing line; apply the new list only to future selections. |
Manual prices, supplier-offer costs and pack snapshots are never silently repriced. Issued/historical documents are immutable snapshots and are not affected by later price-list changes.
Errors and MCP
Branch on these error codes, not the Spanish message:
price_list_not_found, duplicate_price_list_name, inactive_price_list,
invalid_price_list_item and price_list_in_use.
The MCP Pricing domain has 13 matching tools: list_price_lists,
create_price_list, get_price_list, update_price_list, delete_price_list,
get_price_list_options, list_price_list_items, upsert_price_list_item,
delete_price_list_item, resolve_catalog_price, resolve_many_catalog_prices,
reassign_retired_price_list_item and purge_retired_price_list_item. OAuth consent exposes
price_lists.read and price_lists.write, so all 13 tools are available through
OAuth as well as API keys, subject to the Products plan module.
See Product catalog, Amounts & dates and the exact API Reference.
Preserve resolved line values
Keep price_unit and the resolved base/commercial quantities with the catalog snapshot. additional_description adds human-readable detail without selecting a different price. Recurring-document previews expose the resolved next invoice without persisting it; see recurring invoices and the operation’s concrete response example.