StabisoDocs

API reference

VAT returns

VAT settings and returns (CH, DE; Canada's GST/HST and QST): compute, finalise, amend, settle.

Operation Summary Scope Idempotency-Key
GET /v1/entities/{entity}/vat-periods List the return periods of a year read
GET /v1/entities/{entity}/vat-settings Get the VAT settings of an entity read
PUT /v1/entities/{entity}/vat-settings Save the VAT settings of an entity admin
GET /v1/vat-returns List VAT returns read
POST /v1/vat-returns Compute a draft VAT return draft required
GET /v1/vat-returns/{return_id} Get a VAT return read
POST /v1/vat-returns/{return_id}/amend Open a correction of a final VAT return approve required
GET /v1/vat-returns/{return_id}/boxes/{box}/lines List the ledger lines behind a box read
POST /v1/vat-returns/{return_id}/discard Discard a draft VAT return draft required
GET /v1/vat-returns/{return_id}/file Return File read
POST /v1/vat-returns/{return_id}/finalize Finalise a VAT return draft required
GET /v1/vat-returns/{return_id}/payment-candidates List the entries that may have paid a VAT return read
POST /v1/vat-returns/{return_id}/payments Link the entry that paid a VAT return draft required
POST /v1/vat-returns/{return_id}/payments/{payment_id}/unlink Unlink a payment from a VAT return draft required
POST /v1/vat-returns/{return_id}/recompute Recompute a draft VAT return draft required
POST /v1/vat-returns/{return_id}/submitted Record that a VAT return was submitted draft required
POST /v1/vat-returns/{return_id}/submitted/withdraw Withdraw the recorded submission of a VAT return draft required

GET /v1/entities/{entity}/vat-periods

List the return periods of a year

The year's return periods as set in the entity's VAT settings: the VAT return periods and, when a recapitulative statement period is set, its periods too. Each row names the live return of the period (return_id, reference, payable) and its status; a period without a draft, pending, final or amending return has the status open. Periods are calendar months, quarters, half years or years, independent of the fiscal calendar. Each row also says when its return is due to be filed and paid (due_date, by the country's rule, null where none is known) and, seen from today, due_status: filed, upcoming, due_soon, overdue or unknown.

Required scope read (admin implies every scope)
Operation id vat_periods_v1_entities__entity__vat_periods_get

Parameters

In Name Type Required Description
path entity string yes Entity code, e.g. CH01 (GET /v1/entities).
query year integer yes Calendar year, 2000 to 2100. (min 2000; max 2100)

Example request

curl "$ERP_URL/v1/entities/CH01/vat-periods?year=2026" \
  -H "Authorization: Bearer $ERP_KEY"

Responses

Status Meaning Body
200 OK array of VatPeriod
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)

[
  {
    "filing_status": "not_submitted",
    "submitted_on": "2026-09-21",
    "submission_reference": "string",
    "submitted_by": {},
    "submitted_at": "2026-09-21T09:30:00Z",
    "settled_amount": "string",
    "paid_amount": "string",
    "payment_difference": "string",
    "payments": [
      {
        "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "journal_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "entry_number": null,
        "paid_on": "2026-09-21",
        "amount": "string",
        "linked_by": {},
        "linked_at": "2026-09-21T09:30:00Z"
      }
    ],
    "period": "string",
    "start": "2026-09-21",
    "end": "2026-09-21",
    "kind": "annual_summary",
    "return_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "reference": "string",
    "status": "string",
    "payable": "string",
    "due_date": "2026-09-21",
    "payment_due_date": "2026-09-21",
    "due_status": "unknown",
    "payment_overdue": false
  }
]

GET /v1/entities/{entity}/vat-settings

Get the VAT settings of an entity

How the entity files VAT: method, return period, recapitulative statement (ZM) period, tax number, net tax rates and settlement account. Until settings are saved (configured is false) the defaults apply: a Swiss entity files by the effective method per quarter, a German one with the standard method per month and a monthly ZM, a Spanish one per quarter with a quarterly Modelo 349, any other entity per quarter.

Required scope read (admin implies every scope)
Operation id get_settings_v1_entities__entity__vat_settings_get

Parameters

In Name Type Required Description
path entity string yes Entity code, e.g. CH01 (GET /v1/entities).

Example request

curl "$ERP_URL/v1/entities/CH01/vat-settings" \
  -H "Authorization: Bearer $ERP_KEY"

Responses

Status Meaning Body
200 OK VatSettingsOut
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",
  "country": "string",
  "vat_number": "string",
  "subdivision": "string",
  "configured": true,
  "registered_from": "2026-09-21",
  "method": "effective",
  "period": "half_year",
  "basis": "invoice",
  "cash_basis_law": "string",
  "cash_basis_condition": "string",
  "cash_basis_purchases": false,
  "cash_basis_open": 0,
  "recapitulative_period": "month",
  "tax_number": "string",
  "net_tax_rates": [
    {
      "accounts": [
        "3400"
      ],
      "activity_id": "A1234",
      "series": "ch.vat.net_rate.treuhandbuero"
    }
  ],
  "settlement_account": "string",
  "tax_fx": "daily",
  "tax_fx_booking": false,
  "filing_extension": false,
  "registrations": [
    "string"
  ],
  "provincial_periods": {},
  "quick_method": "resale",
  "oss_available": false,
  "oss": false,
  "oss_from": "2026-09-21",
  "oss_destination": false
}

PUT /v1/entities/{entity}/vat-settings

Save the VAT settings of an entity

Saves how the entity files VAT (the body replaces the stored settings) and returns them. The effective and net_tax_rate methods exist in Switzerland only and standard everywhere else; the net tax rate method needs the ESTV-approved rate series, each known to the reference data, and at most one of them may leave its accounts empty. Answers 422 for a method the country does not have, for net tax rates under another method, for an unknown account or rate series, or for a tax_fx method the country does not offer, for a period other than month or quarter in Italy or the United Kingdom, and 409 when tax_fx would change while posted documents converted with the current method are not yet covered by a final return.

Required scope admin (admin implies every scope)
Idempotency-Key not used
Operation id put_settings_v1_entities__entity__vat_settings_put

Parameters

In Name Type Required Description
path entity string yes Entity code, e.g. CH01 (GET /v1/entities).

Request body

application/json (required): VatSettingsInput

Field Type Required Description
method "effective" | "net_tax_rate" | "quick" | "standard" yes 'effective' or 'net_tax_rate' (CH), 'quick' (CA), else 'standard'.
period "half_year" | "month" | "quarter" | "two_months" | "year" yes Return period: month, two_months (the Norwegian termin), quarter, half_year or year.
basis "cash" | "invoice" or null invoice or cash (VAT due when paid), where the country offers it (cash_basis_law). It applies to the documents posted from then on; those posted before keep theirs. Omit to keep the current basis (default invoice).
recapitulative_period "month" | "quarter" or null EU recapitulative statement (ZM) period.
tax_number string or null DE: Steuernummer.
registered_from string (date) or null The day the VAT registration takes effect (a company registered after its books start, or one that kept its earlier returns elsewhere): periods that end before it are not listed as due and not named as unfiled. Omit to keep it; null: since the books start.
net_tax_rates array of VatNetTaxRate The net tax rates the ESTV approved, with their activity codes. Required for net_tax_rate and refused for any other method. Default: none.
settlement_account string or null Account for the VAT payable or receivable (default: role).
tax_fx "daily" | "ecb_daily" | "monthly" or null Official exchange rates for the VAT on foreign-currency documents. CH (MWSTV Art. 45): 'monthly' (ESTV monthly average, default) or 'daily' (daily selling rate); keep the method for at least a whole tax period. DE (UStG §16 Abs. 6): 'monthly' (BMF monthly average, default) or 'ecb_daily' (daily ECB rate, only with the tax office's approval). Omit to keep the current method.
tax_fx_booking boolean or null Also book foreign-currency documents at the official VAT rate instead of the ECB fixing (only rates published when the document is posted). Omit to keep the current choice (default false).
filing_extension boolean or null DE only: the tax office granted the permanent extension of the filing deadline (Dauerfristverlängerung, UStDV §§ 46-48), so each advance return is due on the 10th of the second month after its period. Omit to keep the current choice (default false).
registrations array of string or null CA: the provinces besides its own whose sales tax the entity collects: CA-QC, CA-BC, CA-SK, CA-MB. Omit to keep the current list.
provincial_periods map of "half_year" | "month" | "quarter" | "two_months" | "year" or null CA: per province (CA-BC, CA-SK, CA-MB, CA-QC), the period of its sales tax return where it differs from period. Omit to keep the current periods.
quick_method "resale" | "services" or null CA, required with method quick: resale (goods bought for resale are at least 40% of taxable sales) or services.
oss boolean or null EU only: registered for the One-Stop Shop (OSS) union scheme. Omit to keep the current choice (default false).
oss_from string (date) or null EU only: the day the OSS registration takes effect: the first day of the quarter after the registration, or the day of the first such sale when it is notified by the 10th of the following month (Implementing Regulation 282/2011 art. 57d). Omit to keep it; when oss is switched on without one, the first day of the current quarter.
oss_destination boolean or null EU only: charge the customer's VAT on distance sales to consumers in other member states below the EUR 10,000 threshold too (art. 59c(3); binding for two calendar years). Omit to keep the current choice (default false).

Example request

curl -X PUT "$ERP_URL/v1/entities/CH01/vat-settings" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "method": "effective",
  "period": "quarter",
  "settlement_account": "2202"
}'

Responses

Status Meaning Body
200 OK VatSettingsOut
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)

{
  "entity": "string",
  "country": "string",
  "vat_number": "string",
  "subdivision": "string",
  "configured": true,
  "registered_from": "2026-09-21",
  "method": "effective",
  "period": "half_year",
  "basis": "invoice",
  "cash_basis_law": "string",
  "cash_basis_condition": "string",
  "cash_basis_purchases": false,
  "cash_basis_open": 0,
  "recapitulative_period": "month",
  "tax_number": "string",
  "net_tax_rates": [
    {
      "accounts": [
        "3400"
      ],
      "activity_id": "A1234",
      "series": "ch.vat.net_rate.treuhandbuero"
    }
  ],
  "settlement_account": "string",
  "tax_fx": "daily",
  "tax_fx_booking": false,
  "filing_extension": false,
  "registrations": [
    "string"
  ],
  "provincial_periods": {},
  "quick_method": "resale",
  "oss_available": false,
  "oss": false,
  "oss_from": "2026-09-21",
  "oss_destination": false
}

GET /v1/vat-returns

List VAT returns

Summaries of the organization's VAT returns, newest period first, without their boxes: status, payable, the settlement entry and the number of errors and warnings. Open one with GET /v1/vat-returns/{return_id} for the boxes and issues. All filters are optional and combine; discarded and superseded returns are listed unless filtered.

Required scope read (admin implies every scope)
Operation id list_returns_v1_vat_returns_get

Parameters

In Name Type Required Description
query entity string or null Only returns of this entity, by code.
query kind "annual_summary" | "oss_return" | "pst_return_bc" | "pst_return_sk" | "qst_return" | "recapitulative_statement" | "rst_return_mb" | "vat_return" or null Only this kind: vat_return, recapitulative_statement, qst_return, pst_return_bc, pst_return_sk, rst_return_mb, annual_summary, oss_return.
query status string or null Only returns with this status: draft, pending_approval, final, amending, superseded or discarded.
query year integer or null Only returns whose period starts in this calendar year.

Example request

curl "$ERP_URL/v1/vat-returns" \
  -H "Authorization: Bearer $ERP_KEY"

Responses

Status Meaning Body
200 OK array of VatReturnSummary
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
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)

[
  {
    "filing_status": "not_submitted",
    "submitted_on": "2026-09-21",
    "submission_reference": "string",
    "submitted_by": {},
    "submitted_at": "2026-09-21T09:30:00Z",
    "settled_amount": "string",
    "paid_amount": "string",
    "payment_difference": "string",
    "payments": [
      {
        "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "journal_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "entry_number": null,
        "paid_on": "2026-09-21",
        "amount": "string",
        "linked_by": {},
        "linked_at": "2026-09-21T09:30:00Z"
      }
    ],
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "entity": "string",
    "kind": "annual_summary",
    "reference": "string",
    "form_id": "string",
    "form_version": "string",
    "method": "string",
    "period": "string",
    "start": "2026-09-21",
    "end": "2026-09-21",
    "status": "string",
    "currency": "string",
    "payable": "string",
    "amends_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "settlement_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "settlement_entry_number": "string",
    "errors": 1,
    "warnings": 1,
    "computed_at": "2026-09-21T09:30:00Z",
    "finalized_at": "2026-09-21T09:30:00Z",
    "finalized_by": {}
  }
]

