KAPITAH® REST API (v1)

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).

1. Get a token

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_….

2. Authenticate

Send the token in the Authorization header:

Authorization: Bearer kpt_live_xxxxxxxxxxxxxxxxxxxxxxxx

3. Base URL

https://kapitah.com/api/public/v1

All endpoints return JSON. All requests are scoped to the company that owns the token.

4. Available resources

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

5. Query parameters

6. Examples

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

7. Response shape

{
  "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).

7b. Use from Excel (Power Query)

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
    BalanceSheet

8. Errors