Read-only access to a single company's accounting, AR, AP, and inventory data. Designed for consultants, accountants, and BI tools (Power BI, Excel, Tableau, Python, R).
Ask a company owner or admin to generate a token from Settings → API Tokens. The token is shown only once and looks like kpt_live_….
Send the token in the Authorization header:
Authorization: Bearer kpt_live_xxxxxxxxxxxxxxxxxxxxxxxxhttps://kapitah.com/api/public/v1All endpoints return JSON. All requests are scoped to the company that owns the token.
| Financials | /accounts, /journal-entries, /journal-lines |
| AR | /customers, /invoices, /credit-notes, /customer-receipts |
| AP | /vendors, /bills, /vendor-credit-notes, /vendor-payments |
| Inventory & Ops | /items, /item-categories, /warehouses, /stock-movements, /purchase-orders, /sales-orders |
| Reports | /reports/balance-sheet, /reports/income-statement, /reports/cash-flow, /reports/trial-balance, /reports/account-activity, /reports/budget-vs-actual, /reports/tax, /reports/cash-forecast, /reports/cfo-metrics, /reports/cfo-trends |
| Meta | /company, /healthz |
page (default 1), limit (default 100, max 500)updated_since=YYYY-MM-DD — incremental pullsstatus, customer_id, vendor_id, is_active)curl
curl -H "Authorization: Bearer $KAPITAH®_TOKEN" \
"https://kapitah.com/api/public/v1/invoices?status=posted&limit=200&page=1"Python (pandas)
import os, requests, pandas as pd
TOKEN = os.environ["KAPITAH®_TOKEN"]
r = requests.get(
"https://kapitah.com/api/public/v1/journal-lines",
headers={"Authorization": f"Bearer {TOKEN}"},
params={"limit": 500, "page": 1},
)
r.raise_for_status()
df = pd.DataFrame(r.json()["data"])
print(df.head())Power BI (Power Query M)
let
Token = "kpt_live_xxxxxxxxxxxxxxxxxxxxxxxx",
Source = Json.Document(Web.Contents("https://kapitah.com/api/public/v1/invoices", [
Headers = [ #"Authorization" = "Bearer " & Token ],
Query = [ limit = "500", page = "1" ]
])),
Data = Source[data],
Table = Table.FromRecords(Data)
in
Table{
"data": [ { ... }, { ... } ],
"pagination": { "page": 1, "limit": 100, "total": 1240, "has_more": true }
}Reports under /reports/… return { "data": [...] } with no pagination (each report is a single result set).
Download the pre-wired workbook from Settings → API Tokens → Excel dashboard, or build your own with this M snippet (Data → Get Data → From Other Sources → Blank Query):
let
Token = "kpt_live_xxxxxxxxxxxxxxxxxxxxxxxx",
BaseUrl = "https://kapitah.com/api/public/v1",
// Generic paginated GET — loops pages until empty.
KapitahGet = (path as text, optional query as record) =>
let
Page = (n) => Json.Document(Web.Contents(BaseUrl, [
RelativePath = path,
Query = Record.Combine({ query ?? [], [ page = Text.From(n), limit = "500" ] }),
Headers = [ #"Authorization" = "Bearer " & Token ]
])),
Pages = List.Generate(
() => [p = 1, r = Page(1)],
each List.Count(_[r][data]) > 0,
each [p = _[p] + 1, r = Page(_[p] + 1)],
each _[r][data]
)
in List.Combine(Pages),
// Reports return a single set (no pagination).
KapitahReport = (slug as text, query as record) =>
Json.Document(Web.Contents(BaseUrl, [
RelativePath = "reports/" & slug,
Query = query,
Headers = [ #"Authorization" = "Bearer " & Token ]
]))[data],
Invoices = Table.FromRecords(KapitahGet("invoices")),
Today = Date.ToText(Date.From(DateTime.LocalNow()), "yyyy-MM-dd"),
BalanceSheet = Table.FromRecords(KapitahReport("balance-sheet", [ as_of = Today ]))
in
BalanceSheet401 missing / invalid / expired token410 token has been revoked404 unknown resource or report400 invalid filter / report parameter429 rate-limited