POST /v1/vat-returns

Compute a draft VAT return

Computes a draft return (vat_return, the EU recapitulative_statement, or the annual_summary where the country has one, the Spanish Modelo 390) for an entity and period (2026-08, 2026-Q3, 2026-H2 or 2026) from the posted, tax-tagged journal lines, and stores which line fills which box. An existing draft of the period is recomputed instead. The result carries the boxes, the reconciliation with the VAT accounts and the issues. Answers 409 when the period already has a pending, final or amending return (amend it instead) and 422 for a malformed period or an adjustment on a box the ledger fills or computes.

Required scope draft (admin implies every scope)
Idempotency-Key required
Operation id create_return_v1_vat_returns_post

Request body

application/json (required): VatReturnInput

Field Type Required Description
entity string yes Entity code, e.g. CH01 or DE01 (GET /v1/entities).
kind "annual_summary" | "oss_return" | "pst_return_bc" | "pst_return_sk" | "qst_return" | "recapitulative_statement" | "rst_return_mb" | "vat_return" vat_return, recapitulative_statement (ZM, Modelo 349), qst_return (Quebec), pst_return_bc, pst_return_sk, rst_return_mb, annual_summary (Modelo 390, Dichiarazione IVA) or oss_return (EU One-Stop Shop, union scheme). Default vat_return; annual_summary takes the period YYYY. (default "vat_return")
period string yes '2026-08', '2026-Q3', '2026-H2' or '2026'.
adjustments array of VatAdjustment-Input Hand-entered amounts for boxes the ledger cannot fill (import VAT, Einlageentsteuerung and similar). Default: none.

Example request

curl -X POST "$ERP_URL/v1/vat-returns" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "entity": "CH01",
  "kind": "vat_return",
  "period": "2026-Q3"
}'

Responses

Status Meaning Body
201 Created VatReturnOut
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)

{
  "filing_status": "not_submitted",
  "submitted_on": "2026-09-21",
  "submission_reference": "string",
  "submitted_by": {},
  "submitted_at": "2026-09-21T09:30:00Z",
  "settled_amount": "string",
  "paid_amount": "string",
  "payment_difference": "string",
  "payments": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "journal_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "entry_number": "string",
      "paid_on": "2026-09-21",
      "amount": "string",
      "linked_by": {},
      "linked_at": "2026-09-21T09:30:00Z"
    }
  ],
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "entity": "string",
  "kind": "annual_summary",
  "reference": "string",
  "form_id": "string",
  "form_version": "string",
  "method": "string",
  "period": "string",
  "start": "2026-09-21",
  "end": "2026-09-21",
  "status": "string",
  "currency": "string",
  "payable": "string",
  "amends_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "settlement_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "settlement_entry_number": "string",
  "errors": 1,
  "warnings": 1,
  "computed_at": "2026-09-21T09:30:00Z",
  "finalized_at": "2026-09-21T09:30:00Z",
  "finalized_by": {},
  "result": {
    "kind": "annual_summary",
    "form": {
      "id": "string",
      "jurisdiction": "",
      "name": "string",
      "kind": "annual_summary",
      "method": null,
      "version": "string",
      "currency": "string",
      "base_precision": 1,
      "tax_precision": 2,
      "notes": [
        null
      ],
      "limitations": [
        null
      ],
      "sources": [
        null
      ]
    },
    "entity": "string",
    "entity_name": "string",
    "vat_number": "string",
    "tax_number": "string",
    "period": "string",
    "start": "2026-09-21",
    "end": "2026-09-21",
    "currency": "string",
    "method": "string",
    "boxes": [
      {
        "id": null,
        "code": null,
        "line": null,
        "label": null,
        "section": null,
        "unit": null,
        "rate": null,
        "amount": null,
        "tax": null,
        "computed": null,
        "lines": null,
        "adjustable": null,
        "adjusted": null,
        "filled": null,
        "xml": null,
        "by_rate": null
      }
    ],
    "rows": [
      {
        "country_code": null,
        "vat_id": null,
        "party": null,
        "box": null,
        "amount": null
      }
    ],
    "oss_rows": [
      {
        "member_state": null,
        "supply": null,
        "rate": null,
        "rate_type": null,
        "base": null,
        "vat": null
      }
    ],
    "oss_corrections": [
      {
        "period": null,
        "member_state": null,
        "vat": null
      }
    ],
    "activities": [
      {
        "activity_id": null,
        "series": null,
        "activity": null,
        "rate": null,
        "turnover": null,
        "tax": null
      }
    ],
    "payable": "string",
    "reconciliation": {
      "accounts": null,
      "ledger": null,
      "reported": null,
      "other_period": null,
      "payable": null,
      "adjustments": null,
      "computation_difference": null,
      "tax_fx_difference": null,
      "whole_unit_rounding": null,
      "unexplained": null,
      "settlement": null,
      "reconciling_items": null
    },
    "adjustments": [
      {
        "account": "1020",
        "amount": "120.00",
        "box": "410",
        "note": "Import VAT paid to customs"
      }
    ],
    "issues": [
      {
        "severity": null,
        "code": null,
        "message": null,
        "details": null
      }
    ],
    "lines": 1,
    "dataset_version": "string",
    "tax_fx": [
      {
        "series": null,
        "currency": null,
        "period": null,
        "rate": null,
        "quotation": null,
        "lines": null,
        "looked_up": null
      }
    ],
    "payment_code": "string",
    "payment_due_date": "2026-09-21"
  },
  "explanation": "string",
  "adjustments": [
    {
      "account": "1020",
      "amount": "120.00",
      "box": "410",
      "note": "Import VAT paid to customs"
    }
  ],
  "test_copy": false
}

GET /v1/vat-returns/{return_id}

Get a VAT return

The return as stored: status, payable, the settlement entry and the computed result (form, boxes with their Ziffer or Kennzahl, reconciliation, issues, adjustments). A final return and its result do not change; a draft shows the state of its last computation.

Required scope read (admin implies every scope)
Operation id get_return_v1_vat_returns__return_id__get

Parameters

In Name Type Required Description
path return_id string (uuid) yes VAT return id.

Example request

curl "$ERP_URL/v1/vat-returns/3fa85f64-5717-4562-b3fc-2c963f66afa6" \
  -H "Authorization: Bearer $ERP_KEY"

Responses

Status Meaning Body
200 OK VatReturnOut
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)

{
  "filing_status": "not_submitted",
  "submitted_on": "2026-09-21",
  "submission_reference": "string",
  "submitted_by": {},
  "submitted_at": "2026-09-21T09:30:00Z",
  "settled_amount": "string",
  "paid_amount": "string",
  "payment_difference": "string",
  "payments": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "journal_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "entry_number": "string",
      "paid_on": "2026-09-21",
      "amount": "string",
      "linked_by": {},
      "linked_at": "2026-09-21T09:30:00Z"
    }
  ],
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "entity": "string",
  "kind": "annual_summary",
  "reference": "string",
  "form_id": "string",
  "form_version": "string",
  "method": "string",
  "period": "string",
  "start": "2026-09-21",
  "end": "2026-09-21",
  "status": "string",
  "currency": "string",
  "payable": "string",
  "amends_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "settlement_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "settlement_entry_number": "string",
  "errors": 1,
  "warnings": 1,
  "computed_at": "2026-09-21T09:30:00Z",
  "finalized_at": "2026-09-21T09:30:00Z",
  "finalized_by": {},
  "result": {
    "kind": "annual_summary",
    "form": {
      "id": "string",
      "jurisdiction": "",
      "name": "string",
      "kind": "annual_summary",
      "method": null,
      "version": "string",
      "currency": "string",
      "base_precision": 1,
      "tax_precision": 2,
      "notes": [
        null
      ],
      "limitations": [
        null
      ],
      "sources": [
        null
      ]
    },
    "entity": "string",
    "entity_name": "string",
    "vat_number": "string",
    "tax_number": "string",
    "period": "string",
    "start": "2026-09-21",
    "end": "2026-09-21",
    "currency": "string",
    "method": "string",
    "boxes": [
      {
        "id": null,
        "code": null,
        "line": null,
        "label": null,
        "section": null,
        "unit": null,
        "rate": null,
        "amount": null,
        "tax": null,
        "computed": null,
        "lines": null,
        "adjustable": null,
        "adjusted": null,
        "filled": null,
        "xml": null,
        "by_rate": null
      }
    ],
    "rows": [
      {
        "country_code": null,
        "vat_id": null,
        "party": null,
        "box": null,
        "amount": null
      }
    ],
    "oss_rows": [
      {
        "member_state": null,
        "supply": null,
        "rate": null,
        "rate_type": null,
        "base": null,
        "vat": null
      }
    ],
    "oss_corrections": [
      {
        "period": null,
        "member_state": null,
        "vat": null
      }
    ],
    "activities": [
      {
        "activity_id": null,
        "series": null,
        "activity": null,
        "rate": null,
        "turnover": null,
        "tax": null
      }
    ],
    "payable": "string",
    "reconciliation": {
      "accounts": null,
      "ledger": null,
      "reported": null,
      "other_period": null,
      "payable": null,
      "adjustments": null,
      "computation_difference": null,
      "tax_fx_difference": null,
      "whole_unit_rounding": null,
      "unexplained": null,
      "settlement": null,
      "reconciling_items": null
    },
    "adjustments": [
      {
        "account": "1020",
        "amount": "120.00",
        "box": "410",
        "note": "Import VAT paid to customs"
      }
    ],
    "issues": [
      {
        "severity": null,
        "code": null,
        "message": null,
        "details": null
      }
    ],
    "lines": 1,
    "dataset_version": "string",
    "tax_fx": [
      {
        "series": null,
        "currency": null,
        "period": null,
        "rate": null,
        "quotation": null,
        "lines": null,
        "looked_up": null
      }
    ],
    "payment_code": "string",
    "payment_due_date": "2026-09-21"
  },
  "explanation": "string",
  "adjustments": [
    {
      "account": "1020",
      "amount": "120.00",
      "box": "410",
      "note": "Import VAT paid to customs"
    }
  ],
  "test_copy": false
}

POST /v1/vat-returns/{return_id}/amend

Open a correction of a final VAT return

Opens a correction of a final return: the original becomes amending, the period's VAT postings are unlocked, and a new draft (its amends_id names the original) is computed from the current ledger. Finalising the correction books only the difference to the original in its settlement and marks the original superseded; discarding the correction puts the original back in force. Takes no body. Needs the approval policy action finalize_vat_return (403 when denied) and answers 409 unless the return is final.

Required scope approve (admin implies every scope)
Idempotency-Key required
Operation id amend_v1_vat_returns__return_id__amend_post

Parameters

In Name Type Required Description
path return_id string (uuid) yes VAT return id.

Example request

curl -X POST "$ERP_URL/v1/vat-returns/3fa85f64-5717-4562-b3fc-2c963f66afa6/amend" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Idempotency-Key: $(uuidgen)"

Responses

Status Meaning Body
201 Created VatReturnOut
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)

