Appearance
accounting
93 endpoints.
GET /api/v1/accounting/books-sites
List Books Instances
The businesses whose books this hub can show — the site switcher's list.
The estate is multi-company by SCHEMA, not by company_id: each business keeps its own complete books, and switching repoints the session rather than adding a filter (see app.core.books_switch).
Platform STAFF only (books_switch.may_switch), and a non-superuser is offered only the businesses they hold an account on — the same two-part rule grid_engine.load_config and deps.get_switched_books_db enforce on the switched request itself. Anyone else gets no list, therefore no switcher: useBooksSites reads canSwitch off its length and the sidebar falls back to the organization switcher.
200 — Successful Response
json
{}GET /api/v1/accounting/companies
List Companies
Every company this user may see — the company switcher's list.
Narrowed by AccUserCompany, NOT by the active-company header: the switcher has to be able to show the companies you could switch TO, and filtering this by the company you are currently on would leave it with one entry and no way out.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
include_disabled | query | no | boolean |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}PUT /api/v1/accounting/companies/{company_id}
Update Company
Edit one company's header.
base_currency is accepted but guarded: changing it after the company has posted anything silently restates every historical base_* amount and every GL row, because those columns record a number, not a currency — there is no conversion pass that could fix them. So it is only editable while the books are empty.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
company_id | path | yes | string |
Request body
json
{
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Name"
},
"abbr": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Abbr"
},
"base_currency": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Base Currency"
},
"country": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Country"
},
"tax_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Tax Id"
},
"naming_prefix": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Naming Prefix"
},
"disabled": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"title": "Disabled"
}
},
"type": "object",
"title": "CompanyIn",
"description": "Editable company header fields (Settings → Accounting → Company)."
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/companies/{company_id}/branding
Get Company Branding
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
company_id | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}PUT /api/v1/accounting/companies/{company_id}/branding
Update Company Branding
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
company_id | path | yes | string |
Request body
json
{
"properties": {
"company_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Company Name"
},
"address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Address"
},
"contact_line": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Contact Line"
},
"footer_text": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Footer Text"
},
"notes": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Notes"
},
"vat_note": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Vat Note"
},
"logo_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Logo Url"
},
"registration_no": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Registration No"
}
},
"type": "object",
"title": "CompanyBrandingIn"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/accounting/companies/quick-create
Quick Create Company
One-click "Create organization" for the Setup Status page: the generic /g/acc-companies grid can only insert a bare row, which isn't usable for anything until it has a chart of accounts — this seeds the standard one (same template every other company got) plus the current fiscal year, a cost center and warehouses in a single call.
Request body
json
{
"properties": {
"name": {
"type": "string",
"title": "Name"
},
"abbr": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Abbr"
},
"base_currency": {
"type": "string",
"title": "Base Currency",
"default": "ZAR"
},
"country": {
"type": "string",
"title": "Country",
"default": "South Africa"
},
"tax_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Tax Id"
}
},
"type": "object",
"required": [
"name"
],
"title": "QuickCreateCompanyIn"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/currencies
List Currencies
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
enabled_only | query | no | boolean |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/accounting/currencies
Create Currency
Request body
json
{
"properties": {
"code": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Code"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Name"
},
"symbol": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Symbol"
},
"decimals": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Decimals"
},
"enabled": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"title": "Enabled"
},
"auto_fetch": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"title": "Auto Fetch"
}
},
"type": "object",
"title": "CurrencyIn"
}201 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}PUT /api/v1/accounting/currencies/{currency_id}
Update Currency
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
currency_id | path | yes | string |
Request body
json
{
"properties": {
"code": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Code"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Name"
},
"symbol": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Symbol"
},
"decimals": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Decimals"
},
"enabled": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"title": "Enabled"
},
"auto_fetch": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"title": "Auto Fetch"
}
},
"type": "object",
"title": "CurrencyIn"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}DELETE /api/v1/accounting/currencies/{currency_id}
Delete Currency
Soft-disable, never a hard delete: a currency with documents against it must keep formatting correctly forever.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
currency_id | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/exchange-rates
List Exchange Rates
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
from_ccy | query | no | ||
to_ccy | query | no | ||
limit | query | no | integer |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/accounting/exchange-rates
Create Exchange Rate
Request body
json
{
"properties": {
"from_ccy": {
"type": "string",
"title": "From Ccy"
},
"to_ccy": {
"type": "string",
"title": "To Ccy"
},
"date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Date"
},
"rate": {
"anyOf": [
{
"type": "number"
},
{
"type": "string",
"pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"
}
],
"title": "Rate"
}
},
"type": "object",
"required": [
"from_ccy",
"to_ccy",
"rate"
],
"title": "ExchangeRateIn"
}201 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}DELETE /api/v1/accounting/exchange-rates/{rate_id}
Delete Exchange Rate
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
rate_id | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/accounting/exchange-rates/fetch
Fetch Exchange Rates
Pull today's rates from the feed now — the "Fetch rates" button.
Quotes every auto_fetch currency INTO each company's base currency, which is the direction documents convert in. Never overwrites a rate entered by hand (see accounting_currency.set_rate).
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
on_date | query | no |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/currency-status
Currency Status
What the Exchange Rates settings card shows above the table: which pairs are stale, and how many currencies are on the feed.
Surfacing staleness in Settings is the point — the previous failure mode was finding out the rates were wrong from an invoice, weeks later.
200 — Successful Response
json
{}GET /api/v1/accounting/features
Accounting Features
Which of the books' PAID capabilities this site has (2026-08-30).
One endpoint rather than each settings card asking /apps for itself: the Accounting settings page renders four cards that depend on these two answers, and the page should not flash three sections it is about to hide.
in_use is sent beside each flag so the UI can explain an uninstall honestly rather than just going blank — a site with a GBP customer and no Multi-Company... sorry, Multi-Currency app is a real state (it is what an uninstall leaves behind), and the cards say so instead of pretending the foreign balances are not there. Reads only; nothing here grants anything.
200 — Successful Response
json
{}GET /api/v1/accounting/fx/realisable
Fx Realisable
Foreign-currency accounts that are square in their own currency but not in base — the exchange difference each one has realised.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
company_id | query | no | ||
as_on | query | no |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/accounting/fx/realise
Fx Realise Post
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
company_id | query | no |
Request body
json
{
"properties": {
"customer_ids": {
"items": {
"type": "string"
},
"type": "array",
"title": "Customer Ids"
},
"as_on": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "As On"
}
},
"type": "object",
"title": "RealiseFxIn"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/user-companies
List User Companies
Every user, with the companies they're restricted to (empty = all).
Hidden platform accounts excluded, for the reason the Org Users grid gives (app/grids/platform.py's org-users base_filter): Ahmed and Faizaan are seeded as internal superadmins on EVERY site including customers' own ERPs so support can reach them, and a customer looking at their own people should see their own staff, not two Lubb logins they did not create and must not manage. That grid filtered them and this list did not, so the same two rows it hides were listed here — with is_superuser: true beside them — on every customer ERP. Company grants for them would be meaningless anyway: company_scope bypasses the restriction for superusers entirely.
200 — Successful Response
json
{}PUT /api/v1/accounting/user-companies/{user_id}
Set User Companies
Replace one user's company grants. An empty list clears the restriction (back to "sees every company"), which is the only way back — there is no separate "unrestrict" call to forget.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
user_id | path | yes | string |
Request body
json
{
"properties": {
"company_ids": {
"items": {
"type": "string"
},
"type": "array",
"title": "Company Ids"
}
},
"type": "object",
"title": "UserCompaniesIn"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/party-contacts
Get Party Contacts
The contact people to offer for a document's "Contact" field — the names that fill the picker sitting right under the party on the document form (owner, 2026-09-08: "add a contact person field after customer", "always put contact after company").
A SUGGESTION list, never a constraint. The field stores a plain name string, so the form is free to take a typed one that appears nowhere here — which it has to be: only 34 of tc's 469 customers have a linked acc_contact row (of 1 697 contacts, nearly all unlinked ERPNext imports) and 4 of lubb's 26, so a picker that could only offer these would be empty on the great majority of documents.
The two sides read different stores, because that is where each one keeps a contact:
- customer — its
acc_contactrows, primary first then by name, with the role carried through so "Accounts" and "Technical" are distinguishable when a customer has several. - supplier — the single
AccSupplier.contact_personfree-text field. One option, or none.
Returns {"contacts": [...]}, empty when the party has none or when neither id is given. Never 404s on an unknown party: an empty picker that still takes a typed name is the working state here, and an error would block a form over a suggestion.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
customer_id | query | no | ||
supplier_id | query | no |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/item-price
Get Item Price
The rate a document line should use for item_id — resolved, not typed. Resolution order, most specific first:
- a price row scoped to this exact customer (
AccItemPrice.customer_id, the party-specific override); - the customer's own
default_price_list_id, if it has one; - the standard list for what this party IS — Reseller for a reseller or a reseller's sub user, Customer for everybody else;
- any generic row at all, lowest rate first.
Step 3 is what stops a normal customer being quoted off whatever list happens to hold a row for the item. Before 2026-08-11 there was no such step: a customer with no default_price_list_id — which is every ordinary customer, the column is opt-in — fell straight to step 4, then written as next(p for p in prices if p.customer_id is None), i.e. the first row in unordered SELECT order. On OFFICE that is the Wholesale row, so SM Watch (a plain customer, no group, no reseller) was quoted R80 for a R100 item. It picked the right rate only for items priced on exactly one list, which hid it.
Deliberately mirrors bill_run._price_active_subscriptions' party rule, including its Resellers-setting gate, so a quotation and the bill run that later invoices the same item agree. Step 4 keeps its "something is better than nothing" role for items priced on neither standard list, but takes the LOWEST rate rather than an arbitrary one — never quote a customer more than a row on file says, and never depend on row order again.
Returns {"rate": null} rather than a 404 when nothing is priced — an unpriced item is a normal, fixable state (add a row in Item Prices), not an error.
Also returns the item's pricing-table content (long_description, the stored HTML block — see AccItem.long_description — falling back to features bullets for items not yet backfilled) so the Quotation/Sales Order form can show it per line the same way the read-only document view and PDF already do — this is the one call already made whenever a line's item is picked, so it's piggybacked here rather than adding a second round trip.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
item_id | query | yes | integer | |
customer_id | query | no |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/settings/letterhead
Get Letterhead
200 — Successful Response
json
{}PUT /api/v1/accounting/settings/letterhead
Update Letterhead
Request body
json
{
"properties": {
"enabled": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"title": "Enabled"
},
"company_name": {
"anyOf": [
{
"type": "string",
"maxLength": 255
},
{
"type": "null"
}
],
"title": "Company Name"
},
"address": {
"anyOf": [
{
"type": "string",
"maxLength": 2000
},
{
"type": "null"
}
],
"title": "Address"
},
"contact_line": {
"anyOf": [
{
"type": "string",
"maxLength": 500
},
{
"type": "null"
}
],
"title": "Contact Line"
},
"footer_text": {
"anyOf": [
{
"type": "string",
"maxLength": 2000
},
{
"type": "null"
}
],
"title": "Footer Text"
},
"notes": {
"anyOf": [
{
"type": "string",
"maxLength": 2000
},
{
"type": "null"
}
],
"title": "Notes"
},
"vat_note": {
"anyOf": [
{
"type": "string",
"maxLength": 500
},
{
"type": "null"
}
],
"title": "Vat Note"
}
},
"type": "object",
"title": "LetterheadIn",
"description": "Partial update for the site's invoice letterhead. A field omitted\n(``None``) is left untouched."
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/settings/document-banking
Get Document Banking
200 — Successful Response
json
{}PUT /api/v1/accounting/settings/document-banking
Update Document Banking
Request body
json
{
"properties": {
"show_on_invoices": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"title": "Show On Invoices"
},
"show_on_quotes": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"title": "Show On Quotes"
},
"show_on_receipts": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"title": "Show On Receipts"
},
"show_on_statements": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"title": "Show On Statements"
},
"show_when_no_card_option": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"title": "Show When No Card Option"
},
"accounts_by_currency": {
"anyOf": [
{
"additionalProperties": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
]
},
"type": "object"
},
{
"type": "null"
}
],
"title": "Accounts By Currency"
}
},
"type": "object",
"title": "DocumentBankingIn",
"description": "Partial update for which bank account prints on which document. A field\nomitted (``None``) is left untouched — see\n:mod:`app.apps.erp.services.accounting_bank_display`."
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/settings/document-banking/options
Get Document Banking Options
The currencies and bank accounts the form offers — see :func:accounting_bank_display.options.
200 — Successful Response
json
{}GET /api/v1/accounting/settings/vat
Get Vat Settings
200 — Successful Response
json
{}PUT /api/v1/accounting/settings/vat
Update Vat Settings
Request body
json
{
"properties": {
"enabled": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"title": "Enabled"
},
"rate": {
"anyOf": [
{
"type": "number",
"maximum": 100,
"minimum": 0
},
{
"type": "null"
}
],
"title": "Rate"
},
"account_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Account Id"
},
"inclusive": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"title": "Inclusive"
}
},
"type": "object",
"title": "VatSettingsIn",
"description": "Partial update for the site's VAT settings. A field omitted (``None``)\nis left untouched."
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/settings/prorata
Get Prorata Settings
200 — Successful Response
json
{}PUT /api/v1/accounting/settings/prorata
Update Prorata Settings
Request body
json
{
"properties": {
"enabled": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"title": "Enabled"
}
},
"type": "object",
"title": "ProrataSettingsIn",
"description": "Partial update for the site's Prorated First-Bill setting. Omitted\n(``None``) is left untouched."
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/settings/resellers
Get Reseller Settings
200 — Successful Response
json
{}PUT /api/v1/accounting/settings/resellers
Update Reseller Settings
Request body
json
{
"properties": {
"enabled": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"title": "Enabled"
}
},
"type": "object",
"title": "ResellerSettingsIn",
"description": "Partial update for the site's Resellers setting. Omitted (``None``) is\nleft untouched."
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/settings/company-defaults
Get Company Defaults
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
company_id | query | no |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}PUT /api/v1/accounting/settings/company-defaults
Update Company Defaults
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
company_id | query | no |
Request body
json
{
"properties": {
"income_account_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Income Account Id"
},
"expense_account_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Expense Account Id"
},
"exchange_gain_loss_account_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Exchange Gain Loss Account Id"
}
},
"type": "object",
"title": "CompanyDefaultsIn"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/bank-accounts
List Bank Accounts
Bank accounts with their is_default flag, default-first — narrowed to the active company's own accounts plus the shared ones.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
company_id | query | no |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/settings/default-bank
Get Default Bank
The default bank account (or the sole account on a one-account site), narrowed to the active company exactly as list_bank_accounts above — otherwise a form on company B pre-fills company A's account.
200 — Successful Response
json
{}PUT /api/v1/accounting/settings/default-bank
Set Default Bank
Request body
json
{
"properties": {
"bank_account_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Bank Account Id"
}
},
"type": "object",
"title": "DefaultBankIn",
"description": "Which account is the site default. ``null`` clears the default."
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/accounting/documents/{doctype}
Create Document
Create a draft document (header + child rows) from the entry form. With ?submit=true it is posted to the GL immediately after creation.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
doctype | path | yes | string | |
submit | query | no | boolean |
Request body
json
{
"type": "object",
"additionalProperties": true,
"title": "Payload"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/reseller-users/{reseller_user_id}/party
Resolve Reseller User Party
Resolve a ResellerUser — picked directly by name from the combined Customer/Lead/Reseller-User picker on the Quotation form (see features/accounting/party-options.ts) — to the AccCustomer a document actually posts against. A document's customer_id is strictly an AccCustomer FK (unlike Activation/Subscription's soft uuid ref), so a reseller's own end-user always resolves to the parent reseller account, carrying reseller_user_id alongside so the saved document still records which end-user it's actually for (mirrors the Leads grid's create_quotation resolve-at-save pattern, one step later since the party here already exists rather than needing to be created).
Returns both customer_id (the integer FK Quotation/Sales Order forms save) and customer_uuid (what Bank Reconciliation's Create Payment Entry needs instead — AccPaymentEntry.party_id is a polymorphic GUID soft-ref, not the integer id, since it has to point at either an AccCustomer or an AccSupplier).
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
reseller_user_id | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/accounting/documents/acc_purchase_invoice/ocr-upload
Ocr Upload Purchase Invoice
Upload & Scan Invoice: OCR an uploaded supplier bill and create a draft Purchase Invoice from it. When the supplier can't be confidently matched by name the draft is still created without a party (never auto-picking/guessing a supplier on a financial document); the response's supplier_matched is null and supplier_scanned carries the name the OCR read, so the user can pick the supplier on the edit form — where it stays required before saving.
Password-protected PDFs raise 423 with a machine-readable detail.code (password_required / wrong_password) so the frontend can pop a small window to collect the password and retry, rather than surfacing a dead-end error.
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/documents/acc_purchase_invoice/{doc_id}/billing-check
Billing Check Status
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
doc_id | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/accounting/documents/acc_purchase_invoice/{doc_id}/billing-check/{which}
Billing Check Upload
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
doc_id | path | yes | string | |
which | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/accounting/documents/acc_purchase_invoice/{doc_id}/billing-check-reviewed
Billing Check Reviewed
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
doc_id | path | yes | string |
Request body
json
{
"type": "object",
"additionalProperties": true,
"title": "Payload"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/documents/acc_purchase_invoice/{doc_id}/billing-check-file/{which}
Billing Check File
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
doc_id | path | yes | string | |
which | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/documents/{doctype}/{doc_id}
View Document
Read one document (header + child rows, FK names resolved) for the grid's view modal — opened by double-clicking a transactional grid row.
Two different crossings stack here, and both are needed: the switcher picks the schema (the row was double-clicked on a switched grid, so the id means something only there), and _books_db below then crosses a PORTAL to its parent's books. With no switch in force the first is a no-op and this is exactly what it was.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
doctype | path | yes | string | |
doc_id | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}PUT /api/v1/accounting/documents/{doctype}/{doc_id}
Update Document
Update a draft document's header + child rows in place. With ?submit=true it is posted to the GL immediately after saving.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
doctype | path | yes | string | |
doc_id | path | yes | string | |
submit | query | no | boolean |
Request body
json
{
"type": "object",
"additionalProperties": true,
"title": "Payload"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/documents/{doctype}/{doc_id}/edit
Edit Document
Read one DRAFT document back in raw, editable form (ids, not resolved display names) — feeds the edit form opened by double-clicking a draft row on the Sales Invoices grid.
Deliberately NOT crossed to a PORTAL's parent the way the read-only view above is (_books_db): the PUT that saves the form doesn't cross either (a write carries GL posting and docstatus-trigger side effects that shouldn't silently land in another site's books), so crossing only the GET would open an edit form that 404s on save. Editing a draft happens on the books site that owns it.
The books-site SWITCHER is the other thing entirely, and this route does follow it — deliberately, and so does the PUT, so the pair still agree. A superuser who switched to Telecloud is looking at tc's Quotations grid; the draft they double-click is a tc row and must be read back, and saved, in tc.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
doctype | path | yes | string | |
doc_id | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/accounting/{doctype}/{doc_id}/submit
Submit
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
doctype | path | yes | string | |
doc_id | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/accounting/{doctype}/{doc_id}/cancel
Cancel
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
doctype | path | yes | string | |
doc_id | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/reports/trial-balance
R Trial Balance
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
company_id | query | no | ||
from | query | no | ||
to | query | no | ||
hide_zero | query | no | boolean |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/reports/general-ledger
R General Ledger
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
company_id | query | no | ||
account_id | query | no | ||
party_id | query | no | ||
from | query | no | ||
to | query | no |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/reports/profit-loss
R Profit Loss
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
company_id | query | no | ||
from | query | no | ||
to | query | no |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/reports/balance-sheet
R Balance Sheet
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
company_id | query | no | ||
as_on | query | no |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/reports/cash-flow
R Cash Flow
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
company_id | query | no | ||
from | query | no | ||
to | query | no |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/reports/cash-flow-projection
R Cash Flow Projection
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
company_id | query | no | ||
as_on | query | no | ||
months_history | query | no | integer | |
months_forward | query | no | integer |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/reports/sales-register
R Sales Register
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
company_id | query | no | ||
from | query | no | ||
to | query | no |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/reports/purchase-register
R Purchase Register
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
company_id | query | no | ||
from | query | no | ||
to | query | no |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/reports/ar-summary
R Ar Summary
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
company_id | query | no | ||
as_on | query | no |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/reports/ap-summary
R Ap Summary
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
company_id | query | no | ||
as_on | query | no |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/reports/ar-ageing
R Ar Ageing
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
company_id | query | no | ||
as_on | query | no |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/reports/ap-ageing
R Ap Ageing
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
company_id | query | no | ||
as_on | query | no |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/accounting/cash-book/post
R Cash Book Post
Post a page of cash-book lines against one bank account — one journal per line, so each stays independently reconcilable against the statement. The whole batch is validated before anything posts.
Request body
json
{
"properties": {
"company_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Company Id"
},
"bank_account_id": {
"type": "string",
"title": "Bank Account Id"
},
"lines": {
"items": {
"properties": {
"date": {
"type": "string",
"title": "Date"
},
"direction": {
"type": "string",
"title": "Direction"
},
"amount": {
"type": "number",
"title": "Amount"
},
"account_id": {
"type": "string",
"title": "Account Id"
},
"party_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Party Type"
},
"party_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Party Id"
},
"reference": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Reference"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Description"
}
},
"type": "object",
"required": [
"date",
"direction",
"amount",
"account_id"
],
"title": "CashBookLineIn"
},
"type": "array",
"title": "Lines"
},
"dry_run": {
"type": "boolean",
"title": "Dry Run",
"default": false
}
},
"type": "object",
"required": [
"bank_account_id",
"lines"
],
"title": "CashBookBatchIn"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/journal-types
R Journal Types
The suggested journal types for the Journal Entry form. Served rather than hardcoded in the client so the vocabulary has one home (accounting_documents.JOURNAL_ENTRY_TYPES) and cannot drift.
200 — Successful Response
json
{}GET /api/v1/accounting/reports/detailed-general-ledger
R Detailed General Ledger
Pastel's "GL Detailed Ledger" — every account grouped, each with its own opening balance, movements and cumulative. The flat /reports/general-ledger only computes those for a single selected account.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
company_id | query | no | ||
from | query | no | ||
to | query | no | ||
hide_empty | query | no | boolean |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/reports/party-detailed-ledger
R Party Detailed Ledger
Pastel's "Customer/Supplier Detailed Ledger" — every party in one pass. The per-party statement answers one customer at a time.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
company_id | query | no | ||
party_type | query | no | string | |
from | query | no | ||
to | query | no | ||
hide_empty | query | no | boolean |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/reports/age-analysis
R Age Analysis
Ageing in Pastel's own bands (Current / 30 / 60 / 90 / 120+) rather than the platform's finer early-warning ones. Same FIFO charges, so the totals agree with the statements and the control account.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
company_id | query | no | ||
party_type | query | no | string | |
as_on | query | no |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/reports/vat201
R Vat201
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
company_id | query | no | ||
from | query | no | ||
to | query | no | ||
period | query | no | ||
anchor | query | no |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/reports/vat-transactions
R Vat Transactions
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
company_id | query | no | ||
from | query | no | ||
to | query | no | ||
period | query | no | ||
anchor | query | no |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/year-end/status
R Year End Status
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
company_id | query | no |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/accounting/year-end/preview
R Year End Preview
What closing the year would post — shown to the operator before they commit to it. Writes nothing.
Request body
json
{
"properties": {
"company_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Company Id"
},
"fiscal_year_id": {
"type": "string",
"title": "Fiscal Year Id"
}
},
"type": "object",
"required": [
"fiscal_year_id"
],
"title": "YearEndIn"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/accounting/year-end/close
R Year End Close
Request body
json
{
"properties": {
"company_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Company Id"
},
"fiscal_year_id": {
"type": "string",
"title": "Fiscal Year Id"
}
},
"type": "object",
"required": [
"fiscal_year_id"
],
"title": "YearEndIn"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/accounting/year-end/reopen
R Year End Reopen
Request body
json
{
"properties": {
"company_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Company Id"
},
"fiscal_year_id": {
"type": "string",
"title": "Fiscal Year Id"
}
},
"type": "object",
"required": [
"fiscal_year_id"
],
"title": "YearEndIn"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/reports/bank-reconciliation
R Bank Reconciliation
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
bank_account_id | query | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/reports/{report}/pdf
R Report Pdf
The Accounting Reports page's "View PDF" button — same branded table renderer every grid's auto-attached View PDF button uses (:mod:app.services.grid_pdf), since this bespoke tabbed page isn't a GridConfig-backed grid and so never picked that up automatically.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
report | path | yes | string | |
company_id | query | no | ||
from | query | no | ||
to | query | no | ||
as_on | query | no | ||
bank_account_id | query | no | ||
hide_zero | query | no | boolean |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/reports/{report}/excel
R Report Excel
"Export to Excel" — the same report, the same rows as the PDF, but with the amounts as real numbers so the sheet can be summed and filtered.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
report | path | yes | string | |
company_id | query | no | ||
from | query | no | ||
to | query | no | ||
as_on | query | no | ||
bank_account_id | query | no | ||
hide_zero | query | no | boolean |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/accounting/customers/{customer_id}/email-attachments
Upload Customer Email Attachment
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
customer_id | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}DELETE /api/v1/accounting/customers/{customer_id}/email-attachments/{attachment_id}
Discard Customer Email Attachment
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
customer_id | path | yes | string | |
attachment_id | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/suppliers/{supplier_id}/documents
List Supplier Documents
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
supplier_id | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/accounting/suppliers/{supplier_id}/documents
Upload Supplier Document
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
supplier_id | path | yes | string |
201 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}PATCH /api/v1/accounting/suppliers/{supplier_id}/documents/{document_id}
Rename Supplier Document
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
supplier_id | path | yes | string | |
document_id | path | yes | string |
Request body
json
{
"properties": {
"filename": {
"type": "string",
"title": "Filename"
}
},
"type": "object",
"required": [
"filename"
],
"title": "Body_rename_supplier_document_api_v1_accounting_suppliers__supplier_id__documents__document_id__patch"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}DELETE /api/v1/accounting/suppliers/{supplier_id}/documents/{document_id}
Delete Supplier Document
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
supplier_id | path | yes | string | |
document_id | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/suppliers/{supplier_id}/documents/{document_id}/content
Get Supplier Document Content
Serve the raw file (inline) for preview/download in the drawer — the frontend fetches this with its auth header and shows images inline.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
supplier_id | path | yes | string | |
document_id | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/accounting/bank/import-statement/{bank_account_id}
Import Statement
Parse an uploaded OFX or CSV statement and import its lines (deduped).
fmt is optional — the format is detected from the file's own content when it isn't given. Until 2026-09-02 this accepted OFX and nothing else, which left every bank but FNB (whose CSV parsing sat behind a separate app) with no import route at all; the parser it refused to reach was never FNB-specific and now backs both.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
bank_account_id | path | yes | string |
Request body
json
{
"properties": {
"text": {
"type": "string",
"title": "Text"
},
"fmt": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Fmt"
}
},
"type": "object",
"required": [
"text"
],
"title": "Body_import_statement_api_v1_accounting_bank_import_statement__bank_account_id__post"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/accounting/bank/import-statement-pdf/{bank_account_id}
Import Statement Pdf
Read an uploaded PDF bank statement and import its lines (deduped).
Same importer as OFX/CSV, so a line already on the books is skipped. The response carries balances_consistent: True when every running balance on the statement follows from the one before it plus that line's amount — the check that a digit was not misread. False means the figures do not tie and the imported lines should be eyeballed before they are reconciled.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
bank_account_id | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/accounting/bank/auto-match/{bank_account_id}
Bank Auto Match
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
bank_account_id | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/bank/match-candidates/{txn_id}
Bank Match Candidates
Vouchers that could clear this statement line (the 'Match Against Voucher' picker).
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
txn_id | path | yes | string | |
day_window | query | no | integer |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/bank/payment-form-options/{txn_id}
Bank Payment Form Options
The statement line plus the party / mode-of-payment picklists that back the Create Payment form (ERPNext's 'Create Voucher → Payment Entry' dialog).
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
txn_id | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/accounting/bank/create-payment/{txn_id}
Bank Create Payment
Create + submit a Payment Entry from a statement line and reconcile it (ERPNext's 'Create Voucher → Payment Entry').
keyphrase (optional) remembers the line's substring as a party-alias rule so future lines containing it auto-match to the same party.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
txn_id | path | yes | string |
Request body
json
{
"properties": {
"company_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Company Id"
},
"party_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Party Type"
},
"party_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Party Id"
},
"mode_of_payment_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Mode Of Payment Id"
},
"keyphrase": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Keyphrase"
}
},
"type": "object",
"title": "Body_bank_create_payment_api_v1_accounting_bank_create_payment__txn_id__post"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/accounting/bank/journal-form-options/{txn_id}
Bank Journal Form Options
The statement line plus the postable ledger accounts that back the Create Journal form (book a line to income/expense/asset accounts).
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
txn_id | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/accounting/bank/create-journal/{txn_id}
Bank Create Journal
Create + submit a Journal Entry from a statement line (bank vs the chosen ledger account, optionally tagged to a Customer/Supplier) and reconcile it.
keyphrase (optional) remembers the line's substring as a recon rule so future lines containing it auto-match to the chosen account.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
txn_id | path | yes | string |
Request body
json
{
"properties": {
"account_id": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Account Id"
},
"company_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Company Id"
},
"remark": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Remark"
},
"party_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Party Type"
},
"party_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Party Id"
},
"keyphrase": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Keyphrase"
}
},
"type": "object",
"title": "Body_bank_create_journal_api_v1_accounting_bank_create_journal__txn_id__post"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/accounting/bank/reconcile/{txn_id}
Bank Reconcile
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
txn_id | path | yes | string |
Request body
json
{
"properties": {
"voucher_type": {
"type": "string",
"title": "Voucher Type"
},
"voucher_id": {
"type": "string",
"title": "Voucher Id"
}
},
"type": "object",
"required": [
"voucher_type",
"voucher_id"
],
"title": "Body_bank_reconcile_api_v1_accounting_bank_reconcile__txn_id__post"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/accounting/bank/unreconcile/{txn_id}
Bank Unreconcile
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
txn_id | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}