Parties
Customers and vendors: master data, activation, bank details.
| Operation | Summary | Scope | Idempotency-Key |
|---|---|---|---|
GET /v1/entities/{entity}/credit-exposure |
Get the credit exposure of customers with a credit limit | read |
|
GET /v1/entities/{entity}/parties |
List customers and vendors | read |
|
POST /v1/entities/{entity}/parties |
Create a customer or vendor | draft |
required |
GET /v1/entities/{entity}/parties/{party} |
Get a customer or vendor card | read |
|
PATCH /v1/entities/{entity}/parties/{party} |
Change a customer or vendor | draft |
|
POST /v1/entities/{entity}/parties/{party}/activate |
Activate a draft customer or vendor | draft |
|
POST /v1/entities/{entity}/parties/{party}/merge |
Merge a duplicate customer | draft |
|
POST /v1/entities/{entity}/parties/{party}/status |
Block a customer or vendor, set it inactive, or make it active again | draft |
|
POST /v1/entities/{entity}/parties/{party}/vat-check |
Check a customer's or vendor's VAT number in its public register | draft |
|
POST /v1/vat-registers/check |
Check a VAT number against its public register | draft |
GET /v1/entities/{entity}/credit-exposure
Get the credit exposure of customers with a credit limit
Every customer of the company with a credit limit, those over it first: its limit, what
it owes (receivables: open invoices less open credit notes and payments on account), its
invoices waiting for approval, what is left to invoice on its open sales orders (VAT
included), the total (exposure), the credit still available and whether it is over the
limit. All in the customer's currency: an amount in another currency is converted at today's
ECB rate (today where the company is). An invoice that would take a customer above its limit
waits for a second person when it is submitted; a sales order is not confirmed. Read-only;
404 for an unknown entity.
| Required scope | read (admin implies every scope) |
| Operation id | get_credit_exposure_v1_entities__entity__credit_exposure_get |
Parameters
| In | Name | Type | Required | Description |
|---|---|---|---|---|
| path | entity |
string | yes | Entity code, e.g. CH01 (GET /v1/entities). |
| query | format |
"csv" | "json" |
json (default) or csv: one row per customer with the columns customer, name, currency, credit_limit, receivables, pending_invoices, open_orders, exposure, available, over_limit and note, meaning what the JSON fields of the same names mean. (default "json") |
|
| query | download |
boolean | csv: true sends the file as an attachment; false inline. (default false) |
Example request
curl "$ERP_URL/v1/entities/CH01/credit-exposure" \
-H "Authorization: Bearer $ERP_KEY"
Responses
| Status | Meaning | Body |
|---|---|---|
| 200 | JSON (the report) or CSV (one row per customer). | CreditExposure, text/csv |
| 401 | Missing or invalid API key (unauthorized). |
ErrorEnvelope |
| 403 | The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). |
ErrorEnvelope |
| 404 | The resource does not exist, or belongs to another organization (not_found). |
ErrorEnvelope |
| 422 | Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. |
HTTPValidationError |
Example response (shape)
{
"entity": "string",
"as_of": "2026-09-21",
"customers": [
{
"party": "string",
"name": "string",
"currency": "string",
"credit_limit": "string",
"receivables": "string",
"pending_invoices": "string",
"open_orders": "string",
"exposure": "string",
"available": "string",
"over_limit": true,
"note": "string"
}
]
}
GET /v1/entities/{entity}/parties
List customers and vendors
Customers and vendors of an entity, ordered by code, with their open balances
(open and overdue amounts of posted documents per currency; credit notes count negative)
and the requests waiting for a second person (pending_actions). All filters combine
with AND. Someone who sees only their own or their team's records gets the customers those
people own or have deals with (and every vendor).
| Required scope | read (admin implies every scope) |
| Operation id | list_parties_v1_entities__entity__parties_get |
Parameters
| In | Name | Type | Required | Description |
|---|---|---|---|---|
| path | entity |
string | yes | Entity code, e.g. CH01 (GET /v1/entities). |
| query | kind |
"customer" | "vendor" or null |
customer or vendor; default: both. |
|
| query | q |
string or null | Text in the name, VAT number (any part), code (starts with) or town (starts with); case-insensitive. | |
| query | status |
"active" | "blocked" | "draft" | "inactive" or null |
active, draft (not yet activated by a second person), blocked or inactive; default: all. |
|
| query | country |
string or null | ISO 3166-1 alpha-2 country, e.g. DE. (pattern ^[A-Za-z]{2}$) |
|
| query | vat_number |
string or null | Part of the VAT number or UID; spaces, dots and case are ignored, so 811569 finds DE 811 569 869. |
|
| query | parent |
string (uuid) or null | Only the subsidiaries of this party (its id): those naming it parent. | |
| query | owner_user_id |
string (uuid) or null | Only the customers this person owns (GET /v1/people). |
|
| query | as_of |
string (date) or null | Day the overdue amounts are counted to (ISO 8601, e.g. 2026-09-30); default today where the entity is. |
|
| query | limit |
integer | Most parties returned, 1 to 1000. (min 1; max 1000; default 1000) |
Example request
curl "$ERP_URL/v1/entities/CH01/parties" \
-H "Authorization: Bearer $ERP_KEY"
Responses
| Status | Meaning | Body |
|---|---|---|
| 200 | OK | array of PartyRow |
| 401 | Missing or invalid API key (unauthorized). |
ErrorEnvelope |
| 403 | The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). |
ErrorEnvelope |
| 404 | The resource does not exist, or belongs to another organization (not_found). |
ErrorEnvelope |
| 422 | Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. |
HTTPValidationError |
Example response (shape)
[
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"kind": "string",
"code": "string",
"name": "string",
"country": "string",
"subdivision": "string",
"vat_number": "string",
"business": true,
"split_payment": false,
"withholding_code": "string",
"withholding_rate": "string",
"vat_unverified": false,
"currency": "string",
"payment_terms_days": 1,
"email": "string",
"iban": "string",
"street": "string",
"building_number": "string",
"postal_code": "string",
"town": "string",
"status": "active",
"group_entity_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"leitweg_id": "string",
"electronic_address": "string",
"electronic_address_scheme": "string",
"cash_discount_percent": "string",
"cash_discount_days": 1,
"credit_limit": "string",
"bank_accounts": [
{
"iban": "string",
"bic": null,
"label": null
}
],
"contacts": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "string",
"role": null,
"email": null,
"phone": null
}
],
"parent_party_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"custom": {},
"owner_user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"language": "string",
"default_account_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"created_at": "2026-09-21T09:30:00Z",
"balances": [
{
"currency": "string",
"open": "string",
"overdue": "string",
"on_account": "0.00",
"open_documents": 1,
"overdue_documents": 1
}
],
"pending_actions": [
"string"
]
}
]
POST /v1/entities/{entity}/parties
Create a customer or vendor
Create a customer or vendor in an entity, identified by kind and code. Without a
code it gets the company's next number (C-00001, V-00001, counted per company and kind
without gaps); a code given is kept as written. A draft
party is neither booked nor paid until a second person activates it. By default a customer
is active; a person's new vendor is a draft with an activation request, an agent's vendor
(or any party with bank details an agent creates) a plain draft (see the activate
operation). The IBAN is checked and stored without spaces. Refuses with 409 when a
code given exists for that kind, 422 for an invalid IBAN, Leitweg-ID or cash discount terms, a
currency without exchange rates or an IBAN of your own company, 404 for an unknown entity
or account, and 403 when the approval policy denies activation. The answer lists existing
customers or vendors it may duplicate (same VAT number, an IBAN in common or the same
name); the party is created anyway.
| Required scope | draft (admin implies every scope) |
| Idempotency-Key | required |
| Operation id | create_party_v1_entities__entity__parties_post |
Parameters
| In | Name | Type | Required | Description |
|---|---|---|---|---|
| path | entity |
string | yes | Entity code, e.g. CH01 (GET /v1/entities). |
Request body
application/json (required): PartyInput
| Field | Type | Required | Description |
|---|---|---|---|
kind |
"customer" | "vendor" |
yes | customer or vendor; a code is unique per kind in an entity. |
code |
string or null | Leave it out and the party gets the company's next number: C-00001 for a customer, V-00001 for a vendor, counted per company without gaps. Give one (up to 40 characters, e.g. the number of the system before) only to keep it; it is how documents and URLs name the party, and never changes. (min length 1; max length 40) |
|
name |
string | yes | Legal name of the customer or vendor. |
country |
string or null | ISO 3166-1 alpha-2 country code, e.g. DE; drives the place of supply of the tax determination. Omitted: the country its VAT number names by its prefix, else the company's. (pattern ^[A-Z]{2}$) |
|
subdivision |
string or null | ISO 3166-2 subdivision where it matters for tax, e.g. DE-BY, or a US customer's state (US-CA), which decides its sales tax. A Spanish postal code gives it when left empty: 35 and 38 the Canary Islands (ES-CN), 51 Ceuta (ES-CE), 52 Melilla (ES-ML); one of another country, or that the postal code contradicts, is refused (422 party_subdivision_mismatch). (pattern ^[A-Z]{2}-[A-Z0-9]{1,3}$) |
|
vat_number |
string or null | VAT or UID number, e.g. DE811569869 or CHE-116.281.710 MWST; for a party of an EU country, the UK, Norway, Switzerland or Liechtenstein its format is checked, and its check digit for CH, DE, FR, IT, ES and BE (422 vat_number_invalid). |
|
business |
boolean | true for a business (B2B), false for a private person (B2C); affects how VAT is determined on sales: a sale to another VAT area goes under the reverse charge only to a business, and a customer with a VAT number counts as one. Between two EU countries only the VAT number makes the customer a business: without it the sale is taxed as one to a private person. (default true) |
|
split_payment |
boolean | Customers of an Italian company: true for one under split payment (scissione dei pagamenti, DPR 633/1972 art. 17-ter: public bodies and the companies the law lists). Its invoices show the VAT but it owes only the net amount and pays the VAT to the State; the VAT returns leave that VAT out. Default false. (default false) |
|
currency |
string or null | ISO 4217 currency of the party's documents and payments, e.g. EUR: functional or with exchange rates (422 party_currency_without_rates). Omitted: its country's currency when the company has exchange rates for it, else the company's. (pattern ^[A-Z]{3}$) |
|
withholding_code |
string or null | Vendors: the withholding tax code kept back from its bills and paid to the tax authority by the company (GET /v1/entities/{entity}/withholding-tax/codes lists the codes of the company's country, e.g. IT-RA-20), or custom with withholding_rate; null for none. Changing it once a bill of the vendor is posted waits for a second person. (max length 20) |
|
withholding_rate |
decimal string or null | With withholding_code custom: the rate in percent of a bill's net amount before VAT, e.g. 18.5; a code of the table takes its own rate. (greater than 0) |
|
payment_terms_days |
integer | Days from the document date to the due date, 0 to 365; default 30. (min 0; max 365; default 30) |
|
default_account |
string or null | Revenue/expense account code. | |
email |
string or null | Contact email address. | |
iban |
string or null | IBAN payments to the party go to, stored without spaces; one of your own companies' accounts is refused (422 party_own_bank_account). |
|
bank_accounts |
array of PartyBankAccount |
Further accounts payments may go to (a QR-IBAN). | |
language |
"de" | "en" | "fr" | "it" | "rm" | "sv" or null |
Correspondence language. Omitted: its country's, where the country has one of ours (DE and AT de, FR fr, IT it, SE sv, GB and US en); none for a country of several (CH, BE, CA): set it there. |
|
contacts |
array of NewContact |
People at the party; later ones are added with POST /v1/contacts. |
|
parent |
string or null | Code (or id) of the company it belongs to, of the same kind. | |
custom |
map of string | number | integer | boolean or null | Values of the organization's own fields (GET /v1/custom-fields) by key, e.g. {"industry": "Retail"}: text, a number, a date (2026-10-23), true or false, or one of a choice field's choices. On a change only the keys sent change; null removes a value. |
|
owner_user_id |
string (uuid) or null | Customers: the sales person who looks after it (GET /v1/people); a vendor has none. Who sees only their own or their team's records gives it to one of those people. Omitted: you. |
|
street |
string or null | Street of the postal address (up to 70 characters); used on QR-bills and XRechnung. (max length 70) | |
building_number |
string or null | Building number of the postal address (up to 16 characters). (max length 16) | |
postal_code |
string or null | Postal code of the address (up to 16 characters). (max length 16) | |
town |
string or null | Town of the address (up to 35 characters). (max length 35) | |
leitweg_id |
string or null | Customers: Leitweg-ID of a German public buyer (XRechnung buyer reference). | |
electronic_address |
string or null | E-invoicing address (BT-34/BT-49), e.g. an email or Peppol id. | |
electronic_address_scheme |
string or null | EAS code of the electronic address, e.g. EM (email), 0204, 9930. | |
status |
"active" | "draft" |
draft until a second person activates it. A vendor (or a party with bank details) created by an agent, and a vendor created from an e-invoice, start as draft; otherwise 'active' needs the approval policy to allow activate_party. (default "active") |
|
cash_discount_percent |
decimal string or null | Cash discount (Skonto) percent if paid within cash_discount_days, e.g. 2. (greater than 0) | |
cash_discount_days |
integer or null | Days within which the cash discount applies, 0 to 365. (min 0; max 365) | |
credit_limit |
decimal string or null | Customers: the most the customer may owe, in its currency (currency), e.g. 100000; null for no limit. Its open invoices, its invoices waiting for approval and what is left to invoice on its open sales orders count; above it an invoice waits for a second person and a sales order is not confirmed. (min 0) |
|
source_sha256 |
string or null | SHA-256 of the bill this vendor was read from (the bill wizard sends the sha256 of POST /v1/agents/bill-capture/read). The audit entry and the activation request then say that its bank details come from that invoice, and what the public VAT register said about its number: the approver sees what nobody has confirmed. (pattern ^[0-9a-f]{64}$) |
Example request
curl -X POST "$ERP_URL/v1/entities/CH01/parties" \
-H "Authorization: Bearer $ERP_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"building_number": "1268",
"contacts": [
{
"first_name": "Anna",
"last_name": "Muster",
"role": "Buchhaltung"
}
],
"country": "CH",
"currency": "CHF",
"iban": "CH44 3199 9123 0008 8901 2",
"kind": "vendor",
"language": "de",
"name": "Neu Handel AG",
"payment_terms_days": 20,
"postal_code": "2501",
"street": "Rue du Lac",
"town": "Biel"
}'
Responses
| Status | Meaning | Body |
|---|---|---|
| 201 | Created | PartyCreated |
| 401 | Missing or invalid API key (unauthorized). |
ErrorEnvelope |
| 403 | The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). |
ErrorEnvelope |
| 404 | The resource does not exist, or belongs to another organization (not_found). |
ErrorEnvelope |
| 409 | The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). |
ErrorEnvelope |
| 422 | Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. |
HTTPValidationError |
Example response (shape)
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"kind": "string",
"code": "string",
"name": "string",
"country": "string",
"subdivision": "string",
"vat_number": "string",
"business": true,
"split_payment": false,
"withholding_code": "string",
"withholding_rate": "string",
"vat_unverified": false,
"currency": "string",
"payment_terms_days": 1,
"email": "string",
"iban": "string",
"street": "string",
"building_number": "string",
"postal_code": "string",
"town": "string",
"status": "active",
"group_entity_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"leitweg_id": "string",
"electronic_address": "string",
"electronic_address_scheme": "string",
"cash_discount_percent": "string",
"cash_discount_days": 1,
"credit_limit": "string",
"bank_accounts": [
{
"iban": "string",
"bic": "string",
"label": "string"
}
],
"contacts": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "string",
"role": "string",
"email": "string",
"phone": "string"
}
],
"parent_party_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"custom": {},
"owner_user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"language": "string",
"default_account_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"created_at": "2026-09-21T09:30:00Z",
"possible_duplicates": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"code": "string",
"name": "string",
"status": "string",
"same": [
"iban"
],
"message": "string"
}
]
}
GET /v1/entities/{entity}/parties/{party}
Get a customer or vendor card
A customer or vendor by code or id: master data (structured address, language,
IBAN and further bank accounts, contacts, electronic address, Leitweg-ID), who created
and activated it, open balances per currency, pending requests with who asked and, for
bank details, the current and proposed values, payment_blockers, the reasons no
payment to it can be released now, and for a customer with a credit limit its credit:
what it owes and has on order against the limit, and the credit still available. 404 when
not found; 409 when the code names both a customer and a vendor and kind is missing.
| Required scope | read (admin implies every scope) |
| Operation id | get_party_v1_entities__entity__parties__party__get |
Parameters
| In | Name | Type | Required | Description |
|---|---|---|---|---|
| path | entity |
string | yes | Entity code, e.g. CH01 (GET /v1/entities). |
| path | party |
string | yes | Customer or vendor code, e.g. C-DE or V-BM. |
| query | kind |
"customer" | "vendor" or null |
customer or vendor; needed when one code names both a customer and a vendor (otherwise 409). |
|
| query | as_of |
string (date) or null | Day the overdue amounts are counted to (ISO 8601, e.g. 2026-09-30); default today where the entity is. |
Example request
curl "$ERP_URL/v1/entities/CH01/parties/C-DE" \
-H "Authorization: Bearer $ERP_KEY"
Responses
| Status | Meaning | Body |
|---|---|---|
| 200 | OK | PartyCard |
| 401 | Missing or invalid API key (unauthorized). |
ErrorEnvelope |
| 403 | The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). |
ErrorEnvelope |
| 404 | The resource does not exist, or belongs to another organization (not_found). |
ErrorEnvelope |
| 422 | Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. |
HTTPValidationError |
Example response (shape)
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"kind": "string",
"code": "string",
"name": "string",
"country": "string",
"subdivision": "string",
"vat_number": "string",
"business": true,
"split_payment": false,
"withholding_code": "string",
"withholding_rate": "string",
"vat_unverified": false,
"currency": "string",
"payment_terms_days": 1,
"email": "string",
"iban": "string",
"street": "string",
"building_number": "string",
"postal_code": "string",
"town": "string",
"status": "active",
"group_entity_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"leitweg_id": "string",
"electronic_address": "string",
"electronic_address_scheme": "string",
"cash_discount_percent": "string",
"cash_discount_days": 1,
"credit_limit": "string",
"bank_accounts": [
{
"iban": "string",
"bic": "string",
"label": "string"
}
],
"contacts": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "string",
"role": "string",
"email": "string",
"phone": "string"
}
],
"parent_party_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"custom": {},
"owner_user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"language": "string",
"default_account_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"created_at": "2026-09-21T09:30:00Z",
"balances": [
{
"currency": "string",
"open": "string",
"overdue": "string",
"on_account": "0.00",
"open_documents": 1,
"overdue_documents": 1
}
],
"pending_actions": [
"string"
],
"created_by": {},
"activated_by": {},
"activated_at": "2026-09-21T09:30:00Z",
"pending": [
{
"approval_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"action": "string",
"requested_by": {},
"requested_at": "2026-09-21T09:30:00Z",
"reason": "string",
"current": {},
"proposed": {}
}
],
"payment_blockers": [
{
"code": "string",
"message": "string",
"details": {}
}
],
"vat_check": {
"registry": "ch_uid",
"status": "invalid",
"vat_number": "string",
"name": "string",
"name_matches": true,
"reference": "string",
"checked_at": "2026-09-21T09:30:00Z",
"checked_by": {}
},
"credit": {
"party": "string",
"name": "string",
"currency": "string",
"credit_limit": "string",
"receivables": "string",
"pending_invoices": "string",
"open_orders": "string",
"exposure": "string",
"available": "string",
"over_limit": true,
"note": "string"
},
"parent": {
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"code": "string",
"name": "string"
},
"owner": {
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"email": "string",
"name": "string"
},
"merged_into": {
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"code": "string",
"name": "string"
},
"subsidiaries": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"code": "string",
"name": "string"
}
],
"possible_duplicates": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"code": "string",
"name": "string",
"status": "string",
"same": [
"iban"
],
"message": "string"
}
],
"open_support_cases": 0,
"breached_support_cases": 0,
"active_subscriptions": 0,
"open_opportunities": 0
}
PATCH /v1/entities/{entity}/parties/{party}
Change a customer or vendor
Change a customer or vendor, e.g. its address, contacts or Leitweg-ID. Omitted or
null fields stay as they are; "" clears a text field; contacts and bank_accounts
replace the whole list.
New bank details (iban, bank_accounts) are not applied: they become a request
that a second person approves (pending on the card), and payments to the party are
blocked meanwhile. Once a document of the party is posted or pending approval, a new
name, vat_number, country, subdivision, currency or credit_limit is such a
request too. Only humans change bank or key details (403 for agents); a second open request
of the same kind answers 409. A credit limit is for customers only (422,
credit_limit_customers_only). status: active does what the activate operation does.
| Required scope | draft (admin implies every scope) |
| Idempotency-Key | not used |
| Operation id | update_party_v1_entities__entity__parties__party__patch |
Parameters
| In | Name | Type | Required | Description |
|---|---|---|---|---|
| path | entity |
string | yes | Entity code, e.g. CH01 (GET /v1/entities). |
| path | party |
string | yes | Customer or vendor code, e.g. C-DE or V-BM. |
| query | kind |
"customer" | "vendor" |
yes | customer or vendor; required. |
Request body
application/json (required): PartyUpdate
| Field | Type | Required | Description |
|---|---|---|---|
name |
string or null | New legal name; once the party is past draft, or a document of it is posted or pending approval, this waits for a second person. | |
country |
string or null | New ISO 3166-1 alpha-2 country; waits for a second person like name. (pattern ^[A-Z]{2}$) |
|
subdivision |
string or null | ISO 3166-2 subdivision where it matters for tax, e.g. DE-BY, or a US customer's state (US-CA); empty clears it. A Spanish postal code gives it as on create (422 party_subdivision_mismatch on a contradiction); a change waits for a second person like name. (pattern ^([A-Z]{2}-[A-Z0-9]{1,3})?$) |
|
vat_number |
string or null | New VAT or UID number (format checked as on create, 422); waits for a second person like name. |
|
business |
boolean or null | true for a business (B2B), false for a private person (B2C); affects how VAT is determined on sales: a sale to another VAT area goes under the reverse charge only to a business, and a customer with a VAT number counts as one. Between two EU countries only the VAT number makes the customer a business: without it the sale is taxed as one to a private person. |
|
split_payment |
boolean or null | Customers of an Italian company: true for one under split payment (DPR 633/1972 art. 17-ter); applies to invoices drafted from then on. |
|
currency |
string or null | New ISO 4217 currency: the functional currency or one with exchange rates (422 party_currency_without_rates); waits for a second person like name. (pattern ^[A-Z]{3}$) |
|
email |
string or null | Contact email address. | |
iban |
string or null | New IBAN, stored without spaces. It is not applied at once: a second person must approve it and payments to the party are blocked meanwhile. "" clears it. |
|
bank_accounts |
array of PartyBankAccount or null |
New list of further bank accounts; replaces the list. Waits for a second person's approval like iban. |
|
language |
"de" | "en" | "fr" | "it" | "rm" | "sv" | "" or null |
Correspondence language (de, fr, it, en, sv, rm); "" clears. |
|
parent |
string or null | Code (or id) of the company it belongs to; "" clears it. |
|
custom |
map of string | number | integer | boolean or null or null | Values of the organization's own fields (GET /v1/custom-fields) by key, e.g. {"industry": "Retail"}: text, a number, a date (2026-10-23), true or false, or one of a choice field's choices. On a change only the keys sent change; null removes a value. |
|
owner_user_id |
string (uuid) or null | New owner. Customers: the sales person who looks after it (GET /v1/people); a vendor has none. Who sees only their own or their team's records gives it to one of those people. |
|
withholding_code |
string or null | Vendors: the withholding tax code kept back from its bills and paid to the tax authority by the company (GET /v1/entities/{entity}/withholding-tax/codes lists the codes of the company's country, e.g. IT-RA-20), or custom with withholding_rate; "" removes it. Waits for a second person like name. (max length 20) |
|
withholding_rate |
decimal string or null | With withholding_code custom: the rate in percent of a bill's net amount before VAT. (greater than 0) |
|
payment_terms_days |
integer or null | Days from the document date to the due date, 0 to 365; waits for a second person like name. (min 0; max 365) |
|
default_account |
string or null | Code of the revenue (customer) or expense (vendor) account used on document lines that name no account, e.g. 6570. |
|
street |
string or null | Street of the postal address (up to 70 characters); used on QR-bills and XRechnung. (max length 70) | |
building_number |
string or null | Building number of the postal address (up to 16 characters). (max length 16) | |
postal_code |
string or null | Postal code of the address (up to 16 characters). (max length 16) | |
town |
string or null | Town of the address (up to 35 characters). (max length 35) | |
leitweg_id |
string or null | Customers: the Leitweg-ID of a German public buyer (validated, including its check digits); becomes the XRechnung buyer reference. | |
electronic_address |
string or null | E-invoicing address (EN 16931 BT-34 / BT-49), e.g. an email address or a Peppol id. | |
electronic_address_scheme |
string or null | Scheme of the electronic address (EAS code), e.g. EM (email), 0204 or 9930; needs an electronic_address. |
|
status |
"active" | "draft" or null |
'active' activates a draft party (as POST …/activate); 'draft' blocks its documents and payments again. | |
cash_discount_percent |
decimal string or null | 0 removes the terms; waits like name. (min 0) |
|
cash_discount_days |
integer or null | Days within which the cash discount applies, 0 to 365; waits for a second person like name. (min 0; max 365) |
|
credit_limit |
decimal string or null | Customers: the most the customer may owe, in its currency (currency), e.g. 100000; null for no limit. Its open invoices, its invoices waiting for approval and what is left to invoice on its open sales orders count; above it an invoice waits for a second person and a sales order is not confirmed. "" removes the limit. Waits for a second person like name. (min 0) |
Example request
curl -X PATCH "$ERP_URL/v1/entities/CH01/parties/C-DE?kind=value" \
-H "Authorization: Bearer $ERP_KEY" \
-H "Content-Type: application/json" \
-d '{
"language": "de",
"parent": "C-GROUP",
"payment_terms_days": 20
}'
Responses
| Status | Meaning | Body |
|---|---|---|
| 200 | OK | PartyCard |
| 401 | Missing or invalid API key (unauthorized). |
ErrorEnvelope |
| 403 | The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). |
ErrorEnvelope |
| 404 | The resource does not exist, or belongs to another organization (not_found). |
ErrorEnvelope |
| 409 | The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). |
ErrorEnvelope |
| 422 | Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. |
HTTPValidationError |
Example response (shape)
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"kind": "string",
"code": "string",
"name": "string",
"country": "string",
"subdivision": "string",
"vat_number": "string",
"business": true,
"split_payment": false,
"withholding_code": "string",
"withholding_rate": "string",
"vat_unverified": false,
"currency": "string",
"payment_terms_days": 1,
"email": "string",
"iban": "string",
"street": "string",
"building_number": "string",
"postal_code": "string",
"town": "string",
"status": "active",
"group_entity_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"leitweg_id": "string",
"electronic_address": "string",
"electronic_address_scheme": "string",
"cash_discount_percent": "string",
"cash_discount_days": 1,
"credit_limit": "string",
"bank_accounts": [
{
"iban": "string",
"bic": "string",
"label": "string"
}
],
"contacts": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "string",
"role": "string",
"email": "string",
"phone": "string"
}
],
"parent_party_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"custom": {},
"owner_user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"language": "string",
"default_account_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"created_at": "2026-09-21T09:30:00Z",
"balances": [
{
"currency": "string",
"open": "string",
"overdue": "string",
"on_account": "0.00",
"open_documents": 1,
"overdue_documents": 1
}
],
"pending_actions": [
"string"
],
"created_by": {},
"activated_by": {},
"activated_at": "2026-09-21T09:30:00Z",
"pending": [
{
"approval_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"action": "string",
"requested_by": {},
"requested_at": "2026-09-21T09:30:00Z",
"reason": "string",
"current": {},
"proposed": {}
}
],
"payment_blockers": [
{
"code": "string",
"message": "string",
"details": {}
}
],
"vat_check": {
"registry": "ch_uid",
"status": "invalid",
"vat_number": "string",
"name": "string",
"name_matches": true,
"reference": "string",
"checked_at": "2026-09-21T09:30:00Z",
"checked_by": {}
},
"credit": {
"party": "string",
"name": "string",
"currency": "string",
"credit_limit": "string",
"receivables": "string",
"pending_invoices": "string",
"open_orders": "string",
"exposure": "string",
"available": "string",
"over_limit": true,
"note": "string"
},
"parent": {
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"code": "string",
"name": "string"
},
"owner": {
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"email": "string",
"name": "string"
},
"merged_into": {
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"code": "string",
"name": "string"
},
"subsidiaries": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"code": "string",
"name": "string"
}
],
"possible_duplicates": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"code": "string",
"name": "string",
"status": "string",
"same": [
"iban"
],
"message": "string"
}
],
"open_support_cases": 0,
"breached_support_cases": 0,
"active_subscriptions": 0,
"open_opportunities": 0
}
POST /v1/entities/{entity}/parties/{party}/activate
Activate a draft customer or vendor
Activate a draft customer or vendor (four eyes).
A person with the approve scope who did not create the party activates it at once;
anyone else's call (every call, when the approval policy says so) becomes an approval
request (pending) for a second person. Agents are refused. Safe to repeat: a second
call answers 409 (already active, or already requested).
| Required scope | draft (admin implies every scope) |
| Idempotency-Key | not used |
| Operation id | activate_party_v1_entities__entity__parties__party__activate_post |
Parameters
| In | Name | Type | Required | Description |
|---|---|---|---|---|
| path | entity |
string | yes | Entity code, e.g. CH01 (GET /v1/entities). |
| path | party |
string | yes | Customer or vendor code, e.g. C-DE or V-BM. |
| query | kind |
"customer" | "vendor" or null |
customer or vendor; needed when one code names both a customer and a vendor (otherwise 409). |
Example request
curl -X POST "$ERP_URL/v1/entities/CH01/parties/C-DE/activate" \
-H "Authorization: Bearer $ERP_KEY"
Responses
| Status | Meaning | Body |
|---|---|---|
| 200 | OK | PartyCard |
| 401 | Missing or invalid API key (unauthorized). |
ErrorEnvelope |
| 403 | The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). |
ErrorEnvelope |
| 404 | The resource does not exist, or belongs to another organization (not_found). |
ErrorEnvelope |
| 409 | The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). |
ErrorEnvelope |
| 422 | Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. |
HTTPValidationError |
Example response (shape)
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"kind": "string",
"code": "string",
"name": "string",
"country": "string",
"subdivision": "string",
"vat_number": "string",
"business": true,
"split_payment": false,
"withholding_code": "string",
"withholding_rate": "string",
"vat_unverified": false,
"currency": "string",
"payment_terms_days": 1,
"email": "string",
"iban": "string",
"street": "string",
"building_number": "string",
"postal_code": "string",
"town": "string",
"status": "active",
"group_entity_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"leitweg_id": "string",
"electronic_address": "string",
"electronic_address_scheme": "string",
"cash_discount_percent": "string",
"cash_discount_days": 1,
"credit_limit": "string",
"bank_accounts": [
{
"iban": "string",
"bic": "string",
"label": "string"
}
],
"contacts": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "string",
"role": "string",
"email": "string",
"phone": "string"
}
],
"parent_party_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"custom": {},
"owner_user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"language": "string",
"default_account_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"created_at": "2026-09-21T09:30:00Z",
"balances": [
{
"currency": "string",
"open": "string",
"overdue": "string",
"on_account": "0.00",
"open_documents": 1,
"overdue_documents": 1
}
],
"pending_actions": [
"string"
],
"created_by": {},
"activated_by": {},
"activated_at": "2026-09-21T09:30:00Z",
"pending": [
{
"approval_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"action": "string",
"requested_by": {},
"requested_at": "2026-09-21T09:30:00Z",
"reason": "string",
"current": {},
"proposed": {}
}
],
"payment_blockers": [
{
"code": "string",
"message": "string",
"details": {}
}
],
"vat_check": {
"registry": "ch_uid",
"status": "invalid",
"vat_number": "string",
"name": "string",
"name_matches": true,
"reference": "string",
"checked_at": "2026-09-21T09:30:00Z",
"checked_by": {}
},
"credit": {
"party": "string",
"name": "string",
"currency": "string",
"credit_limit": "string",
"receivables": "string",
"pending_invoices": "string",
"open_orders": "string",
"exposure": "string",
"available": "string",
"over_limit": true,
"note": "string"
},
"parent": {
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"code": "string",
"name": "string"
},
"owner": {
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"email": "string",
"name": "string"
},
"merged_into": {
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"code": "string",
"name": "string"
},
"subsidiaries": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"code": "string",
"name": "string"
}
],
"possible_duplicates": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"code": "string",
"name": "string",
"status": "string",
"same": [
"iban"
],
"message": "string"
}
],
"open_support_cases": 0,
"breached_support_cases": 0,
"active_subscriptions": 0,
"open_opportunities": 0
}
POST /v1/entities/{entity}/parties/{party}/merge
Merge a duplicate customer
Merge this customer, entered twice, into into, a customer of the same company
(ADR-0089). Only a customer without business records of its own is merged: no document,
payment, order, subscription, price list, mandate, won deal or request waiting for approval
names it (409 party_merge_has_records lists what does). Its contacts, deals, activities and
subsidiaries move to the customer that stays, its own field values fill the ones that one has
none of, and it becomes inactive for good (merged_into on its card). Returns the card of the
customer that stays. Vendors are not merged. A person's decision: 403 merge_agent for an
agent. 422 merge_same for itself; 409 party_merged if either was merged already,
party_merge_loop if the one that stays belongs to its group below it.
| Required scope | draft (admin implies every scope) |
| Idempotency-Key | not used |
| Operation id | merge_party_v1_entities__entity__parties__party__merge_post |
Parameters
| In | Name | Type | Required | Description |
|---|---|---|---|---|
| path | entity |
string | yes | Entity code, e.g. CH01 (GET /v1/entities). |
| path | party |
string | yes | Customer or vendor code, e.g. C-DE or V-BM. |
Request body
application/json (required): CustomerMerge
| Field | Type | Required | Description |
|---|---|---|---|
into |
string | yes | Code or id of the customer that stays (same company). (min length 1) |
Example request
curl -X POST "$ERP_URL/v1/entities/CH01/parties/C-DE/merge" \
-H "Authorization: Bearer $ERP_KEY" \
-H "Content-Type: application/json" \
-d '{
"into": "C-CH"
}'
Responses
| Status | Meaning | Body |
|---|---|---|
| 200 | OK | PartyCard |
| 401 | Missing or invalid API key (unauthorized). |
ErrorEnvelope |
| 403 | The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). |
ErrorEnvelope |
| 404 | The resource does not exist, or belongs to another organization (not_found). |
ErrorEnvelope |
| 409 | The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). |
ErrorEnvelope |
| 422 | Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. |
HTTPValidationError |
Example response (shape)
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"kind": "string",
"code": "string",
"name": "string",
"country": "string",
"subdivision": "string",
"vat_number": "string",
"business": true,
"split_payment": false,
"withholding_code": "string",
"withholding_rate": "string",
"vat_unverified": false,
"currency": "string",
"payment_terms_days": 1,
"email": "string",
"iban": "string",
"street": "string",
"building_number": "string",
"postal_code": "string",
"town": "string",
"status": "active",
"group_entity_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"leitweg_id": "string",
"electronic_address": "string",
"electronic_address_scheme": "string",
"cash_discount_percent": "string",
"cash_discount_days": 1,
"credit_limit": "string",
"bank_accounts": [
{
"iban": "string",
"bic": "string",
"label": "string"
}
],
"contacts": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "string",
"role": "string",
"email": "string",
"phone": "string"
}
],
"parent_party_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"custom": {},
"owner_user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"language": "string",
"default_account_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"created_at": "2026-09-21T09:30:00Z",
"balances": [
{
"currency": "string",
"open": "string",
"overdue": "string",
"on_account": "0.00",
"open_documents": 1,
"overdue_documents": 1
}
],
"pending_actions": [
"string"
],
"created_by": {},
"activated_by": {},
"activated_at": "2026-09-21T09:30:00Z",
"pending": [
{
"approval_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"action": "string",
"requested_by": {},
"requested_at": "2026-09-21T09:30:00Z",
"reason": "string",
"current": {},
"proposed": {}
}
],
"payment_blockers": [
{
"code": "string",
"message": "string",
"details": {}
}
],
"vat_check": {
"registry": "ch_uid",
"status": "invalid",
"vat_number": "string",
"name": "string",
"name_matches": true,
"reference": "string",
"checked_at": "2026-09-21T09:30:00Z",
"checked_by": {}
},
"credit": {
"party": "string",
"name": "string",
"currency": "string",
"credit_limit": "string",
"receivables": "string",
"pending_invoices": "string",
"open_orders": "string",
"exposure": "string",
"available": "string",
"over_limit": true,
"note": "string"
},
"parent": {
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"code": "string",
"name": "string"
},
"owner": {
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"email": "string",
"name": "string"
},
"merged_into": {
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"code": "string",
"name": "string"
},
"subsidiaries": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"code": "string",
"name": "string"
}
],
"possible_duplicates": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"code": "string",
"name": "string",
"status": "string",
"same": [
"iban"
],
"message": "string"
}
],
"open_support_cases": 0,
"breached_support_cases": 0,
"active_subscriptions": 0,
"open_opportunities": 0
}
POST /v1/entities/{entity}/parties/{party}/status
Block a customer or vendor, set it inactive, or make it active again
Ask a second person to change the status (four eyes, as a change of key details): the
answer lists the request in pending (action change_party_status), decided with
POST /v1/approvals/{id}/approve or reject by someone other than the requester.
blocked: no new documents, orders or subscriptions for the party and nothing paid to it
(payment proposals leave its bills out, payments and payment files refuse it); what it pays
still settles its open items. Payments to it are blocked already while the block waits.
inactive: no longer used, nothing paid to it or received from it; only a party without open
items, documents or payments waiting for approval, open purchase orders or active
subscriptions and recurring invoices (409 party_has_open_items). active makes a blocked or
inactive party usable again; a draft has no status change (409 party_status_move), it is
activated instead. People only (403 for agents and when the policy denies
change_party_details); 409 for a move the rules do not allow or a request already waiting.
| Required scope | draft (admin implies every scope) |
| Idempotency-Key | not used |
| Operation id | change_party_status_v1_entities__entity__parties__party__status_post |
Parameters
| In | Name | Type | Required | Description |
|---|---|---|---|---|
| path | entity |
string | yes | Entity code, e.g. CH01 (GET /v1/entities). |
| path | party |
string | yes | Customer or vendor code, e.g. C-DE or V-BM. |
| query | kind |
"customer" | "vendor" or null |
customer or vendor; needed when one code names both a customer and a vendor (otherwise 409). |
Request body
application/json (required): PartyStatusInput
| Field | Type | Required | Description |
|---|---|---|---|
status |
"active" | "blocked" | "inactive" |
yes | blocked: no new documents or orders, nothing paid to it. inactive: no longer used (only without open items). active: in use again. |
reason |
string | yes | Why; the approver sees it and it is audited. (min length 1; max length 500) |
Example request
curl -X POST "$ERP_URL/v1/entities/CH01/parties/C-DE/status" \
-H "Authorization: Bearer $ERP_KEY" \
-H "Content-Type: application/json" \
-d '{
"reason": "Disputed deliveries, legal review",
"status": "blocked"
}'
Responses
| Status | Meaning | Body |
|---|---|---|
| 200 | OK | PartyCard |
| 401 | Missing or invalid API key (unauthorized). |
ErrorEnvelope |
| 403 | The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). |
ErrorEnvelope |
| 404 | The resource does not exist, or belongs to another organization (not_found). |
ErrorEnvelope |
| 409 | The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). |
ErrorEnvelope |
| 422 | Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. |
HTTPValidationError |
Example response (shape)
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"kind": "string",
"code": "string",
"name": "string",
"country": "string",
"subdivision": "string",
"vat_number": "string",
"business": true,
"split_payment": false,
"withholding_code": "string",
"withholding_rate": "string",
"vat_unverified": false,
"currency": "string",
"payment_terms_days": 1,
"email": "string",
"iban": "string",
"street": "string",
"building_number": "string",
"postal_code": "string",
"town": "string",
"status": "active",
"group_entity_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"leitweg_id": "string",
"electronic_address": "string",
"electronic_address_scheme": "string",
"cash_discount_percent": "string",
"cash_discount_days": 1,
"credit_limit": "string",
"bank_accounts": [
{
"iban": "string",
"bic": "string",
"label": "string"
}
],
"contacts": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "string",
"role": "string",
"email": "string",
"phone": "string"
}
],
"parent_party_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"custom": {},
"owner_user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"language": "string",
"default_account_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"created_at": "2026-09-21T09:30:00Z",
"balances": [
{
"currency": "string",
"open": "string",
"overdue": "string",
"on_account": "0.00",
"open_documents": 1,
"overdue_documents": 1
}
],
"pending_actions": [
"string"
],
"created_by": {},
"activated_by": {},
"activated_at": "2026-09-21T09:30:00Z",
"pending": [
{
"approval_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"action": "string",
"requested_by": {},
"requested_at": "2026-09-21T09:30:00Z",
"reason": "string",
"current": {},
"proposed": {}
}
],
"payment_blockers": [
{
"code": "string",
"message": "string",
"details": {}
}
],
"vat_check": {
"registry": "ch_uid",
"status": "invalid",
"vat_number": "string",
"name": "string",
"name_matches": true,
"reference": "string",
"checked_at": "2026-09-21T09:30:00Z",
"checked_by": {}
},
"credit": {
"party": "string",
"name": "string",
"currency": "string",
"credit_limit": "string",
"receivables": "string",
"pending_invoices": "string",
"open_orders": "string",
"exposure": "string",
"available": "string",
"over_limit": true,
"note": "string"
},
"parent": {
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"code": "string",
"name": "string"
},
"owner": {
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"email": "string",
"name": "string"
},
"merged_into": {
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"code": "string",
"name": "string"
},
"subsidiaries": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"code": "string",
"name": "string"
}
],
"possible_duplicates": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"code": "string",
"name": "string",
"status": "string",
"same": [
"iban"
],
"message": "string"
}
],
"open_support_cases": 0,
"breached_support_cases": 0,
"active_subscriptions": 0,
"open_opportunities": 0
}
POST /v1/entities/{entity}/parties/{party}/vat-check
Check a customer's or vendor's VAT number in its public register
Ask the public register of the party's VAT number (VIES, the Swiss UID register or
HMRC) whether it is registered for VAT, as POST /v1/vat-registers/check does, and keep a
definite answer (valid or invalid) on the card (vat_check) and in the audit trail.
For a UK number, when the entity has a UK VAT number of its own, HMRC also gives a
consultation number (reference): the proof that the number was checked that day. Advice
only: nothing is refused on the answer. unavailable (the register did not answer) and
not_configured (this server has no access to the register yet, e.g. HMRC credentials not
set up) keep the last answer. 422 no_vat_number when the party has none; 429 past 30
register checks a minute per organization.
| Required scope | draft (admin implies every scope) |
| Idempotency-Key | not used |
| Operation id | check_party_vat_number_v1_entities__entity__parties__party__vat_check_post |
Parameters
| In | Name | Type | Required | Description |
|---|---|---|---|---|
| path | entity |
string | yes | Entity code, e.g. CH01 (GET /v1/entities). |
| path | party |
string | yes | Customer or vendor code, e.g. C-DE or V-BM. |
| query | kind |
"customer" | "vendor" or null |
customer or vendor; needed when one code names both a customer and a vendor (otherwise 409). |
Example request
curl -X POST "$ERP_URL/v1/entities/CH01/parties/C-DE/vat-check" \
-H "Authorization: Bearer $ERP_KEY"
Responses
| Status | Meaning | Body |
|---|---|---|
| 200 | OK | RegisterCheck |
| 401 | Missing or invalid API key (unauthorized). |
ErrorEnvelope |
| 403 | The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). |
ErrorEnvelope |
| 404 | The resource does not exist, or belongs to another organization (not_found). |
ErrorEnvelope |
| 409 | The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). |
ErrorEnvelope |
| 422 | Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. |
HTTPValidationError |
Example response (shape)
{
"country": "string",
"vat_number": "string",
"registry": "ch_uid",
"status": "invalid",
"name": "string",
"address": "string",
"street": "string",
"building_number": "string",
"postal_code": "string",
"town": "string",
"name_matches": true,
"message": "string",
"reference": "string",
"checked_at": "2026-09-21T09:30:00Z",
"cached": false
}
POST /v1/vat-registers/check
Check a VAT number against its public register
Ask the public register whether a VAT number is valid, and for the registered name.
EU numbers (and XI) are checked in VIES, Swiss UIDs in the UID register, UK numbers with
HMRC (when the server is configured for it). The answer is advisory: invalid says the
register does not know the number as registered for VAT, unavailable that it did not
answer in time and the check can be repeated. Definite answers are kept for a day
(cached). Nothing is stored or changed. The number and name go in the body, never the
URL. An organization may make 30 checks a minute that reach a register (cached answers do
not count); beyond that the answer is 429 with retry_after_seconds.
| Required scope | draft (admin implies every scope) |
| Idempotency-Key | not used |
| Operation id | check_vat_number_v1_vat_registers_check_post |
Request body
application/json (required): RegisterCheckInput
| Field | Type | Required | Description |
|---|---|---|---|
country |
string or null | ISO 3166-1 alpha-2 country of the party, e.g. DE. A number shaped like another country's (e.g. an IE registration of a US company, ATU… at a German address) is checked in that country's register. Omitted: the country the number's prefix names (no_register for a number without one); the answer says which. (pattern ^[A-Za-z]{2}$) |
|
vat_number |
string | yes | The VAT number as written, e.g. DE811569869 or CHE-123.456.788 MWST. (min length 4; max length 40) |
name |
string or null | The party's name as you have it: name_matches says whether the register's name is the same company's. (max length 200) |
Example request
curl -X POST "$ERP_URL/v1/vat-registers/check" \
-H "Authorization: Bearer $ERP_KEY" \
-H "Content-Type: application/json" \
-d '{
"country": "DE",
"name": "Muster Lieferant GmbH",
"vat_number": "DE811569869"
}'
Responses
| Status | Meaning | Body |
|---|---|---|
| 200 | OK | RegisterCheck |
| 401 | Missing or invalid API key (unauthorized). |
ErrorEnvelope |
| 403 | The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). |
ErrorEnvelope |
| 409 | The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). |
ErrorEnvelope |
| 422 | Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. |
HTTPValidationError |
Example response (shape)
{
"country": "string",
"vat_number": "string",
"registry": "ch_uid",
"status": "invalid",
"name": "string",
"address": "string",
"street": "string",
"building_number": "string",
"postal_code": "string",
"town": "string",
"name_matches": true,
"message": "string",
"reference": "string",
"checked_at": "2026-09-21T09:30:00Z",
"cached": false
}
Schemas
Balance
Open posted documents of a party in one currency (credit notes count negative).
| Field | Type | Required | Description |
|---|---|---|---|
currency |
string | yes | ISO 4217 currency of the amounts. |
open |
string | yes | Open amount of posted documents (credit notes negative), less what is on account (on_account): what the party owes, or is owed, in this currency. |
overdue |
string | yes | The part of it due before the as_of day. |
on_account |
string | What is left on account of the party's posted payments, not yet applied to an invoice or bill (ADR-0045): received from a customer, or paid to a vendor, ahead. Positive; open is already less it. (default "0.00") |
|
open_documents |
integer | yes | Number of documents with an open amount. |
overdue_documents |
integer | yes | Number of those that are overdue. |
CreditExposure
The customers of a company with a credit limit, and their exposure today.
| Field | Type | Required | Description |
|---|---|---|---|
entity |
string | yes | The company's code. |
as_of |
string (date) | yes | Today where the company is: amounts in another currency are converted at this day's ECB reference rate. |
customers |
array of CreditPosition |
yes | Every customer with a credit limit, those over it first, then by code. |
CreditPosition
One customer's credit exposure against its credit limit, in the customer's currency.
| Field | Type | Required | Description |
|---|---|---|---|
party |
string | yes | The customer's code, e.g. C-SE. |
name |
string | yes | The customer's name. |
currency |
string | yes | The customer's currency: every amount here is in it. |
credit_limit |
string or null | yes | The most the customer may owe; null for no limit. |
receivables |
string or null | yes | What the customer owes on posted documents: open invoices less open credit notes and payments received on account. |
pending_invoices |
string or null | yes | The totals of its invoices waiting for a second person's approval. |
open_orders |
string or null | yes | What is left to invoice on its open sales orders, VAT included. |
exposure |
string or null | yes | receivables + pending_invoices + open_orders; null when an amount in another currency has no exchange rate today (note). |
available |
string or null | yes | credit_limit - exposure: what may still be invoiced or ordered; negative when over the limit; null without a limit. |
over_limit |
boolean | yes | true when the exposure is above the credit limit. |
note |
string or null | Why the exposure could not be worked out (an exchange rate missing today). |
CustomerMerge
| Field | Type | Required | Description |
|---|---|---|---|
into |
string | yes | Code or id of the customer that stays (same company). (min length 1) |
NewContact
A person at a new customer or vendor.
| Field | Type | Required | Description |
|---|---|---|---|
first_name |
string or null | First name. (min length 1; max length 100) | |
role |
string or null | Role or department, e.g. Head of purchasing. A role that says billing, accounting or Buchhaltung makes the contact one an invoice goes to by default. (max length 100) |
|
email |
string or null | E-mail address. (max length 200) | |
phone |
string or null | Phone number. (max length 50) | |
mobile |
string or null | Mobile number. (max length 50) | |
last_name |
string | yes | Last name. A name sent instead is split: its last word is the last name, the words before it the first name. (min length 1; max length 100) |
PartyBankAccount
A further account of a customer or vendor next to its IBAN, e.g. a QR-IBAN.
| Field | Type | Required | Description |
|---|---|---|---|
iban |
string | yes | IBAN of the account, 5 to 42 characters; stored without spaces. (min length 5; max length 42) |
bic |
string or null | BIC/SWIFT code of the bank (8 or 11 characters). (pattern ^[A-Z]{6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3})?$) |
|
label |
string or null | Short label for the account, e.g. QR-IBAN. (max length 70) |
PartyCard
One customer or vendor with everything its card shows.
| Field | Type | Required | Description |
|---|---|---|---|
id |
string (uuid) | yes | Id of the customer or vendor. |
kind |
string | yes | customer or vendor. |
code |
string | yes | The party's short code, e.g. C-DE; unique per kind in an entity. |
name |
string | yes | Legal name. |
country |
string | yes | ISO 3166-1 alpha-2 country code. |
subdivision |
string or null | yes | ISO 3166-2 subdivision used for tax, if any. |
vat_number |
string or null | yes | VAT or UID number. |
business |
boolean | yes | true for a business (B2B), false for a private person (B2C). |
split_payment |
boolean | Italy: true for a customer under split payment (scissione dei pagamenti, DPR 633/1972 art. 17-ter, e.g. a public body): an Italian company's invoices to it show the VAT, which the customer pays to the State, and the customer owes the net amount. (default false) |
|
withholding_code |
string or null | Vendors: the withholding tax code its bills keep back (IT-RA-20, custom); null for none. |
|
withholding_rate |
string or null | Vendors: the withholding rate in percent of a bill's net amount before VAT. | |
vat_unverified |
boolean | true for a vendor created from a received document whose vat_number (recorded as printed) is not a valid Swiss UID or German USt-IdNr; a later change of vat_number that passes the check clears it. (default false) |
|
currency |
string | yes | ISO 4217 currency of the party's documents and payments. |
payment_terms_days |
integer | yes | Days from the document date to the due date. |
email |
string or null | yes | Contact email address. |
iban |
string or null | yes | IBAN payments to the party go to, without spaces. |
street |
string or null | Street of the postal address. | |
building_number |
string or null | Building number of the postal address. | |
postal_code |
string or null | Postal code of the address. | |
town |
string or null | Town of the address. | |
status |
string | active; draft until a second person activates it (a draft is neither booked nor paid); blocked (no new documents or orders, nothing paid to it; what it pays still settles its open items) or inactive (no longer used, no open items). (default "active") |
|
group_entity_id |
string (uuid) or null | Id of the entity this customer or vendor is, when it is another entity of the organization (created by an approved intercompany relationship); null for an ordinary customer or vendor. Its documents post to the group accounts (ic_ar_control, ic_ap_control) and are mirrored in that entity. |
|
leitweg_id |
string or null | Leitweg-ID of a German public buyer (XRechnung buyer reference). | |
electronic_address |
string or null | E-invoicing address (EN 16931 BT-34 / BT-49). | |
electronic_address_scheme |
string or null | EAS code of the electronic address, e.g. EM. |
|
cash_discount_percent |
string or null | Cash discount (Skonto) percent if paid within the days. | |
cash_discount_days |
integer or null | Days within which the cash discount applies. | |
credit_limit |
string or null | Customers: the most the customer may owe, in its currency (currency), e.g. 100000; null for no limit. Its open invoices, its invoices waiting for approval and what is left to invoice on its open sales orders count; above it an invoice waits for a second person and a sales order is not confirmed. |
|
bank_accounts |
array of PartyBankAccount |
Further accounts payments may go to. | |
contacts |
array of PartyContact |
People at the party (GET /v1/contacts?party_id=). |
|
parent_party_id |
string (uuid) or null | Id of the company it belongs to (a party of the same kind). | |
custom |
object | Values of the organization's own fields (GET /v1/custom-fields) by key, e.g. {"industry": "Retail"}: text, a number, a date (2026-10-23), true or false, or one of a choice field's choices. On a change only the keys sent change; null removes a value. |
|
owner_user_id |
string (uuid) or null | Customers: the sales person who looks after it (GET /v1/people); a vendor has none. Who sees only their own or their team's records gives it to one of those people. |
|
language |
string or null | Correspondence language (de, fr, it, en, sv, rm). |
|
default_account_id |
string (uuid) or null | Id of the revenue or expense account used on lines without an account. | |
created_at |
string (date-time) or null | When the party was created (UTC). | |
balances |
array of Balance |
Open posted documents per currency: open and overdue amount and number of documents; credit notes count negative. | |
pending_actions |
array of string | Requests waiting for a second person: activate_party, change_bank_details. | |
created_by |
object or null | From the audit trail. | |
activated_by |
object or null | Who activated it last, if it started as a draft. | |
activated_at |
string (date-time) or null | When the party was last activated (UTC). | |
pending |
array of PendingRequest |
The requests waiting for a second person, with who asked and why. | |
payment_blockers |
array of BlockerOut |
Why no payment to the party can be released now. | |
vat_check |
PartyVatCheck or null |
The public register's last answer for the current VAT number, with its consultation reference as proof; null until it is checked from the card. | |
credit |
CreditPosition or null |
Customers with a credit limit: what the customer owes and has on order against its limit today, and the credit still available; null without a limit. | |
parent |
PartyRef or null |
The company it belongs to. | |
owner |
Person or null |
The owner (owner_user_id), by name. |
|
merged_into |
PartyRef or null |
The customer this duplicate was merged into (it is inactive). | |
subsidiaries |
array of PartyRef |
The parties that name it as their parent company. | |
possible_duplicates |
array of PossibleDuplicate |
Other customers or vendors of the same company with the same VAT number, an IBAN in common or the same name. | |
open_support_cases |
integer | Support cases of this customer that are open or waiting on the customer. (default 0) |
|
breached_support_cases |
integer | Support cases of this customer where a service level is breached. (default 0) |
|
active_subscriptions |
integer | Active recurring subscriptions of this customer. (default 0) |
|
open_opportunities |
integer | Open sales pipeline deals (opportunities) for this customer. (default 0) |
PartyContact
A person at a customer or vendor, as its card lists them.
| Field | Type | Required | Description |
|---|---|---|---|
id |
string (uuid) | yes | Id of the contact (GET /v1/contacts/{contact_id}). |
name |
string | yes | First and last name. |
role |
string or null | Role or department, e.g. Buchhaltung. |
|
email |
string or null | E-mail address. | |
phone |
string or null | Phone number. |
PartyCreated
A new customer or vendor, with the existing ones it may duplicate.
| Field | Type | Required | Description |
|---|---|---|---|
id |
string (uuid) | yes | Id of the customer or vendor. |
kind |
string | yes | customer or vendor. |
code |
string | yes | The party's short code, e.g. C-DE; unique per kind in an entity. |
name |
string | yes | Legal name. |
country |
string | yes | ISO 3166-1 alpha-2 country code. |
subdivision |
string or null | yes | ISO 3166-2 subdivision used for tax, if any. |
vat_number |
string or null | yes | VAT or UID number. |
business |
boolean | yes | true for a business (B2B), false for a private person (B2C). |
split_payment |
boolean | Italy: true for a customer under split payment (scissione dei pagamenti, DPR 633/1972 art. 17-ter, e.g. a public body): an Italian company's invoices to it show the VAT, which the customer pays to the State, and the customer owes the net amount. (default false) |
|
withholding_code |
string or null | Vendors: the withholding tax code its bills keep back (IT-RA-20, custom); null for none. |
|
withholding_rate |
string or null | Vendors: the withholding rate in percent of a bill's net amount before VAT. | |
vat_unverified |
boolean | true for a vendor created from a received document whose vat_number (recorded as printed) is not a valid Swiss UID or German USt-IdNr; a later change of vat_number that passes the check clears it. (default false) |
|
currency |
string | yes | ISO 4217 currency of the party's documents and payments. |
payment_terms_days |
integer | yes | Days from the document date to the due date. |
email |
string or null | yes | Contact email address. |
iban |
string or null | yes | IBAN payments to the party go to, without spaces. |
street |
string or null | Street of the postal address. | |
building_number |
string or null | Building number of the postal address. | |
postal_code |
string or null | Postal code of the address. | |
town |
string or null | Town of the address. | |
status |
string | active; draft until a second person activates it (a draft is neither booked nor paid); blocked (no new documents or orders, nothing paid to it; what it pays still settles its open items) or inactive (no longer used, no open items). (default "active") |
|
group_entity_id |
string (uuid) or null | Id of the entity this customer or vendor is, when it is another entity of the organization (created by an approved intercompany relationship); null for an ordinary customer or vendor. Its documents post to the group accounts (ic_ar_control, ic_ap_control) and are mirrored in that entity. |
|
leitweg_id |
string or null | Leitweg-ID of a German public buyer (XRechnung buyer reference). | |
electronic_address |
string or null | E-invoicing address (EN 16931 BT-34 / BT-49). | |
electronic_address_scheme |
string or null | EAS code of the electronic address, e.g. EM. |
|
cash_discount_percent |
string or null | Cash discount (Skonto) percent if paid within the days. | |
cash_discount_days |
integer or null | Days within which the cash discount applies. | |
credit_limit |
string or null | Customers: the most the customer may owe, in its currency (currency), e.g. 100000; null for no limit. Its open invoices, its invoices waiting for approval and what is left to invoice on its open sales orders count; above it an invoice waits for a second person and a sales order is not confirmed. |
|
bank_accounts |
array of PartyBankAccount |
Further accounts payments may go to. | |
contacts |
array of PartyContact |
People at the party (GET /v1/contacts?party_id=). |
|
parent_party_id |
string (uuid) or null | Id of the company it belongs to (a party of the same kind). | |
custom |
object | Values of the organization's own fields (GET /v1/custom-fields) by key, e.g. {"industry": "Retail"}: text, a number, a date (2026-10-23), true or false, or one of a choice field's choices. On a change only the keys sent change; null removes a value. |
|
owner_user_id |
string (uuid) or null | Customers: the sales person who looks after it (GET /v1/people); a vendor has none. Who sees only their own or their team's records gives it to one of those people. |
|
language |
string or null | Correspondence language (de, fr, it, en, sv, rm). |
|
default_account_id |
string (uuid) or null | Id of the revenue or expense account used on lines without an account. | |
created_at |
string (date-time) or null | When the party was created (UTC). | |
possible_duplicates |
array of PossibleDuplicate |
Customers or vendors of the same company with the same VAT number, an IBAN in common or the same name. The party is created anyway (a vendor as a draft); check them before it is activated. |
PartyInput
| Field | Type | Required | Description |
|---|---|---|---|
kind |
"customer" | "vendor" |
yes | customer or vendor; a code is unique per kind in an entity. |
code |
string or null | Leave it out and the party gets the company's next number: C-00001 for a customer, V-00001 for a vendor, counted per company without gaps. Give one (up to 40 characters, e.g. the number of the system before) only to keep it; it is how documents and URLs name the party, and never changes. (min length 1; max length 40) |
|
name |
string | yes | Legal name of the customer or vendor. |
country |
string or null | ISO 3166-1 alpha-2 country code, e.g. DE; drives the place of supply of the tax determination. Omitted: the country its VAT number names by its prefix, else the company's. (pattern ^[A-Z]{2}$) |
|
subdivision |
string or null | ISO 3166-2 subdivision where it matters for tax, e.g. DE-BY, or a US customer's state (US-CA), which decides its sales tax. A Spanish postal code gives it when left empty: 35 and 38 the Canary Islands (ES-CN), 51 Ceuta (ES-CE), 52 Melilla (ES-ML); one of another country, or that the postal code contradicts, is refused (422 party_subdivision_mismatch). (pattern ^[A-Z]{2}-[A-Z0-9]{1,3}$) |
|
vat_number |
string or null | VAT or UID number, e.g. DE811569869 or CHE-116.281.710 MWST; for a party of an EU country, the UK, Norway, Switzerland or Liechtenstein its format is checked, and its check digit for CH, DE, FR, IT, ES and BE (422 vat_number_invalid). |
|
business |
boolean | true for a business (B2B), false for a private person (B2C); affects how VAT is determined on sales: a sale to another VAT area goes under the reverse charge only to a business, and a customer with a VAT number counts as one. Between two EU countries only the VAT number makes the customer a business: without it the sale is taxed as one to a private person. (default true) |
|
split_payment |
boolean | Customers of an Italian company: true for one under split payment (scissione dei pagamenti, DPR 633/1972 art. 17-ter: public bodies and the companies the law lists). Its invoices show the VAT but it owes only the net amount and pays the VAT to the State; the VAT returns leave that VAT out. Default false. (default false) |
|
currency |
string or null | ISO 4217 currency of the party's documents and payments, e.g. EUR: functional or with exchange rates (422 party_currency_without_rates). Omitted: its country's currency when the company has exchange rates for it, else the company's. (pattern ^[A-Z]{3}$) |
|
withholding_code |
string or null | Vendors: the withholding tax code kept back from its bills and paid to the tax authority by the company (GET /v1/entities/{entity}/withholding-tax/codes lists the codes of the company's country, e.g. IT-RA-20), or custom with withholding_rate; null for none. Changing it once a bill of the vendor is posted waits for a second person. (max length 20) |
|
withholding_rate |
decimal string or null | With withholding_code custom: the rate in percent of a bill's net amount before VAT, e.g. 18.5; a code of the table takes its own rate. (greater than 0) |
|
payment_terms_days |
integer | Days from the document date to the due date, 0 to 365; default 30. (min 0; max 365; default 30) |
|
default_account |
string or null | Revenue/expense account code. | |
email |
string or null | Contact email address. | |
iban |
string or null | IBAN payments to the party go to, stored without spaces; one of your own companies' accounts is refused (422 party_own_bank_account). |
|
bank_accounts |
array of PartyBankAccount |
Further accounts payments may go to (a QR-IBAN). | |
language |
"de" | "en" | "fr" | "it" | "rm" | "sv" or null |
Correspondence language. Omitted: its country's, where the country has one of ours (DE and AT de, FR fr, IT it, SE sv, GB and US en); none for a country of several (CH, BE, CA): set it there. |
|
contacts |
array of NewContact |
People at the party; later ones are added with POST /v1/contacts. |
|
parent |
string or null | Code (or id) of the company it belongs to, of the same kind. | |
custom |
map of string | number | integer | boolean or null | Values of the organization's own fields (GET /v1/custom-fields) by key, e.g. {"industry": "Retail"}: text, a number, a date (2026-10-23), true or false, or one of a choice field's choices. On a change only the keys sent change; null removes a value. |
|
owner_user_id |
string (uuid) or null | Customers: the sales person who looks after it (GET /v1/people); a vendor has none. Who sees only their own or their team's records gives it to one of those people. Omitted: you. |
|
street |
string or null | Street of the postal address (up to 70 characters); used on QR-bills and XRechnung. (max length 70) | |
building_number |
string or null | Building number of the postal address (up to 16 characters). (max length 16) | |
postal_code |
string or null | Postal code of the address (up to 16 characters). (max length 16) | |
town |
string or null | Town of the address (up to 35 characters). (max length 35) | |
leitweg_id |
string or null | Customers: Leitweg-ID of a German public buyer (XRechnung buyer reference). | |
electronic_address |
string or null | E-invoicing address (BT-34/BT-49), e.g. an email or Peppol id. | |
electronic_address_scheme |
string or null | EAS code of the electronic address, e.g. EM (email), 0204, 9930. | |
status |
"active" | "draft" |
draft until a second person activates it. A vendor (or a party with bank details) created by an agent, and a vendor created from an e-invoice, start as draft; otherwise 'active' needs the approval policy to allow activate_party. (default "active") |
|
cash_discount_percent |
decimal string or null | Cash discount (Skonto) percent if paid within cash_discount_days, e.g. 2. (greater than 0) | |
cash_discount_days |
integer or null | Days within which the cash discount applies, 0 to 365. (min 0; max 365) | |
credit_limit |
decimal string or null | Customers: the most the customer may owe, in its currency (currency), e.g. 100000; null for no limit. Its open invoices, its invoices waiting for approval and what is left to invoice on its open sales orders count; above it an invoice waits for a second person and a sales order is not confirmed. (min 0) |
|
source_sha256 |
string or null | SHA-256 of the bill this vendor was read from (the bill wizard sends the sha256 of POST /v1/agents/bill-capture/read). The audit entry and the activation request then say that its bank details come from that invoice, and what the public VAT register said about its number: the approver sees what nobody has confirmed. (pattern ^[0-9a-f]{64}$) |
PartyRef
Another customer or vendor named by this one (its parent company or a subsidiary).
| Field | Type | Required | Description |
|---|---|---|---|
id |
string (uuid) | yes | Id of the party. |
code |
string | yes | Its code. |
name |
string | yes | Its name. |
PartyRow
A customer or vendor in a list, with its open balance and pending requests.
| Field | Type | Required | Description |
|---|---|---|---|
id |
string (uuid) | yes | Id of the customer or vendor. |
kind |
string | yes | customer or vendor. |
code |
string | yes | The party's short code, e.g. C-DE; unique per kind in an entity. |
name |
string | yes | Legal name. |
country |
string | yes | ISO 3166-1 alpha-2 country code. |
subdivision |
string or null | yes | ISO 3166-2 subdivision used for tax, if any. |
vat_number |
string or null | yes | VAT or UID number. |
business |
boolean | yes | true for a business (B2B), false for a private person (B2C). |
split_payment |
boolean | Italy: true for a customer under split payment (scissione dei pagamenti, DPR 633/1972 art. 17-ter, e.g. a public body): an Italian company's invoices to it show the VAT, which the customer pays to the State, and the customer owes the net amount. (default false) |
|
withholding_code |
string or null | Vendors: the withholding tax code its bills keep back (IT-RA-20, custom); null for none. |
|
withholding_rate |
string or null | Vendors: the withholding rate in percent of a bill's net amount before VAT. | |
vat_unverified |
boolean | true for a vendor created from a received document whose vat_number (recorded as printed) is not a valid Swiss UID or German USt-IdNr; a later change of vat_number that passes the check clears it. (default false) |
|
currency |
string | yes | ISO 4217 currency of the party's documents and payments. |
payment_terms_days |
integer | yes | Days from the document date to the due date. |
email |
string or null | yes | Contact email address. |
iban |
string or null | yes | IBAN payments to the party go to, without spaces. |
street |
string or null | Street of the postal address. | |
building_number |
string or null | Building number of the postal address. | |
postal_code |
string or null | Postal code of the address. | |
town |
string or null | Town of the address. | |
status |
string | active; draft until a second person activates it (a draft is neither booked nor paid); blocked (no new documents or orders, nothing paid to it; what it pays still settles its open items) or inactive (no longer used, no open items). (default "active") |
|
group_entity_id |
string (uuid) or null | Id of the entity this customer or vendor is, when it is another entity of the organization (created by an approved intercompany relationship); null for an ordinary customer or vendor. Its documents post to the group accounts (ic_ar_control, ic_ap_control) and are mirrored in that entity. |
|
leitweg_id |
string or null | Leitweg-ID of a German public buyer (XRechnung buyer reference). | |
electronic_address |
string or null | E-invoicing address (EN 16931 BT-34 / BT-49). | |
electronic_address_scheme |
string or null | EAS code of the electronic address, e.g. EM. |
|
cash_discount_percent |
string or null | Cash discount (Skonto) percent if paid within the days. | |
cash_discount_days |
integer or null | Days within which the cash discount applies. | |
credit_limit |
string or null | Customers: the most the customer may owe, in its currency (currency), e.g. 100000; null for no limit. Its open invoices, its invoices waiting for approval and what is left to invoice on its open sales orders count; above it an invoice waits for a second person and a sales order is not confirmed. |
|
bank_accounts |
array of PartyBankAccount |
Further accounts payments may go to. | |
contacts |
array of PartyContact |
People at the party (GET /v1/contacts?party_id=). |
|
parent_party_id |
string (uuid) or null | Id of the company it belongs to (a party of the same kind). | |
custom |
object | Values of the organization's own fields (GET /v1/custom-fields) by key, e.g. {"industry": "Retail"}: text, a number, a date (2026-10-23), true or false, or one of a choice field's choices. On a change only the keys sent change; null removes a value. |
|
owner_user_id |
string (uuid) or null | Customers: the sales person who looks after it (GET /v1/people); a vendor has none. Who sees only their own or their team's records gives it to one of those people. |
|
language |
string or null | Correspondence language (de, fr, it, en, sv, rm). |
|
default_account_id |
string (uuid) or null | Id of the revenue or expense account used on lines without an account. | |
created_at |
string (date-time) or null | When the party was created (UTC). | |
balances |
array of Balance |
Open posted documents per currency: open and overdue amount and number of documents; credit notes count negative. | |
pending_actions |
array of string | Requests waiting for a second person: activate_party, change_bank_details. |
PartyStatusInput
A request to block a customer or vendor, set it inactive, or make it active again.
| Field | Type | Required | Description |
|---|---|---|---|
status |
"active" | "blocked" | "inactive" |
yes | blocked: no new documents or orders, nothing paid to it. inactive: no longer used (only without open items). active: in use again. |
reason |
string | yes | Why; the approver sees it and it is audited. (min length 1; max length 500) |
PartyUpdate
Fields that can be changed (null leaves a field as is, "" clears it).
Bank details (iban, bank_accounts) are not changed at once: the change waits for a
second person's approval and payments are blocked meanwhile, as are key details of a party past
draft or with posted documents. status: active does what the activate operation does.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string or null | New legal name; once the party is past draft, or a document of it is posted or pending approval, this waits for a second person. | |
country |
string or null | New ISO 3166-1 alpha-2 country; waits for a second person like name. (pattern ^[A-Z]{2}$) |
|
subdivision |
string or null | ISO 3166-2 subdivision where it matters for tax, e.g. DE-BY, or a US customer's state (US-CA); empty clears it. A Spanish postal code gives it as on create (422 party_subdivision_mismatch on a contradiction); a change waits for a second person like name. (pattern ^([A-Z]{2}-[A-Z0-9]{1,3})?$) |
|
vat_number |
string or null | New VAT or UID number (format checked as on create, 422); waits for a second person like name. |
|
business |
boolean or null | true for a business (B2B), false for a private person (B2C); affects how VAT is determined on sales: a sale to another VAT area goes under the reverse charge only to a business, and a customer with a VAT number counts as one. Between two EU countries only the VAT number makes the customer a business: without it the sale is taxed as one to a private person. |
|
split_payment |
boolean or null | Customers of an Italian company: true for one under split payment (DPR 633/1972 art. 17-ter); applies to invoices drafted from then on. |
|
currency |
string or null | New ISO 4217 currency: the functional currency or one with exchange rates (422 party_currency_without_rates); waits for a second person like name. (pattern ^[A-Z]{3}$) |
|
email |
string or null | Contact email address. | |
iban |
string or null | New IBAN, stored without spaces. It is not applied at once: a second person must approve it and payments to the party are blocked meanwhile. "" clears it. |
|
bank_accounts |
array of PartyBankAccount or null |
New list of further bank accounts; replaces the list. Waits for a second person's approval like iban. |
|
language |
"de" | "en" | "fr" | "it" | "rm" | "sv" | "" or null |
Correspondence language (de, fr, it, en, sv, rm); "" clears. |
|
parent |
string or null | Code (or id) of the company it belongs to; "" clears it. |
|
custom |
map of string | number | integer | boolean or null or null | Values of the organization's own fields (GET /v1/custom-fields) by key, e.g. {"industry": "Retail"}: text, a number, a date (2026-10-23), true or false, or one of a choice field's choices. On a change only the keys sent change; null removes a value. |
|
owner_user_id |
string (uuid) or null | New owner. Customers: the sales person who looks after it (GET /v1/people); a vendor has none. Who sees only their own or their team's records gives it to one of those people. |
|
withholding_code |
string or null | Vendors: the withholding tax code kept back from its bills and paid to the tax authority by the company (GET /v1/entities/{entity}/withholding-tax/codes lists the codes of the company's country, e.g. IT-RA-20), or custom with withholding_rate; "" removes it. Waits for a second person like name. (max length 20) |
|
withholding_rate |
decimal string or null | With withholding_code custom: the rate in percent of a bill's net amount before VAT. (greater than 0) |
|
payment_terms_days |
integer or null | Days from the document date to the due date, 0 to 365; waits for a second person like name. (min 0; max 365) |
|
default_account |
string or null | Code of the revenue (customer) or expense (vendor) account used on document lines that name no account, e.g. 6570. |
|
street |
string or null | Street of the postal address (up to 70 characters); used on QR-bills and XRechnung. (max length 70) | |
building_number |
string or null | Building number of the postal address (up to 16 characters). (max length 16) | |
postal_code |
string or null | Postal code of the address (up to 16 characters). (max length 16) | |
town |
string or null | Town of the address (up to 35 characters). (max length 35) | |
leitweg_id |
string or null | Customers: the Leitweg-ID of a German public buyer (validated, including its check digits); becomes the XRechnung buyer reference. | |
electronic_address |
string or null | E-invoicing address (EN 16931 BT-34 / BT-49), e.g. an email address or a Peppol id. | |
electronic_address_scheme |
string or null | Scheme of the electronic address (EAS code), e.g. EM (email), 0204 or 9930; needs an electronic_address. |
|
status |
"active" | "draft" or null |
'active' activates a draft party (as POST …/activate); 'draft' blocks its documents and payments again. | |
cash_discount_percent |
decimal string or null | 0 removes the terms; waits like name. (min 0) |
|
cash_discount_days |
integer or null | Days within which the cash discount applies, 0 to 365; waits for a second person like name. (min 0; max 365) |
|
credit_limit |
decimal string or null | Customers: the most the customer may owe, in its currency (currency), e.g. 100000; null for no limit. Its open invoices, its invoices waiting for approval and what is left to invoice on its open sales orders count; above it an invoice waits for a second person and a sales order is not confirmed. "" removes the limit. Waits for a second person like name. (min 0) |
PartyVatCheck
The register's last definite answer for a customer's or vendor's VAT number.
| Field | Type | Required | Description |
|---|---|---|---|
registry |
"ch_uid" | "uk_hmrc" | "vies" |
yes | The register that answered. |
status |
"invalid" | "valid" |
yes | valid: registered for VAT; invalid: the register does not know it. |
vat_number |
string | yes | The number as it was asked, compacted. |
name |
string or null | The registered name, if given. | |
name_matches |
boolean or null | Whether the registered name matches the party's name. | |
reference |
string or null | The register's consultation reference, kept as proof (HMRC's consultation number when your entity has a UK VAT number). | |
checked_at |
string (date-time) | yes | When the register answered (UTC). |
checked_by |
object or null | Who asked. |
PendingRequest
| Field | Type | Required | Description |
|---|---|---|---|
approval_id |
string (uuid) | yes | Id of the approval request; decide it with POST /v1/approvals/{id}/approve or reject. |
action |
string | yes | activate_party, change_bank_details, change_party_details or change_party_status. |
requested_by |
object | yes | The actor (type, id) that asked. |
requested_at |
string (date-time) | yes | When it was requested (UTC). |
reason |
string | yes | Why a second person is needed. |
current |
object or null | The values now (changes). | |
proposed |
object or null | The values once approved (changes). |
PossibleDuplicate
Another customer or vendor of the same company this one may duplicate.
| Field | Type | Required | Description |
|---|---|---|---|
id |
string (uuid) | yes | Id of the other customer or vendor. |
code |
string | yes | Its code, e.g. V-ALP. |
name |
string | yes | Its legal name. |
status |
string | yes | Its status: draft, active, blocked or inactive. |
same |
array of "iban" | "name" | "vat_number" |
yes | What both have in common: the VAT number (compared as a registration), an IBAN, or the name (case, punctuation and legal forms such as AG or GmbH ignored). |
message |
string | yes | The warning in words, e.g. Possible duplicate of V-ALP Alpen Werkzeug AG: same VAT number and IBAN. |
RegisterCheck
What the public register says about a VAT number. Advisory: nothing is refused on it.
| Field | Type | Required | Description |
|---|---|---|---|
country |
string | yes | ISO 3166-1 alpha-2 country the number was checked for. |
vat_number |
string | yes | The number as it was sent to the register, compacted. |
registry |
"ch_uid" | "uk_hmrc" | "vies" or null |
yes | vies (EU VIES, also XI for Northern Ireland), ch_uid (Swiss UID register) or uk_hmrc (HMRC's VAT number check); null when the country has none here. |
status |
"invalid" | "no_register" | "not_configured" | "unavailable" | "valid" |
yes | valid (the register knows the number as registered for VAT), invalid (it does not), unavailable (the register did not answer: try again later), not_configured (this server has no access to the register yet, e.g. HMRC without its credentials: the number was not checked) or no_register (no register is checked for this country). |
name |
string or null | The registered name, when the register gives one. | |
address |
string or null | The registered address on one line, when the register gives one. | |
street |
string or null | Street, when the register splits it. | |
building_number |
string or null | Building number, if given. | |
postal_code |
string or null | Postal code, if given. | |
town |
string or null | Town, if given. | |
name_matches |
boolean or null | Whether the registered name matches name of the request (case, punctuation and legal-form suffixes ignored); null when either is missing. |
|
message |
string or null | Why the number is invalid or the register unavailable. | |
reference |
string or null | The register's reference for this consultation, kept as proof that the number was checked: HMRC's consultation number, given when the check names your own UK VAT number as the one asking (a customer or vendor card's check does). | |
checked_at |
string (date-time) | yes | When the register answered (UTC). |
cached |
boolean | true when the answer came from the last day's cache. (default false) |
RegisterCheckInput
A VAT number to check, in the body: a sole trader's number and name are personal data and stay out of URLs and access logs.
| Field | Type | Required | Description |
|---|---|---|---|
country |
string or null | ISO 3166-1 alpha-2 country of the party, e.g. DE. A number shaped like another country's (e.g. an IE registration of a US company, ATU… at a German address) is checked in that country's register. Omitted: the country the number's prefix names (no_register for a number without one); the answer says which. (pattern ^[A-Za-z]{2}$) |
|
vat_number |
string | yes | The VAT number as written, e.g. DE811569869 or CHE-123.456.788 MWST. (min length 4; max length 40) |
name |
string or null | The party's name as you have it: name_matches says whether the register's name is the same company's. (max length 200) |