{
  "filing_status": "not_submitted",
  "submitted_on": "2026-09-21",
  "submission_reference": "string",
  "submitted_by": {},
  "submitted_at": "2026-09-21T09:30:00Z",
  "settled_amount": "string",
  "paid_amount": "string",
  "payment_difference": "string",
  "payments": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "journal_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "entry_number": "string",
      "paid_on": "2026-09-21",
      "amount": "string",
      "linked_by": {},
      "linked_at": "2026-09-21T09:30:00Z"
    }
  ],
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "entity": "string",
  "kind": "annual_summary",
  "reference": "string",
  "form_id": "string",
  "form_version": "string",
  "method": "string",
  "period": "string",
  "start": "2026-09-21",
  "end": "2026-09-21",
  "status": "string",
  "currency": "string",
  "payable": "string",
  "amends_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "settlement_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "settlement_entry_number": "string",
  "errors": 1,
  "warnings": 1,
  "computed_at": "2026-09-21T09:30:00Z",
  "finalized_at": "2026-09-21T09:30:00Z",
  "finalized_by": {},
  "result": {
    "kind": "annual_summary",
    "form": {
      "id": "string",
      "jurisdiction": "",
      "name": "string",
      "kind": "annual_summary",
      "method": null,
      "version": "string",
      "currency": "string",
      "base_precision": 1,
      "tax_precision": 2,
      "notes": [
        null
      ],
      "limitations": [
        null
      ],
      "sources": [
        null
      ]
    },
    "entity": "string",
    "entity_name": "string",
    "vat_number": "string",
    "tax_number": "string",
    "period": "string",
    "start": "2026-09-21",
    "end": "2026-09-21",
    "currency": "string",
    "method": "string",
    "boxes": [
      {
        "id": null,
        "code": null,
        "line": null,
        "label": null,
        "section": null,
        "unit": null,
        "rate": null,
        "amount": null,
        "tax": null,
        "computed": null,
        "lines": null,
        "adjustable": null,
        "adjusted": null,
        "filled": null,
        "xml": null,
        "by_rate": null
      }
    ],
    "rows": [
      {
        "country_code": null,
        "vat_id": null,
        "party": null,
        "box": null,
        "amount": null
      }
    ],
    "oss_rows": [
      {
        "member_state": null,
        "supply": null,
        "rate": null,
        "rate_type": null,
        "base": null,
        "vat": null
      }
    ],
    "oss_corrections": [
      {
        "period": null,
        "member_state": null,
        "vat": null
      }
    ],
    "activities": [
      {
        "activity_id": null,
        "series": null,
        "activity": null,
        "rate": null,
        "turnover": null,
        "tax": null
      }
    ],
    "payable": "string",
    "reconciliation": {
      "accounts": null,
      "ledger": null,
      "reported": null,
      "other_period": null,
      "payable": null,
      "adjustments": null,
      "computation_difference": null,
      "tax_fx_difference": null,
      "whole_unit_rounding": null,
      "unexplained": null,
      "settlement": null,
      "reconciling_items": null
    },
    "adjustments": [
      {
        "account": "1020",
        "amount": "120.00",
        "box": "410",
        "note": "Import VAT paid to customs"
      }
    ],
    "issues": [
      {
        "severity": null,
        "code": null,
        "message": null,
        "details": null
      }
    ],
    "lines": 1,
    "dataset_version": "string",
    "tax_fx": [
      {
        "series": null,
        "currency": null,
        "period": null,
        "rate": null,
        "quotation": null,
        "lines": null,
        "looked_up": null
      }
    ],
    "payment_code": "string",
    "payment_due_date": "2026-09-21"
  },
  "explanation": "string",
  "adjustments": [
    {
      "account": "1020",
      "amount": "120.00",
      "box": "410",
      "note": "Import VAT paid to customs"
    }
  ],
  "test_copy": false
}

GET /v1/vat-returns/{return_id}/boxes/{box}/lines

List the ledger lines behind a box

The drill-down of one box: every journal line that was routed into it, with its journal entry, account, document, counterparty, the rule that routed it and the amount it contributes in the return's currency. Ordered by entry date and number. A box that is computed from other boxes, filled by adjustment only, or unknown has no lines (an empty list).

Required scope read (admin implies every scope)
Operation id box_lines_v1_vat_returns__return_id__boxes__box__lines_get

Parameters

In Name Type Required Description
path return_id string (uuid) yes VAT return id.
path box string yes Box id as in the return's boxes[].id: a Ziffer such as 303 (CH) or a Kennzahl id such as kz81 (DE).

Example request

curl "$ERP_URL/v1/vat-returns/3fa85f64-5717-4562-b3fc-2c963f66afa6/boxes/303/lines" \
  -H "Authorization: Bearer $ERP_KEY"

Responses

Status Meaning Body
200 OK array of VatBoxLine
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)

[
  {
    "journal_line_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "entry_number": "string",
    "entry_date": "2026-09-21",
    "account": "string",
    "account_name": "string",
    "description": "string",
    "document": "string",
    "counterparty": "string",
    "row_key": "string",
    "rule": "string",
    "amount": "string"
  }
]

POST /v1/vat-returns/{return_id}/discard

Discard a draft VAT return

Discards a draft return, which stays listed with the status discarded; the period can then be computed again. Discarding a correction puts the original back from amending to final. Takes no body. Answers 409 unless the return is a draft.

Required scope draft (admin implies every scope)
Idempotency-Key required
Operation id discard_v1_vat_returns__return_id__discard_post

Parameters

In Name Type Required Description
path return_id string (uuid) yes VAT return id.

Example request

curl -X POST "$ERP_URL/v1/vat-returns/3fa85f64-5717-4562-b3fc-2c963f66afa6/discard" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Idempotency-Key: $(uuidgen)"

Responses

Status Meaning Body
200 OK VatReturnOut
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)

{
  "filing_status": "not_submitted",
  "submitted_on": "2026-09-21",
  "submission_reference": "string",
  "submitted_by": {},
  "submitted_at": "2026-09-21T09:30:00Z",
  "settled_amount": "string",
  "paid_amount": "string",
  "payment_difference": "string",
  "payments": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "journal_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "entry_number": "string",
      "paid_on": "2026-09-21",
      "amount": "string",
      "linked_by": {},
      "linked_at": "2026-09-21T09:30:00Z"
    }
  ],
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "entity": "string",
  "kind": "annual_summary",
  "reference": "string",
  "form_id": "string",
  "form_version": "string",
  "method": "string",
  "period": "string",
  "start": "2026-09-21",
  "end": "2026-09-21",
  "status": "string",
  "currency": "string",
  "payable": "string",
  "amends_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "settlement_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "settlement_entry_number": "string",
  "errors": 1,
  "warnings": 1,
  "computed_at": "2026-09-21T09:30:00Z",
  "finalized_at": "2026-09-21T09:30:00Z",
  "finalized_by": {},
  "result": {
    "kind": "annual_summary",
    "form": {
      "id": "string",
      "jurisdiction": "",
      "name": "string",
      "kind": "annual_summary",
      "method": null,
      "version": "string",
      "currency": "string",
      "base_precision": 1,
      "tax_precision": 2,
      "notes": [
        null
      ],
      "limitations": [
        null
      ],
      "sources": [
        null
      ]
    },
    "entity": "string",
    "entity_name": "string",
    "vat_number": "string",
    "tax_number": "string",
    "period": "string",
    "start": "2026-09-21",
    "end": "2026-09-21",
    "currency": "string",
    "method": "string",
    "boxes": [
      {
        "id": null,
        "code": null,
        "line": null,
        "label": null,
        "section": null,
        "unit": null,
        "rate": null,
        "amount": null,
        "tax": null,
        "computed": null,
        "lines": null,
        "adjustable": null,
        "adjusted": null,
        "filled": null,
        "xml": null,
        "by_rate": null
      }
    ],
    "rows": [
      {
        "country_code": null,
        "vat_id": null,
        "party": null,
        "box": null,
        "amount": null
      }
    ],
    "oss_rows": [
      {
        "member_state": null,
        "supply": null,
        "rate": null,
        "rate_type": null,
        "base": null,
        "vat": null
      }
    ],
    "oss_corrections": [
      {
        "period": null,
        "member_state": null,
        "vat": null
      }
    ],
    "activities": [
      {
        "activity_id": null,
        "series": null,
        "activity": null,
        "rate": null,
        "turnover": null,
        "tax": null
      }
    ],
    "payable": "string",
    "reconciliation": {
      "accounts": null,
      "ledger": null,
      "reported": null,
      "other_period": null,
      "payable": null,
      "adjustments": null,
      "computation_difference": null,
      "tax_fx_difference": null,
      "whole_unit_rounding": null,
      "unexplained": null,
      "settlement": null,
      "reconciling_items": null
    },
    "adjustments": [
      {
        "account": "1020",
        "amount": "120.00",
        "box": "410",
        "note": "Import VAT paid to customs"
      }
    ],
    "issues": [
      {
        "severity": null,
        "code": null,
        "message": null,
        "details": null
      }
    ],
    "lines": 1,
    "dataset_version": "string",
    "tax_fx": [
      {
        "series": null,
        "currency": null,
        "period": null,
        "rate": null,
        "quotation": null,
        "lines": null,
        "looked_up": null
      }
    ],
    "payment_code": "string",
    "payment_due_date": "2026-09-21"
  },
  "explanation": "string",
  "adjustments": [
    {
      "account": "1020",
      "amount": "120.00",
      "box": "410",
      "note": "Import VAT paid to customs"
    }
  ],
  "test_copy": false
}

GET /v1/vat-returns/{return_id}/file

Return File

Downloads the return in the requested format: xml is the eCH-0217 upload for the ESTV portal, csv the ZM import for the BZStOnline-Portal, html and pdf are printable (shown inline, marked with the status and as a correction where it is one) and json is the return itself. Works for a draft too. Answers 422 when the format does not fit the return: xml needs a Swiss VAT return with an amount payable and the entity's UID, csv a recapitulative statement with at least one and at most 1000 rows.

Required scope read (admin implies every scope)
Operation id return_file_v1_vat_returns__return_id__file_get

Parameters

In Name Type Required Description
path return_id string (uuid) yes VAT return id.
query format "csv" | "html" | "json" | "pdf" | "xml" File format: json (the return as GET /v1/vat-returns/{return_id} gives it), xml (eCH-0217, Swiss VAT returns), csv (BZStOnline-Portal ZM import, recapitulative statements), or html / pdf (printable form). (default "json")
query csv_version string ZM CSV: the version the BZStOnline-Portal's import help shows. (pattern ^\d+\.\d+$; default "1.0")

Example request

curl "$ERP_URL/v1/vat-returns/3fa85f64-5717-4562-b3fc-2c963f66afa6/file" \
  -H "Authorization: Bearer $ERP_KEY"

Responses

Status Meaning Body
200 eCH-0217 XML (CH), BZSt ZM CSV (DE), printable HTML or PDF, JSON. application/xml, text/csv, text/html, application/pdf, VatReturnOut
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)

{
  "filing_status": "not_submitted",
  "submitted_on": "2026-09-21",
  "submission_reference": "string",
  "submitted_by": {},
  "submitted_at": "2026-09-21T09:30:00Z",
  "settled_amount": "string",
  "paid_amount": "string",
  "payment_difference": "string",
  "payments": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "journal_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "entry_number": "string",
      "paid_on": "2026-09-21",
      "amount": "string",
      "linked_by": {},
      "linked_at": "2026-09-21T09:30:00Z"
    }
  ],
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "entity": "string",
  "kind": "annual_summary",
  "reference": "string",
  "form_id": "string",
  "form_version": "string",
  "method": "string",
  "period": "string",
  "start": "2026-09-21",
  "end": "2026-09-21",
  "status": "string",
  "currency": "string",
  "payable": "string",
  "amends_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "settlement_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "settlement_entry_number": "string",
  "errors": 1,
  "warnings": 1,
  "computed_at": "2026-09-21T09:30:00Z",
  "finalized_at": "2026-09-21T09:30:00Z",
  "finalized_by": {},
  "result": {
    "kind": "annual_summary",
    "form": {
      "id": "string",
      "jurisdiction": "",
      "name": "string",
      "kind": "annual_summary",
      "method": null,
      "version": "string",
      "currency": "string",
      "base_precision": 1,
      "tax_precision": 2,
      "notes": [
        null
      ],
      "limitations": [
        null
      ],
      "sources": [
        null
      ]
    },
    "entity": "string",
    "entity_name": "string",
    "vat_number": "string",
    "tax_number": "string",
    "period": "string",
    "start": "2026-09-21",
    "end": "2026-09-21",
    "currency": "string",
    "method": "string",
    "boxes": [
      {
        "id": null,
        "code": null,
        "line": null,
        "label": null,
        "section": null,
        "unit": null,
        "rate": null,
        "amount": null,
        "tax": null,
        "computed": null,
        "lines": null,
        "adjustable": null,
        "adjusted": null,
        "filled": null,
        "xml": null,
        "by_rate": null
      }
    ],
    "rows": [
      {
        "country_code": null,
        "vat_id": null,
        "party": null,
        "box": null,
        "amount": null
      }
    ],
    "oss_rows": [
      {
        "member_state": null,
        "supply": null,
        "rate": null,
        "rate_type": null,
        "base": null,
        "vat": null
      }
    ],
    "oss_corrections": [
      {
        "period": null,
        "member_state": null,
        "vat": null
      }
    ],
    "activities": [
      {
        "activity_id": null,
        "series": null,
        "activity": null,
        "rate": null,
        "turnover": null,
        "tax": null
      }
    ],
    "payable": "string",
    "reconciliation": {
      "accounts": null,
      "ledger": null,
      "reported": null,
      "other_period": null,
      "payable": null,
      "adjustments": null,
      "computation_difference": null,
      "tax_fx_difference": null,
      "whole_unit_rounding": null,
      "unexplained": null,
      "settlement": null,
      "reconciling_items": null
    },
    "adjustments": [
      {
        "account": "1020",
        "amount": "120.00",
        "box": "410",
        "note": "Import VAT paid to customs"
      }
    ],
    "issues": [
      {
        "severity": null,
        "code": null,
        "message": null,
        "details": null
      }
    ],
    "lines": 1,
    "dataset_version": "string",
    "tax_fx": [
      {
        "series": null,
        "currency": null,
        "period": null,
        "rate": null,
        "quotation": null,
        "lines": null,
        "looked_up": null
      }
    ],
    "payment_code": "string",
    "payment_due_date": "2026-09-21"
  },
  "explanation": "string",
  "adjustments": [
    {
      "account": "1020",
      "amount": "120.00",
      "box": "410",
      "note": "Import VAT paid to customs"
    }
  ],
  "test_copy": false
}

POST /v1/vat-returns/{return_id}/finalize

Finalise a VAT return

Finalises a draft: it is recomputed, and the settlement entry (source vat, clearing the reported VAT to the settlement account) goes through the approval policy. The response's settlement.policy is the decision: when the entry is posted the return is final and the period's VAT postings are locked; when it needs a second person the return is pending_approval until the entry is approved or rejected (a rejection puts it back to draft). A return with nothing to settle, such as a recapitulative statement, becomes final at once and settlement is null. Needs the approval policy action finalize_vat_return (403 when denied, which is the default for agents). Answers 409 when the return is not a draft, the ledger changed since it was computed, it has error issues, or the VAT accounts hold amounts it does not explain and no explanation is given; 422 when posting_date is before the period's end or no open period follows.

Required scope draft (admin implies every scope)
Idempotency-Key required
Operation id finalize_v1_vat_returns__return_id__finalize_post

Parameters

In Name Type Required Description
path return_id string (uuid) yes VAT return id.

Request body

application/json (required): VatFinalizeInput

Field Type Required Description
posting_date string (date) or null Date of the settlement entry; default the period's last day, or the first open day after it.
explanation string or null Required when the VAT accounts hold amounts the return does not explain. (max length 2000)

Example request

curl -X POST "$ERP_URL/v1/vat-returns/3fa85f64-5717-4562-b3fc-2c963f66afa6/finalize" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "explanation": "The difference is a manual VAT correction booked on 2026-09-12.",
  "posting_date": "2026-09-30"
}'

Responses

Status Meaning Body
200 OK VatFinalizeOut
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)

{
  "vat_return": {
    "filing_status": "not_submitted",
    "submitted_on": "2026-09-21",
    "submission_reference": "string",
    "submitted_by": {},
    "submitted_at": "2026-09-21T09:30:00Z",
    "settled_amount": "string",
    "paid_amount": "string",
    "payment_difference": "string",
    "payments": [
      {
        "id": null,
        "journal_entry_id": null,
        "entry_number": null,
        "paid_on": null,
        "amount": null,
        "linked_by": null,
        "linked_at": null
      }
    ],
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "entity": "string",
    "kind": "annual_summary",
    "reference": "string",
    "form_id": "string",
    "form_version": "string",
    "method": "string",
    "period": "string",
    "start": "2026-09-21",
    "end": "2026-09-21",
    "status": "string",
    "currency": "string",
    "payable": "string",
    "amends_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "settlement_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "settlement_entry_number": "string",
    "errors": 1,
    "warnings": 1,
    "computed_at": "2026-09-21T09:30:00Z",
    "finalized_at": "2026-09-21T09:30:00Z",
    "finalized_by": {},
    "result": {
      "kind": "annual_summary",
      "form": null,
      "entity": "string",
      "entity_name": "string",
      "vat_number": null,
      "tax_number": null,
      "period": "string",
      "start": "2026-09-21",
      "end": "2026-09-21",
      "currency": "string",
      "method": null,
      "boxes": [
        null
      ],
      "rows": [
        null
      ],
      "oss_rows": [
        null
      ],
      "oss_corrections": [
        null
      ],
      "activities": [
        null
      ],
      "payable": null,
      "reconciliation": null,
      "adjustments": [
        null
      ],
      "issues": [
        null
      ],
      "lines": 1,
      "dataset_version": "string",
      "tax_fx": [
        null
      ],
      "payment_code": null,
      "payment_due_date": null
    },
    "explanation": "string",
    "adjustments": [
      {
        "account": "1020",
        "amount": "120.00",
        "box": "410",
        "note": "Import VAT paid to customs"
      }
    ],
    "test_copy": false
  },
  "settlement": {
    "entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "status": "string",
    "number": "string",
    "policy": {
      "decision": null,
      "reason": null,
      "rule_id": null,
      "table_id": null
    },
    "approval_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "reason": "string"
  }
}

GET /v1/vat-returns/{return_id}/payment-candidates

List the entries that may have paid a VAT return

Posted entries of the return's company, dated on or after the settlement, with a line on the settlement account on the side opposite the settlement (a debit for VAT to pay, a credit for a refund) that no return has linked yet; VAT settlements are left out. Typically the bank entry made by matching the bank debit to the settlement account on the bank worksheet. Empty for a return that is not final or settled nothing.

Required scope read (admin implies every scope)
Operation id payment_candidates_v1_vat_returns__return_id__payment_candidates_get

Parameters

In Name Type Required Description
path return_id string (uuid) yes VAT return id.

Example request

curl "$ERP_URL/v1/vat-returns/3fa85f64-5717-4562-b3fc-2c963f66afa6/payment-candidates" \
  -H "Authorization: Bearer $ERP_KEY"

Responses

Status Meaning Body
200 OK array of VatPaymentCandidate
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)

[
  {
    "journal_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "entry_number": "string",
    "entry_date": "2026-09-21",
    "description": "string",
    "source": "string",
    "amount": "string"
  }
]

POST /v1/vat-returns/{return_id}/payments

Link the entry that paid a VAT return

Links a posted entry as paying the return's VAT (or receiving its refund): its amount is what it puts on the settlement account against the settlement and its day the payment day. A part payment is one link of several; the return is paid once the links cover settled_amount, and a difference is shown (payment_difference), not refused. Answers 409 unless the return is final and recorded as submitted, when it settled nothing, or when the entry already pays a return; 422 for an entry of another company, not posted, a VAT settlement, dated before the settlement, or without a line on the settlement account on the paying side. A person's act: needs the approval policy action finalize_vat_return, which agents are always denied (403).

Required scope draft (admin implies every scope)
Idempotency-Key required
Operation id link_payment_v1_vat_returns__return_id__payments_post

Parameters

In Name Type Required Description
path return_id string (uuid) yes VAT return id.

Request body

application/json (required): VatPaymentInput

Field Type Required Description
journal_entry_id string (uuid) yes The posted entry that paid the VAT (or received the refund): of the return's company, dated on or after the settlement, with a line on the settlement account on the side opposite the settlement (GET .../payment-candidates).

Example request

curl -X POST "$ERP_URL/v1/vat-returns/3fa85f64-5717-4562-b3fc-2c963f66afa6/payments" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "journal_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}'

Responses

Status Meaning Body
201 Created VatReturnOut
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)

{
  "filing_status": "not_submitted",
  "submitted_on": "2026-09-21",
  "submission_reference": "string",
  "submitted_by": {},
  "submitted_at": "2026-09-21T09:30:00Z",
  "settled_amount": "string",
  "paid_amount": "string",
  "payment_difference": "string",
  "payments": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "journal_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "entry_number": "string",
      "paid_on": "2026-09-21",
      "amount": "string",
      "linked_by": {},
      "linked_at": "2026-09-21T09:30:00Z"
    }
  ],
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "entity": "string",
  "kind": "annual_summary",
  "reference": "string",
  "form_id": "string",
  "form_version": "string",
  "method": "string",
  "period": "string",
  "start": "2026-09-21",
  "end": "2026-09-21",
  "status": "string",
  "currency": "string",
  "payable": "string",
  "amends_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "settlement_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "settlement_entry_number": "string",
  "errors": 1,
  "warnings": 1,
  "computed_at": "2026-09-21T09:30:00Z",
  "finalized_at": "2026-09-21T09:30:00Z",
  "finalized_by": {},
  "result": {
    "kind": "annual_summary",
    "form": {
      "id": "string",
      "jurisdiction": "",
      "name": "string",
      "kind": "annual_summary",
      "method": null,
      "version": "string",
      "currency": "string",
      "base_precision": 1,
      "tax_precision": 2,
      "notes": [
        null
      ],
      "limitations": [
        null
      ],
      "sources": [
        null
      ]
    },
    "entity": "string",
    "entity_name": "string",
    "vat_number": "string",
    "tax_number": "string",
    "period": "string",
    "start": "2026-09-21",
    "end": "2026-09-21",
    "currency": "string",
    "method": "string",
    "boxes": [
      {
        "id": null,
        "code": null,
        "line": null,
        "label": null,
        "section": null,
        "unit": null,
        "rate": null,
        "amount": null,
        "tax": null,
        "computed": null,
        "lines": null,
        "adjustable": null,
        "adjusted": null,
        "filled": null,
        "xml": null,
        "by_rate": null
      }
    ],
    "rows": [
      {
        "country_code": null,
        "vat_id": null,
        "party": null,
        "box": null,
        "amount": null
      }
    ],
    "oss_rows": [
      {
        "member_state": null,
        "supply": null,
        "rate": null,
        "rate_type": null,
        "base": null,
        "vat": null
      }
    ],
    "oss_corrections": [
      {
        "period": null,
        "member_state": null,
        "vat": null
      }
    ],
    "activities": [
      {
        "activity_id": null,
        "series": null,
        "activity": null,
        "rate": null,
        "turnover": null,
        "tax": null
      }
    ],
    "payable": "string",
    "reconciliation": {
      "accounts": null,
      "ledger": null,
      "reported": null,
      "other_period": null,
      "payable": null,
      "adjustments": null,
      "computation_difference": null,
      "tax_fx_difference": null,
      "whole_unit_rounding": null,
      "unexplained": null,
      "settlement": null,
      "reconciling_items": null
    },
    "adjustments": [
      {
        "account": "1020",
        "amount": "120.00",
        "box": "410",
        "note": "Import VAT paid to customs"
      }
    ],
    "issues": [
      {
        "severity": null,
        "code": null,
        "message": null,
        "details": null
      }
    ],
    "lines": 1,
    "dataset_version": "string",
    "tax_fx": [
      {
        "series": null,
        "currency": null,
        "period": null,
        "rate": null,
        "quotation": null,
        "lines": null,
        "looked_up": null
      }
    ],
    "payment_code": "string",
    "payment_due_date": "2026-09-21"
  },
  "explanation": "string",
  "adjustments": [
    {
      "account": "1020",
      "amount": "120.00",
      "box": "410",
      "note": "Import VAT paid to customs"
    }
  ],
  "test_copy": false
}

POST /v1/vat-returns/{return_id}/payments/{payment_id}/unlink

Unlink a payment from a VAT return

Undoes a payment link made by mistake, with the reason (kept in the history; the link is not deleted and the entry stays posted). 404 for a link that is not in force on this return. A person's act: needs the approval policy action finalize_vat_return, which agents are always denied (403).

Required scope draft (admin implies every scope)
Idempotency-Key required
Operation id unlink_payment_v1_vat_returns__return_id__payments__payment_id__unlink_post

Parameters

In Name Type Required Description
path return_id string (uuid) yes VAT return id.
path payment_id string (uuid) yes Id of the payment link (payments[].id of the return).

Request body

application/json (required): VatReasonInput

Field Type Required Description
reason string yes Why, in a few words; kept in the history. (min length 1; max length 500)

Example request

curl -X POST "$ERP_URL/v1/vat-returns/3fa85f64-5717-4562-b3fc-2c963f66afa6/payments/3fa85f64-5717-4562-b3fc-2c963f66afa6/unlink" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "reason": "Recorded on the wrong return"
}'

Responses

Status Meaning Body
200 OK VatReturnOut
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)

{
  "filing_status": "not_submitted",
  "submitted_on": "2026-09-21",
  "submission_reference": "string",
  "submitted_by": {},
  "submitted_at": "2026-09-21T09:30:00Z",
  "settled_amount": "string",
  "paid_amount": "string",
  "payment_difference": "string",
  "payments": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "journal_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "entry_number": "string",
      "paid_on": "2026-09-21",
      "amount": "string",
      "linked_by": {},
      "linked_at": "2026-09-21T09:30:00Z"
    }
  ],
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "entity": "string",
  "kind": "annual_summary",
  "reference": "string",
  "form_id": "string",
  "form_version": "string",
  "method": "string",
  "period": "string",
  "start": "2026-09-21",
  "end": "2026-09-21",
  "status": "string",
  "currency": "string",
  "payable": "string",
  "amends_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "settlement_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "settlement_entry_number": "string",
  "errors": 1,
  "warnings": 1,
  "computed_at": "2026-09-21T09:30:00Z",
  "finalized_at": "2026-09-21T09:30:00Z",
  "finalized_by": {},
  "result": {
    "kind": "annual_summary",
    "form": {
      "id": "string",
      "jurisdiction": "",
      "name": "string",
      "kind": "annual_summary",
      "method": null,
      "version": "string",
      "currency": "string",
      "base_precision": 1,
      "tax_precision": 2,
      "notes": [
        null
      ],
      "limitations": [
        null
      ],
      "sources": [
        null
      ]
    },
    "entity": "string",
    "entity_name": "string",
    "vat_number": "string",
    "tax_number": "string",
    "period": "string",
    "start": "2026-09-21",
    "end": "2026-09-21",
    "currency": "string",
    "method": "string",
    "boxes": [
      {
        "id": null,
        "code": null,
        "line": null,
        "label": null,
        "section": null,
        "unit": null,
        "rate": null,
        "amount": null,
        "tax": null,
        "computed": null,
        "lines": null,
        "adjustable": null,
        "adjusted": null,
        "filled": null,
        "xml": null,
        "by_rate": null
      }
    ],
    "rows": [
      {
        "country_code": null,
        "vat_id": null,
        "party": null,
        "box": null,
        "amount": null
      }
    ],
    "oss_rows": [
      {
        "member_state": null,
        "supply": null,
        "rate": null,
        "rate_type": null,
        "base": null,
        "vat": null
      }
    ],
    "oss_corrections": [
      {
        "period": null,
        "member_state": null,
        "vat": null
      }
    ],
    "activities": [
      {
        "activity_id": null,
        "series": null,
        "activity": null,
        "rate": null,
        "turnover": null,
        "tax": null
      }
    ],
    "payable": "string",
    "reconciliation": {
      "accounts": null,
      "ledger": null,
      "reported": null,
      "other_period": null,
      "payable": null,
      "adjustments": null,
      "computation_difference": null,
      "tax_fx_difference": null,
      "whole_unit_rounding": null,
      "unexplained": null,
      "settlement": null,
      "reconciling_items": null
    },
    "adjustments": [
      {
        "account": "1020",
        "amount": "120.00",
        "box": "410",
        "note": "Import VAT paid to customs"
      }
    ],
    "issues": [
      {
        "severity": null,
        "code": null,
        "message": null,
        "details": null
      }
    ],
    "lines": 1,
    "dataset_version": "string",
    "tax_fx": [
      {
        "series": null,
        "currency": null,
        "period": null,
        "rate": null,
        "quotation": null,
        "lines": null,
        "looked_up": null
      }
    ],
    "payment_code": "string",
    "payment_due_date": "2026-09-21"
  },
  "explanation": "string",
  "adjustments": [
    {
      "account": "1020",
      "amount": "120.00",
      "box": "410",
      "note": "Import VAT paid to customs"
    }
  ],
  "test_copy": false
}

POST /v1/vat-returns/{return_id}/recompute

Recompute a draft VAT return

Recomputes a draft from the current ledger, replacing its stored result and box lines. Send adjustments to replace the hand-entered amounts, or omit them to keep the current ones. Answers 409 unless the return is a draft and 422 for an adjustment on a box the ledger fills or computes, or one that changes the amount payable without an offset account.

Required scope draft (admin implies every scope)
Idempotency-Key required
Operation id recompute_v1_vat_returns__return_id__recompute_post

Parameters

In Name Type Required Description
path return_id string (uuid) yes VAT return id.

Request body

application/json (required): VatRecomputeInput

Field Type Required Description
adjustments array of VatAdjustment-Input or null Replaces the adjustments; omit to keep them.

Example request

curl -X POST "$ERP_URL/v1/vat-returns/3fa85f64-5717-4562-b3fc-2c963f66afa6/recompute" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "adjustments": [
    {
      "account": "1020",
      "amount": "120.00",
      "box": "410"
    }
  ]
}'

Responses

Status Meaning Body
200 OK VatReturnOut
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)

{
  "filing_status": "not_submitted",
  "submitted_on": "2026-09-21",
  "submission_reference": "string",
  "submitted_by": {},
  "submitted_at": "2026-09-21T09:30:00Z",
  "settled_amount": "string",
  "paid_amount": "string",
  "payment_difference": "string",
  "payments": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "journal_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "entry_number": "string",
      "paid_on": "2026-09-21",
      "amount": "string",
      "linked_by": {},
      "linked_at": "2026-09-21T09:30:00Z"
    }
  ],
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "entity": "string",
  "kind": "annual_summary",
  "reference": "string",
  "form_id": "string",
  "form_version": "string",
  "method": "string",
  "period": "string",
  "start": "2026-09-21",
  "end": "2026-09-21",
  "status": "string",
  "currency": "string",
  "payable": "string",
  "amends_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "settlement_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "settlement_entry_number": "string",
  "errors": 1,
  "warnings": 1,
  "computed_at": "2026-09-21T09:30:00Z",
  "finalized_at": "2026-09-21T09:30:00Z",
  "finalized_by": {},
  "result": {
    "kind": "annual_summary",
    "form": {
      "id": "string",
      "jurisdiction": "",
      "name": "string",
      "kind": "annual_summary",
      "method": null,
      "version": "string",
      "currency": "string",
      "base_precision": 1,
      "tax_precision": 2,
      "notes": [
        null
      ],
      "limitations": [
        null
      ],
      "sources": [
        null
      ]
    },
    "entity": "string",
    "entity_name": "string",
    "vat_number": "string",
    "tax_number": "string",
    "period": "string",
    "start": "2026-09-21",
    "end": "2026-09-21",
    "currency": "string",
    "method": "string",
    "boxes": [
      {
        "id": null,
        "code": null,
        "line": null,
        "label": null,
        "section": null,
        "unit": null,
        "rate": null,
        "amount": null,
        "tax": null,
        "computed": null,
        "lines": null,
        "adjustable": null,
        "adjusted": null,
        "filled": null,
        "xml": null,
        "by_rate": null
      }
    ],
    "rows": [
      {
        "country_code": null,
        "vat_id": null,
        "party": null,
        "box": null,
        "amount": null
      }
    ],
    "oss_rows": [
      {
        "member_state": null,
        "supply": null,
        "rate": null,
        "rate_type": null,
        "base": null,
        "vat": null
      }
    ],
    "oss_corrections": [
      {
        "period": null,
        "member_state": null,
        "vat": null
      }
    ],
    "activities": [
      {
        "activity_id": null,
        "series": null,
        "activity": null,
        "rate": null,
        "turnover": null,
        "tax": null
      }
    ],
    "payable": "string",
    "reconciliation": {
      "accounts": null,
      "ledger": null,
      "reported": null,
      "other_period": null,
      "payable": null,
      "adjustments": null,
      "computation_difference": null,
      "tax_fx_difference": null,
      "whole_unit_rounding": null,
      "unexplained": null,
      "settlement": null,
      "reconciling_items": null
    },
    "adjustments": [
      {
        "account": "1020",
        "amount": "120.00",
        "box": "410",
        "note": "Import VAT paid to customs"
      }
    ],
    "issues": [
      {
        "severity": null,
        "code": null,
        "message": null,
        "details": null
      }
    ],
    "lines": 1,
    "dataset_version": "string",
    "tax_fx": [
      {
        "series": null,
        "currency": null,
        "period": null,
        "rate": null,
        "quotation": null,
        "lines": null,
        "looked_up": null
      }
    ],
    "payment_code": "string",
    "payment_due_date": "2026-09-21"
  },
  "explanation": "string",
  "adjustments": [
    {
      "account": "1020",
      "amount": "120.00",
      "box": "410",
      "note": "Import VAT paid to customs"
    }
  ],
  "test_copy": false
}

POST /v1/vat-returns/{return_id}/submitted

Record that a VAT return was submitted

Records that a final return (or one being amended) was submitted to the tax administration (ESTV, Finanzamt, HMRC) on submitted_on, with the administration's reference if one was given, and who recorded it. Nothing is sent: the application files no return electronically, and in a test copy (test_copy) the record is local only. From then on the period counts as filed (due_status filed) and the reminders of its due date stop. Answers 409 unless the return is final or amending, or when a submission is already recorded (withdraw it first); 422 for a day in the future or before the period ends. A person's act: needs the approval policy action finalize_vat_return, which agents are always denied (403).

Required scope draft (admin implies every scope)
Idempotency-Key required
Operation id submitted_v1_vat_returns__return_id__submitted_post

Parameters

In Name Type Required Description
path return_id string (uuid) yes VAT return id.

Request body

application/json (required): VatSubmitInput

Field Type Required Description
submitted_on string (date) yes The day the return was submitted to the tax administration: not before the period ends and not in the future.
submission_reference string or null The tax administration's reference or confirmation number. Optional. (max length 200)

Example request

curl -X POST "$ERP_URL/v1/vat-returns/3fa85f64-5717-4562-b3fc-2c963f66afa6/submitted" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "submission_reference": "MWST-2026-123",
  "submitted_on": "2026-10-20"
}'

Responses

Status Meaning Body
200 OK VatReturnOut
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)

{
  "filing_status": "not_submitted",
  "submitted_on": "2026-09-21",
  "submission_reference": "string",
  "submitted_by": {},
  "submitted_at": "2026-09-21T09:30:00Z",
  "settled_amount": "string",
  "paid_amount": "string",
  "payment_difference": "string",
  "payments": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "journal_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "entry_number": "string",
      "paid_on": "2026-09-21",
      "amount": "string",
      "linked_by": {},
      "linked_at": "2026-09-21T09:30:00Z"
    }
  ],
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "entity": "string",
  "kind": "annual_summary",
  "reference": "string",
  "form_id": "string",
  "form_version": "string",
  "method": "string",
  "period": "string",
  "start": "2026-09-21",
  "end": "2026-09-21",
  "status": "string",
  "currency": "string",
  "payable": "string",
  "amends_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "settlement_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "settlement_entry_number": "string",
  "errors": 1,
  "warnings": 1,
  "computed_at": "2026-09-21T09:30:00Z",
  "finalized_at": "2026-09-21T09:30:00Z",
  "finalized_by": {},
  "result": {
    "kind": "annual_summary",
    "form": {
      "id": "string",
      "jurisdiction": "",
      "name": "string",
      "kind": "annual_summary",
      "method": null,
      "version": "string",
      "currency": "string",
      "base_precision": 1,
      "tax_precision": 2,
      "notes": [
        null
      ],
      "limitations": [
        null
      ],
      "sources": [
        null
      ]
    },
    "entity": "string",
    "entity_name": "string",
    "vat_number": "string",
    "tax_number": "string",
    "period": "string",
    "start": "2026-09-21",
    "end": "2026-09-21",
    "currency": "string",
    "method": "string",
    "boxes": [
      {
        "id": null,
        "code": null,
        "line": null,
        "label": null,
        "section": null,
        "unit": null,
        "rate": null,
        "amount": null,
        "tax": null,
        "computed": null,
        "lines": null,
        "adjustable": null,
        "adjusted": null,
        "filled": null,
        "xml": null,
        "by_rate": null
      }
    ],
    "rows": [
      {
        "country_code": null,
        "vat_id": null,
        "party": null,
        "box": null,
        "amount": null
      }
    ],
    "oss_rows": [
      {
        "member_state": null,
        "supply": null,
        "rate": null,
        "rate_type": null,
        "base": null,
        "vat": null
      }
    ],
    "oss_corrections": [
      {
        "period": null,
        "member_state": null,
        "vat": null
      }
    ],
    "activities": [
      {
        "activity_id": null,
        "series": null,
        "activity": null,
        "rate": null,
        "turnover": null,
        "tax": null
      }
    ],
    "payable": "string",
    "reconciliation": {
      "accounts": null,
      "ledger": null,
      "reported": null,
      "other_period": null,
      "payable": null,
      "adjustments": null,
      "computation_difference": null,
      "tax_fx_difference": null,
      "whole_unit_rounding": null,
      "unexplained": null,
      "settlement": null,
      "reconciling_items": null
    },
    "adjustments": [
      {
        "account": "1020",
        "amount": "120.00",
        "box": "410",
        "note": "Import VAT paid to customs"
      }
    ],
    "issues": [
      {
        "severity": null,
        "code": null,
        "message": null,
        "details": null
      }
    ],
    "lines": 1,
    "dataset_version": "string",
    "tax_fx": [
      {
        "series": null,
        "currency": null,
        "period": null,
        "rate": null,
        "quotation": null,
        "lines": null,
        "looked_up": null
      }
    ],
    "payment_code": "string",
    "payment_due_date": "2026-09-21"
  },
  "explanation": "string",
  "adjustments": [
    {
      "account": "1020",
      "amount": "120.00",
      "box": "410",
      "note": "Import VAT paid to customs"
    }
  ],
  "test_copy": false
}

POST /v1/vat-returns/{return_id}/submitted/withdraw

Withdraw the recorded submission of a VAT return

Withdraws a submission recorded by mistake, with the reason (kept in the history; the record is not deleted). The period is not filed any more until a submission is recorded again. Answers 409 when no submission is recorded or payments are linked (unlink them first). A person's act: needs the approval policy action finalize_vat_return, which agents are always denied (403).

Required scope draft (admin implies every scope)
Idempotency-Key required
Operation id withdraw_submitted_v1_vat_returns__return_id__submitted_withdraw_post

Parameters

In Name Type Required Description
path return_id string (uuid) yes VAT return id.

Request body

application/json (required): VatReasonInput

Field Type Required Description
reason string yes Why, in a few words; kept in the history. (min length 1; max length 500)

Example request

curl -X POST "$ERP_URL/v1/vat-returns/3fa85f64-5717-4562-b3fc-2c963f66afa6/submitted/withdraw" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "reason": "Recorded on the wrong return"
}'

Responses

Status Meaning Body
200 OK VatReturnOut
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)

{
  "filing_status": "not_submitted",
  "submitted_on": "2026-09-21",
  "submission_reference": "string",
  "submitted_by": {},
  "submitted_at": "2026-09-21T09:30:00Z",
  "settled_amount": "string",
  "paid_amount": "string",
  "payment_difference": "string",
  "payments": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "journal_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "entry_number": "string",
      "paid_on": "2026-09-21",
      "amount": "string",
      "linked_by": {},
      "linked_at": "2026-09-21T09:30:00Z"
    }
  ],
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "entity": "string",
  "kind": "annual_summary",
  "reference": "string",
  "form_id": "string",
  "form_version": "string",
  "method": "string",
  "period": "string",
  "start": "2026-09-21",
  "end": "2026-09-21",
  "status": "string",
  "currency": "string",
  "payable": "string",
  "amends_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "settlement_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "settlement_entry_number": "string",
  "errors": 1,
  "warnings": 1,
  "computed_at": "2026-09-21T09:30:00Z",
  "finalized_at": "2026-09-21T09:30:00Z",
  "finalized_by": {},
  "result": {
    "kind": "annual_summary",
    "form": {
      "id": "string",
      "jurisdiction": "",
      "name": "string",
      "kind": "annual_summary",
      "method": null,
      "version": "string",
      "currency": "string",
      "base_precision": 1,
      "tax_precision": 2,
      "notes": [
        null
      ],
      "limitations": [
        null
      ],
      "sources": [
        null
      ]
    },
    "entity": "string",
    "entity_name": "string",
    "vat_number": "string",
    "tax_number": "string",
    "period": "string",
    "start": "2026-09-21",
    "end": "2026-09-21",
    "currency": "string",
    "method": "string",
    "boxes": [
      {
        "id": null,
        "code": null,
        "line": null,
        "label": null,
        "section": null,
        "unit": null,
        "rate": null,
        "amount": null,
        "tax": null,
        "computed": null,
        "lines": null,
        "adjustable": null,
        "adjusted": null,
        "filled": null,
        "xml": null,
        "by_rate": null
      }
    ],
    "rows": [
      {
        "country_code": null,
        "vat_id": null,
        "party": null,
        "box": null,
        "amount": null
      }
    ],
    "oss_rows": [
      {
        "member_state": null,
        "supply": null,
        "rate": null,
        "rate_type": null,
        "base": null,
        "vat": null
      }
    ],
    "oss_corrections": [
      {
        "period": null,
        "member_state": null,
        "vat": null
      }
    ],
    "activities": [
      {
        "activity_id": null,
        "series": null,
        "activity": null,
        "rate": null,
        "turnover": null,
        "tax": null
      }
    ],
    "payable": "string",
    "reconciliation": {
      "accounts": null,
      "ledger": null,
      "reported": null,
      "other_period": null,
      "payable": null,
      "adjustments": null,
      "computation_difference": null,
      "tax_fx_difference": null,
      "whole_unit_rounding": null,
      "unexplained": null,
      "settlement": null,
      "reconciling_items": null
    },
    "adjustments": [
      {
        "account": "1020",
        "amount": "120.00",
        "box": "410",
        "note": "Import VAT paid to customs"
      }
    ],
    "issues": [
      {
        "severity": null,
        "code": null,
        "message": null,
        "details": null
      }
    ],
    "lines": 1,
    "dataset_version": "string",
    "tax_fx": [
      {
        "series": null,
        "currency": null,
        "period": null,
        "rate": null,
        "quotation": null,
        "lines": null,
        "looked_up": null
      }
    ],
    "payment_code": "string",
    "payment_due_date": "2026-09-21"
  },
  "explanation": "string",
  "adjustments": [
    {
      "account": "1020",
      "amount": "120.00",
      "box": "410",
      "note": "Import VAT paid to customs"
    }
  ],
  "test_copy": false
}

Schemas

VatAccountReconciliation

Field Type Required Description
account string yes VAT account code.
name string yes Account name.
role string or null yes Account role: vat_output, vat_reverse_charge or vat_input.
ledger string yes Posted movement in the period, credit minus debit, without settlement entries.
reported string yes What the return takes of it, as on the return: foreign-currency VAT at the official VAT exchange rate. ledger = reported - tax_fx_difference + other_period + unmapped + untagged.
tax_fx_difference string What the official VAT exchange rates add to the VAT booked on this account (the return at the official rate less the ledger at the booking rate). The differences of the output and input tax accounts can cancel in the amount payable (acquisition tax) while each box differs from its account. (default "0.00")
other_period string VAT booked in this period whose tax point is in another period, less VAT of this period's tax points booked in another period: the date of supply moved it (goods delivered in September and invoiced in October are on the September return, in the October ledger), or the cash basis (an invoice booked in September is on the return of the period it is paid in, pro rata). Explained, not part of unexplained. (default "0.00")
unmapped string yes Tax-tagged amount that no box takes.
untagged string yes Movement without a tax code (for example manual postings).

VatActivity

Net tax rate method: turnover (gross) and tax per approved activity.

Field Type Required Description
activity_id string yes The ESTV's five-character activity code.
series string yes Net tax rate series.
activity string yes Name of the activity.
rate string yes Net tax rate in percent.
turnover string yes Gross turnover of the activity.
tax string yes Tax at the net tax rate.

VatAdjustment-Input

An amount entered by hand for a box the ledger does not fill (e.g. import VAT).

Field Type Required Description
box string yes Id of the box to adjust, as in the return's boxes[].id (a Ziffer such as 410 or a Kennzahl). Only boxes that the ledger neither fills nor computes can be adjusted (adjustable is true); others are refused (422).
amount decimal string yes Amount to add to the box, as a decimal string in the entity's functional currency, e.g. "120.00". Negative reduces the box.
account string or null Offset account in the settlement; required for boxes that change the amount payable (e.g. import VAT paid to customs).
note string or null Free text explaining the adjustment. Optional.
automatic boolean Filled in by the return itself (CA: the Quick Method 1% credit, instalments paid; ES: amounts carried forward, the Modelo 390 from the 303s); replaced on every recompute, so only adjustments entered by hand are kept. (default false)

VatAdjustment-Output

An amount entered by hand for a box the ledger does not fill (e.g. import VAT).

Field Type Required Description
box string yes Id of the box to adjust, as in the return's boxes[].id (a Ziffer such as 410 or a Kennzahl). Only boxes that the ledger neither fills nor computes can be adjusted (adjustable is true); others are refused (422).
amount string yes Amount to add to the box, as a decimal string in the entity's functional currency, e.g. "120.00". Negative reduces the box. (pattern ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$)
account string or null Offset account in the settlement; required for boxes that change the amount payable (e.g. import VAT paid to customs).
note string or null Free text explaining the adjustment. Optional.
automatic boolean Filled in by the return itself (CA: the Quick Method 1% credit, instalments paid; ES: amounts carried forward, the Modelo 390 from the 303s); replaced on every recompute, so only adjustments entered by hand are kept. (default false)

VatBox

Field Type Required Description
id string yes Box id, as used in adjustments[].box and .../boxes/{box}/lines, e.g. 303 or kz81.
code string or null yes The number printed on the form (Ziffer, Kennzahl); null if unnumbered.
line string or null yes Line number on the form, if any.
label string yes The official wording, abridged.
section string or null yes Section of the form the box is in.
unit string yes base (turnover or taxable amount), tax or amount.
rate string or null yes The rate printed next to the box, in percent.
amount string yes The box's amount in the return's currency, as a decimal string.
tax string or null yes For boxes that compute tax, the tax on the amount; else null.
computed boolean yes True when the form derives the box from other boxes.
lines integer yes Number of journal lines that fill the box (drill down with .../boxes/{box}/lines).
adjustable boolean yes True when the box can take a hand-entered adjustment.
adjusted boolean True when an adjustment is part of the amount. (default false)
filled boolean True when the amount comes from the company's earlier returns rather than from the ledger (Italy: the previous period's credit or carried debt, the interest on quarterly payments, the year's periodic VAT on the annual return). (default false)
xml string or null Element of the eCH-0217 file the box is written to, if any.
by_rate array of VatRatePart Boxes that compute tax: amount and tax per rate.

VatBoxLine

Field Type Required Description
journal_line_id string (uuid) yes Id of the journal line that fills the box.
entry_id string (uuid) yes Id of its journal entry (GET /v1/journal-entries/{id}).
entry_number string or null yes Number of the journal entry.
entry_date string (date) yes Posting date of the entry (ISO 8601 date).
account string yes Account code of the line.
account_name string yes Account name.
description string or null yes The line's description.
document string or null yes For receivable and payable postings, the document number.
counterparty string or null yes Name of the customer or vendor on the line.
row_key string or null yes Recapitulative statement: the customer VAT number (country code and id) the line belongs to.
rule string or null yes Id of the form rule that routed the line into the box.
amount string yes The line's contribution to the box in the return's currency, as a decimal string.

VatFinalizeInput

Field Type Required Description
posting_date string (date) or null Date of the settlement entry; default the period's last day, or the first open day after it.
explanation string or null Required when the VAT accounts hold amounts the return does not explain. (max length 2000)

VatFinalizeOut

Field Type Required Description
vat_return VatReturnOut yes The return after the call: final, or pending_approval when the settlement entry needs a second person.
settlement SubmitResult or null yes The settlement entry's submission: its id, status, number, the policy decision (allow, require_approval, deny) and the approval id when one was requested. Null when nothing needed settling.

VatForm

Field Type Required Description
id string yes Form id, e.g. ch.estv.mwst.effective or de.bmf.ustva.2026.
jurisdiction string Country the form is filed in, e.g. IT. (default "")
name string yes Official name of the form.
kind "annual_summary" | "oss_return" | "pst_return_bc" | "pst_return_sk" | "qst_return" | "recapitulative_statement" | "rst_return_mb" | "vat_return" yes vat_return, recapitulative_statement (ZM, Modelo 349), qst_return (Quebec), pst_return_bc, pst_return_sk, rst_return_mb, annual_summary (Modelo 390, Dichiarazione IVA) or oss_return (EU One-Stop Shop, union scheme).
method string or null yes Filing method the form is for, or null.
version string yes Edition of the form or file format it follows.
currency string yes Currency the form is filed in; the entity must book in it.
base_precision integer yes Decimals of base amounts: 0 means whole units.
tax_precision integer Decimals of tax amounts and totals: 0 means whole units (FR, IT). (default 2)
notes array of string yes How the form computes and rounds.
limitations array of string yes What the form does not derive from the ledger (enter it as adjustments).
sources array of object yes Legal and technical sources of the form.

VatIssue

Field Type Required Description
severity "error" | "info" | "warning" yes error (blocks finalising), warning (review it) or info.
code string yes Stable code (erp.contracts.words.VAT_ISSUES lists them all), e.g. unmapped_line, unexplained_difference, computation_difference (with computation_difference_fx when official VAT exchange rates add to it), tax_fx_not_published, missing_uid, missing_account, missing_settlement_account, period_differs_from_settings, earlier_period_unfiled (an earlier period has no final return yet: filing this one is allowed), annual_differs (vs. the final returns).
message string yes What was found, in English.
details map of string The values the message names, for the screens to word it, e.g. {"periods": "2026-Q1, 2026-Q2"} for earlier_period_unfiled.

VatOssCorrection

A correction in a One-Stop Shop return of the VAT declared for an earlier quarter.

Field Type Required Description
period string yes The quarter corrected (YYYY-Qn).
member_state string yes Member state of consumption (ISO 3166-1 alpha-2).
vat string yes Change of the VAT of that quarter in euros (negative: less).

VatOssRow

A row of the One-Stop Shop return: one member state of consumption, kind of supply and VAT rate.

Field Type Required Description
member_state string yes Member state of consumption (ISO 3166-1 alpha-2).
supply "goods" | "services" yes goods or services.
rate string yes VAT rate of that member state in percent.
rate_type string or null yes standard, reduced, ... or null.
base string yes Taxable amount in euros.
vat string yes VAT due in that member state in euros.

VatPaymentCandidate

Field Type Required Description
journal_entry_id string (uuid) yes Id of the posted entry.
entry_number string or null yes Its number.
entry_date string (date) yes Its date (ISO 8601 date).
description string yes Its description.
source string yes Its source, such as bank or manual.
amount string yes What it puts on the settlement account against the settlement, as a positive decimal string.

VatPaymentInput

Field Type Required Description
journal_entry_id string (uuid) yes The posted entry that paid the VAT (or received the refund): of the return's company, dated on or after the settlement, with a line on the settlement account on the side opposite the settlement (GET .../payment-candidates).

VatPaymentOut

Field Type Required Description
id string (uuid) yes Id of the link (the {payment_id} to unlink it).
journal_entry_id string (uuid) yes Id of the posted entry that paid.
entry_number string or null yes Number of that entry.
paid_on string (date) yes The entry's date: the day it paid (ISO 8601 date).
amount string yes What the entry put on the settlement account against the settlement, as a positive decimal string: VAT paid, or for a refund the refund received.
linked_by object yes Who linked it (type and id).
linked_at string (date-time) yes When it was linked (ISO 8601 timestamp, UTC).

VatPeriod

Field Type Required Description
filing_status "not_submitted" | "paid" | "submitted" yes not_submitted (not final yet, or final but not recorded as submitted), submitted (a person recorded the submission; a return with nothing to pay or refund stays here) or paid (submitted, and the linked payments cover the settled amount).
submitted_on string (date) or null yes The day the return was submitted to the tax administration, as a person recorded it (ISO 8601 date); null when not submitted.
submission_reference string or null yes The tax administration's reference or confirmation number, or null.
submitted_by object or null yes Who recorded the submission (type and id); null when not submitted.
submitted_at string (date-time) or null yes When the submission was recorded (ISO 8601 timestamp, UTC), or null.
settled_amount string or null yes What the posted settlement put on the settlement account: positive is VAT to pay, negative a refund to receive (a correction: only its difference). Null when nothing was settled (not final yet, nothing to pay, a recapitulative statement).
paid_amount string yes What the linked payments cover, signed like settled_amount.
payment_difference string or null yes settled_amount minus paid_amount: what is still to pay (or receive); negative when more was paid. Null when nothing was settled.
payments array of VatPaymentOut yes The posted entries linked as paying the return, oldest first.
period string yes Period label: 2026-Q3, 2026-08, 2026-H2 or 2026.
start string (date) yes First day of the period (ISO 8601 date).
end string (date) yes Last day of the period (ISO 8601 date).
kind "annual_summary" | "oss_return" | "pst_return_bc" | "pst_return_sk" | "qst_return" | "recapitulative_statement" | "rst_return_mb" | "vat_return" yes vat_return, recapitulative_statement (ZM, Modelo 349), qst_return (Quebec), pst_return_bc, pst_return_sk, rst_return_mb, annual_summary (Modelo 390, Dichiarazione IVA) or oss_return (EU One-Stop Shop, union scheme).
return_id string (uuid) or null yes Id of the period's live return, or null when there is none.
reference string or null yes Reference of that return, or null.
status string yes The return's status (draft, pending_approval, final, amending) or open when the period has no live return.
payable string or null yes The return's amount payable as a decimal string, or null.
due_date string (date) or null When the return is due to be filed and paid (ISO 8601 date), by the country's rule (CH: 60 days after the period; DE: the 10th of the next month, a month later with the permanent extension, a recapitulative statement on the 25th day, moved to the Monday when it falls on a weekend; GB: one month and seven days, two months after the year under the Annual Accounting Scheme); null when no rule is known for the country or period.
payment_due_date string (date) or null When the period's VAT is due to be paid (ISO 8601 date): the due_date, except in Italy, where it is paid before the return is filed (the 16th of the next month; quarterly 16 May, 20 August, 16 November and, with the annual balance, 16 March); null when nothing is paid on the return (an annual return) or no rule is known.
due_status "due_soon" | "filed" | "overdue" | "unknown" | "upcoming" filed (a return of the period was recorded as submitted to the tax administration; final alone is not filed), upcoming, due_soon (due within 14 days), overdue (past the due date and not filed) or unknown (no due date known). (default "unknown")
payment_overdue boolean true when the due date has passed and the live return's VAT to pay is not covered by linked payments (shown as a warning; due_status follows the filing only). (default false)

VatRatePart

Field Type Required Description
rate string yes Tax rate in percent.
amount string yes Turnover at that rate.
tax string yes Tax on that turnover.

VatReasonInput

Field Type Required Description
reason string yes Why, in a few words; kept in the history. (min length 1; max length 500)

VatRecomputeInput

Field Type Required Description
adjustments array of VatAdjustment-Input or null Replaces the adjustments; omit to keep them.

VatReconciliation

Movements on the VAT accounts (credit minus debit) against the return.

Field Type Required Description
accounts array of VatAccountReconciliation yes Per VAT account: ledger movement and what the return took.
ledger string yes Total ledger movement of the VAT accounts, credit minus debit.
reported string yes Total of the VAT booked that the return reports (at the booking rate: the per-account reported less its tax_fx_difference), which the settlement clears.
other_period string Total of the accounts' other_period. VAT booked in this period whose tax point is in another period, less VAT of this period's tax points booked in another period: the date of supply moved it (goods delivered in September and invoiced in October are on the September return, in the October ledger), or the cash basis (an invoice booked in September is on the return of the period it is paid in, pro rata). Explained, not part of unexplained. (default "0.00")
payable string yes The return's amount payable.
adjustments string yes Effect of the hand-entered adjustments on the amount payable.
computation_difference string yes Amount payable minus adjustments minus reported: the form computes tax from the turnover while the ledger holds each document's VAT (under the net tax rate method, the net tax rate difference). The settlement clears it to the account with the role rounding or vat_net_rate_difference.
tax_fx_difference string Part of the computational difference from foreign-currency VAT: the return takes it at the official VAT exchange rate, the ledger at the booking rate. (default "0.00")
whole_unit_rounding string Part of the computational difference from declaring amounts in whole currency units: the amount payable minus the same return computed to the cent. Germany's UStVA drops the cents of each base and computes the tax from it; France's CA3 and Italy's Dichiarazione IVA round every amount to the euro. Zero for a form in cents (Switzerland, Spain, Canada, the Italian LIPE). (default "0.00")
unexplained string yes Unmapped plus untagged amounts. Finalising needs it to be zero or an explanation.
settlement array of map of string Implied settlement lines: account, signed debit.
reconciling_items array of ReconcilingItem Revenue and expenses in the ledger that no turnover box of the return contains because the lines are outside the scope of VAT (a labelled reconciling item between ledger revenue and the VAT turnover). Empty when there are none.

VatReturnInput

Field Type Required Description
entity string yes Entity code, e.g. CH01 or DE01 (GET /v1/entities).
kind "annual_summary" | "oss_return" | "pst_return_bc" | "pst_return_sk" | "qst_return" | "recapitulative_statement" | "rst_return_mb" | "vat_return" vat_return, recapitulative_statement (ZM, Modelo 349), qst_return (Quebec), pst_return_bc, pst_return_sk, rst_return_mb, annual_summary (Modelo 390, Dichiarazione IVA) or oss_return (EU One-Stop Shop, union scheme). Default vat_return; annual_summary takes the period YYYY. (default "vat_return")
period string yes '2026-08', '2026-Q3', '2026-H2' or '2026'.
adjustments array of VatAdjustment-Input Hand-entered amounts for boxes the ledger cannot fill (import VAT, Einlageentsteuerung and similar). Default: none.

VatReturnOut

Field Type Required Description
filing_status "not_submitted" | "paid" | "submitted" yes not_submitted (not final yet, or final but not recorded as submitted), submitted (a person recorded the submission; a return with nothing to pay or refund stays here) or paid (submitted, and the linked payments cover the settled amount).
submitted_on string (date) or null yes The day the return was submitted to the tax administration, as a person recorded it (ISO 8601 date); null when not submitted.
submission_reference string or null yes The tax administration's reference or confirmation number, or null.
submitted_by object or null yes Who recorded the submission (type and id); null when not submitted.
submitted_at string (date-time) or null yes When the submission was recorded (ISO 8601 timestamp, UTC), or null.
settled_amount string or null yes What the posted settlement put on the settlement account: positive is VAT to pay, negative a refund to receive (a correction: only its difference). Null when nothing was settled (not final yet, nothing to pay, a recapitulative statement).
paid_amount string yes What the linked payments cover, signed like settled_amount.
payment_difference string or null yes settled_amount minus paid_amount: what is still to pay (or receive); negative when more was paid. Null when nothing was settled.
payments array of VatPaymentOut yes The posted entries linked as paying the return, oldest first.
id string (uuid) yes Return id (uuid); the {return_id} of the other operations.
entity string yes Code of the entity the return is for.
kind "annual_summary" | "oss_return" | "pst_return_bc" | "pst_return_sk" | "qst_return" | "recapitulative_statement" | "rst_return_mb" | "vat_return" yes vat_return, recapitulative_statement (ZM, Modelo 349), qst_return (Quebec), pst_return_bc, pst_return_sk, rst_return_mb, annual_summary (Modelo 390, Dichiarazione IVA) or oss_return (EU One-Stop Shop, union scheme).
reference string yes Human-readable reference, e.g. CH01-VAT-2026-Q3; a correction appends /n.
form_id string yes Id of the official form the return was computed with, e.g. ch.estv.mwst.effective.
form_version string yes Version of that form (the ESTV or BMF edition it follows).
method string or null yes Filing method of the form (effective, net_tax_rate) or null.
period string yes Period label: 2026-08, 2026-Q3, 2026-H2 or 2026.
start string (date) yes First day of the period (ISO 8601 date).
end string (date) yes Last day of the period (ISO 8601 date).
status string yes draft (computed, can be recomputed, discarded or finalised), pending_approval (the settlement entry waits for a second person), final (settled, the period's VAT postings are locked), amending (a final return whose correction is open), superseded (replaced by a final correction) or discarded.
currency string yes Currency of the return and its amounts: the entity's functional currency.
payable string or null yes Amount payable to the tax authority as a decimal string; negative is a refund (credit). Null for a recapitulative statement.
amends_id string (uuid) or null yes For a correction, the id of the final return it corrects; else null.
settlement_entry_id string (uuid) or null yes Id of the settlement journal entry, once finalising created it; else null.
settlement_entry_number string or null yes Number of the settlement entry once it is posted; else null.
errors integer yes Number of issues with severity error; a return with errors cannot be finalised.
warnings integer yes Number of issues with severity warning.
computed_at string (date-time) yes When the return was last computed (ISO 8601 timestamp, UTC).
finalized_at string (date-time) or null yes When the return became final (ISO 8601 timestamp, UTC); null before.
finalized_by object or null yes The actor that finalised it, as stored in the audit trail (type and id); null before.
result VatReturnResult yes The computed return: form, boxes, rows, reconciliation, issues.
explanation string or null yes The explanation given when finalising, or null.
adjustments array of VatAdjustment-Output yes The hand-entered adjustments the return was computed with.
test_copy boolean true in a test copy (POST /v1/test-copies): recording a submission there is a local record only, and nothing is ever filed with a tax administration. (default false)

VatReturnResult

Field Type Required Description
kind "annual_summary" | "oss_return" | "pst_return_bc" | "pst_return_sk" | "qst_return" | "recapitulative_statement" | "rst_return_mb" | "vat_return" yes vat_return, recapitulative_statement (ZM, Modelo 349), qst_return (Quebec), pst_return_bc, pst_return_sk, rst_return_mb, annual_summary (Modelo 390, Dichiarazione IVA) or oss_return (EU One-Stop Shop, union scheme).
form VatForm yes The official form the return follows.
entity string yes Entity code.
entity_name string yes Entity name.
vat_number string or null yes The entity's VAT number (Switzerland: UID).
tax_number string or null yes Germany: the Steuernummer from the VAT settings.
period string yes Period label, e.g. 2026-Q3.
start string (date) yes First day of the period (ISO 8601 date).
end string (date) yes Last day of the period (ISO 8601 date).
currency string yes Currency of all amounts: the entity's functional currency.
method string or null yes Filing method of the form, or null.
boxes array of VatBox yes Every box of the form with its amount, in form order.
rows array of VatStatementRow Recapitulative statement: one row per customer VAT number and kind of supply. Empty for a VAT return.
oss_rows array of VatOssRow One-Stop Shop return: taxable amount and VAT per member state of consumption, kind of supply and rate. Empty for other returns.
oss_corrections array of VatOssCorrection One-Stop Shop return: corrections of earlier quarters (credit notes of sales of those quarters), per quarter and member state, apart from the quarter's supplies (Directive 2006/112/EC art. 369g(4)); they count in the VAT payable.
activities array of VatActivity Net tax rate method: turnover and tax per approved activity.
payable string or null yes Amount payable as a decimal string; negative is a credit. Null for a recapitulative statement.
reconciliation VatReconciliation or null yes The VAT accounts against the return; null for a recapitulative statement.
adjustments array of VatAdjustment-Output yes The hand-entered adjustments that were applied.
issues array of VatIssue yes Findings of the computation. A return with an error issue cannot be finalised.
lines integer yes Number of distinct journal lines the return draws on.
dataset_version string yes Version of the reference data (forms, rates) used.
tax_fx array of VatTaxFxRate Official VAT exchange rates of the foreign-currency lines (CH: ESTV/BAZG, DE: BMF).
payment_code string or null Italy: the F24 tax code (codice tributo) the amount payable is paid with: 6001 to 6012 for a month, 6031 to 6033 for a quarter, 6099 for the fourth quarter paid with the annual balance; null elsewhere or when nothing is to pay.
payment_due_date string (date) or null Italy: the day the payment_code payment is due (ISO 8601 date), before the return is filed; null when there is no payment code.

VatReturnSummary

Field Type Required Description
filing_status "not_submitted" | "paid" | "submitted" yes not_submitted (not final yet, or final but not recorded as submitted), submitted (a person recorded the submission; a return with nothing to pay or refund stays here) or paid (submitted, and the linked payments cover the settled amount).
submitted_on string (date) or null yes The day the return was submitted to the tax administration, as a person recorded it (ISO 8601 date); null when not submitted.
submission_reference string or null yes The tax administration's reference or confirmation number, or null.
submitted_by object or null yes Who recorded the submission (type and id); null when not submitted.
submitted_at string (date-time) or null yes When the submission was recorded (ISO 8601 timestamp, UTC), or null.
settled_amount string or null yes What the posted settlement put on the settlement account: positive is VAT to pay, negative a refund to receive (a correction: only its difference). Null when nothing was settled (not final yet, nothing to pay, a recapitulative statement).
paid_amount string yes What the linked payments cover, signed like settled_amount.
payment_difference string or null yes settled_amount minus paid_amount: what is still to pay (or receive); negative when more was paid. Null when nothing was settled.
payments array of VatPaymentOut yes The posted entries linked as paying the return, oldest first.
id string (uuid) yes Return id (uuid); the {return_id} of the other operations.
entity string yes Code of the entity the return is for.
kind "annual_summary" | "oss_return" | "pst_return_bc" | "pst_return_sk" | "qst_return" | "recapitulative_statement" | "rst_return_mb" | "vat_return" yes vat_return, recapitulative_statement (ZM, Modelo 349), qst_return (Quebec), pst_return_bc, pst_return_sk, rst_return_mb, annual_summary (Modelo 390, Dichiarazione IVA) or oss_return (EU One-Stop Shop, union scheme).
reference string yes Human-readable reference, e.g. CH01-VAT-2026-Q3; a correction appends /n.
form_id string yes Id of the official form the return was computed with, e.g. ch.estv.mwst.effective.
form_version string yes Version of that form (the ESTV or BMF edition it follows).
method string or null yes Filing method of the form (effective, net_tax_rate) or null.
period string yes Period label: 2026-08, 2026-Q3, 2026-H2 or 2026.
start string (date) yes First day of the period (ISO 8601 date).
end string (date) yes Last day of the period (ISO 8601 date).
status string yes draft (computed, can be recomputed, discarded or finalised), pending_approval (the settlement entry waits for a second person), final (settled, the period's VAT postings are locked), amending (a final return whose correction is open), superseded (replaced by a final correction) or discarded.
currency string yes Currency of the return and its amounts: the entity's functional currency.
payable string or null yes Amount payable to the tax authority as a decimal string; negative is a refund (credit). Null for a recapitulative statement.
amends_id string (uuid) or null yes For a correction, the id of the final return it corrects; else null.
settlement_entry_id string (uuid) or null yes Id of the settlement journal entry, once finalising created it; else null.
settlement_entry_number string or null yes Number of the settlement entry once it is posted; else null.
errors integer yes Number of issues with severity error; a return with errors cannot be finalised.
warnings integer yes Number of issues with severity warning.
computed_at string (date-time) yes When the return was last computed (ISO 8601 timestamp, UTC).
finalized_at string (date-time) or null yes When the return became final (ISO 8601 timestamp, UTC); null before.
finalized_by object or null yes The actor that finalised it, as stored in the audit trail (type and id); null before.

VatSettingsOut

Field Type Required Description
entity string yes Entity code.
country string yes Entity country (ISO 3166-1 alpha-2); decides which methods and forms apply.
vat_number string or null yes The entity's VAT number (Switzerland: the UID, CHE-123.456.788 MWST, which the eCH-0217 file needs).
subdivision string or null The entity's state or province (CA-QC).
configured boolean yes False until the settings are saved: defaults apply.
registered_from string (date) or null The day the VAT registration takes effect: no return is due for a period that ends before it. Null: registered since the books start.
method "effective" | "net_tax_rate" | "quick" | "standard" yes effective, net_tax_rate (Switzerland), quick (Canada) or standard.
period "half_year" | "month" | "quarter" | "two_months" | "year" yes Return period: month, two_months (the Norwegian termin), quarter, half_year or year.
basis "cash" | "invoice" When VAT is due: invoice (with the invoice, or the date of supply where the law says so) or cash (when paid: the part of a document a payment, credit note or cash discount settles is reported in the period of the settlement, pro rata). (default "invoice")
cash_basis_law string or null The law that allows the cash basis in the entity's country (CH, DE, FR, GB, ES, IT); null where it is not offered.
cash_basis_condition string or null The law's condition to use the cash basis (a turnover limit, an application), in the law's language; the company checks it, the ERP does not.
cash_basis_purchases boolean Under the cash basis input VAT is reclaimed when the bill is paid too (CH, GB, ES, IT); false: it stays with the bill (DE § 15 UStG, FR; in France the VAT on services bought from a French supplier is deducted when paid on either basis, CGI art. 271). (default false)
cash_basis_open integer How many posted documents on the cash basis are not settled in full: their VAT is reported when they are, whatever the basis is changed to (a change of basis settles nothing; the law may ask for the outstanding VAT to be accounted for on leaving the cash basis, e.g. UK VAT Regulations 1995 reg. 64, which is booked by hand). French services bills, deducted when paid on either basis, do not count. (default 0)
recapitulative_period "month" | "quarter" or null yes Period of the recapitulative statement (ZM, 349): month, quarter or null.
tax_number string or null yes Germany: the Steuernummer, or null.
net_tax_rates array of VatNetTaxRate yes The approved net tax rates (net tax rate method), else empty.
settlement_account string or null yes Code of the settlement account named in the settings; null means the account with the role vat_settlement is used.
tax_fx "daily" | "ecb_daily" | "monthly" or null Method for official VAT exchange rates (None: not applicable).
tax_fx_booking boolean True when foreign-currency documents are booked at the official VAT rate. (default false)
filing_extension boolean DE: true when the tax office granted the permanent extension (Dauerfristverlängerung): each advance return is due one month later. (default false)
registrations array of string CA: the provinces besides its own whose sales tax (QST, PST, RST) the entity collects, e.g. CA-QC (which adds the QST return).
provincial_periods map of "half_year" | "month" | "quarter" | "two_months" | "year" CA: the filing period of each province's sales tax return where it differs from period, e.g. {"CA-BC": "month"}.
quick_method "resale" | "services" or null CA, method quick: the remittance rate of a business buying goods for resale (resale) or of a service provider (services); else null.
oss_available boolean The company is established in the EU, so it can register for the One-Stop Shop (oss, oss_destination). (default false)
oss boolean EU: the company is registered for the One-Stop Shop (OSS) union scheme: it files the quarterly OSS return (kind oss_return) for its sales to consumers in other member states. (default false)
oss_from string (date) or null EU: the day the OSS registration takes effect (Implementing Regulation 282/2011 art. 57d); no OSS return is due for a quarter that ends before it.
oss_destination boolean EU: the company opted to charge the customer's VAT on distance sales of goods and electronic services to consumers in other member states even below the EUR 10,000 threshold (Directive 2006/112/EC art. 59c(3)). (default false)

VatStatementRow

A recapitulative statement row: one customer VAT number and kind of supply.

Field Type Required Description
country_code string yes Country prefix of the customer's VAT number (two letters).
vat_id string yes The customer's VAT number without the country prefix.
party string or null yes Name of the customer with that VAT number, or null.
box string yes Box id of the supply kind: goods, services or triangulation.
amount string yes Total supplies as a decimal string (whole euros on the ZM); 0 cancels a row in a ZM correction, while a 349 sustitutiva repeats every row.

VatSubmitInput

Field Type Required Description
submitted_on string (date) yes The day the return was submitted to the tax administration: not before the period ends and not in the future.
submission_reference string or null The tax administration's reference or confirmation number. Optional. (max length 200)

VatTaxFxRate

An official VAT exchange rate the return converted foreign-currency lines at.

Field Type Required Description
series string yes Official rate series, e.g. de-vat-monthly.
currency string yes Foreign currency the rate converts.
period string or null yes Month of a monthly rate, or the daily rate's date.
rate string yes The rate as a decimal string.
quotation string yes How the rate is quoted (units of which currency per unit of which).
lines integer yes Number of journal lines converted with it.
looked_up boolean yes The rate was not published when the documents were posted; the return looked it up when it was computed.
Stabiso, the Enterprise System of Record · generated from the code and its guides · release 20b7dd5b0c4d