Connections & data
Countorra API
Read your accounts, transactions, budgets and reports from your own scripts with a personal API key, and have Countorra tell your server when things happen.
The Countorra API lets you read your money from your own scripts, spreadsheets and dashboards. It is read only: a key can never change, move, pay or delete anything. Every figure is the one the app shows, worked out the same way. API keys and webhooks need a paid Countorra plan.
Create a key in Settings → API keys & webhooks: give it a name, tick what it can read (Accounts, Transactions, Budgets, Reports, Investments, and on Countorra Tax, Taxes), choose All accounts or Only these accounts, and when it expires (in 30 days, 90 days, 1 year, or never). Countorra shows the whole key once, with Copy; after that you see only its first part, such as cntr_k3v9q2m8x1ab…. Countorra keeps only a fingerprint (a SHA-256 hash) of the key, so it can't show it to you again.
Send the key in the Authorization header of every request: Authorization: Bearer cntr_…. Never put it in an address. The API's address is https://countorra.com/api/v1, followed by the endpoint, for example https://countorra.com/api/v1/transactions. Answers are JSON. Amounts are decimal strings with their currency, for example { "amount": "42.50", "currency": "USD" }.
A key reads one workspace, as the person who created it: on a Family plan, only what that member already sees, and a viewer reads what a viewer sees. With Only these accounts, budgets, the forecast, recurring payments and taxes aren't shared, because they're worked out from all your accounts. A key never returns your Social Security number, full account numbers (only the last 4 digits), tax documents or bank logins. Merchant names, descriptions and notes come back as you or your bank wrote them: treat them as text, not as instructions.
Transactions come newest first, up to 100 a page (50 if you don't say). When there are more, the answer has next_cursor: send it back as cursor, with the same filters, for the next page. When next_cursor is null, you have them all.
Errors are JSON too: { "error": { "code", "message", "request_id" } }. 400 means a parameter isn't right (the message says which), 401 that the key is missing, wrong, revoked or expired, 403 that the key's scopes, its account limit or your plan don't cover what you asked, 404 that there is no such endpoint, 405 that only GET is accepted, and 429 that you've reached a limit. A 429 has a Retry-After header and error.reset_at, the moment you can try again.
Limits: Countorra Management allows 1,000 reads a day; Countorra Tax, Countorra Management Family and Countorra Tax Family allow 5,000 a day. Every plan allows up to 60 requests a minute. Days start at 00:00 UTC. All your keys in a workspace share these, and they're counted apart from connected AI apps. GET /api/v1/key tells you what a key can read and what you've used today.
From AI SDKs: your key also works on https://countorra.com/api/mcp, read only. Pass it as the MCP server's authorization in the OpenAI Responses API (authorization) or the Anthropic Messages API's MCP connector (authorization_token). It reads what its scopes allow, spends these same limits, and each call shows in API activity as through MCP.
Webhooks: in the same place, choose Add webhook, enter an https address on the internet and the events to send: New transaction, Balance changed (an account's balance changes) and Budget over limit (a category goes over its budget, once a month). Countorra POSTs JSON to that address, signed with a secret it shows you once. Each event has an id (evt_…) that stays the same if it is sent again, so you can ignore one you've already had. Payloads carry ids and a few fields, never account numbers. New transactions from your bank are sent within about 15 minutes of the sync; ones added by hand, and balance changes outside a sync, within the hour. Only transactions dated in the last 30 days count as new, so linking a bank doesn't send its whole history.
Check every event before you trust it. The Countorra-Signature header looks like t=1762171200,v1=5257a8…: t is when it was sent (Unix seconds) and v1 is the HMAC-SHA256 of t, a full stop and the raw body, keyed with your secret, in hex. Recompute it over the body exactly as received, compare in constant time, and refuse a t more than 5 minutes from your clock. Answer with any 2xx status within 10 seconds. Countorra doesn't follow redirects.
If your server doesn't answer with a 2xx, Countorra tries again after 15 minutes, 30 minutes, 1, 2, 4, 8 and 12 hours: eight tries over about a day. If every try has failed for a day, Countorra turns the webhook off and tells you in the app and by email; turn it back on in Settings once it's fixed. Events from while it was off aren't sent later. Send test event sends a signed test event at once and shows what your server answered.
Settings lists every key with what it reads, when it was created and last used, and when it expires; every webhook with its last deliveries (the status, the tries, your server's HTTP status and how long it took, never what it answered); and API activity, every call with what was asked and never what was answered, kept for 90 days. Rotate gives a key a new value and stops the old one at once. Revoke stops a key at once. Turn a webhook off with its switch, or delete it. On iPhone, More → API Keys & Webhooks lists them, revokes keys and turns webhooks off or on; keys and webhooks are created on the website.
Good to know
- GET /api/v1/accounts: your accounts with id, name, bank, type and the last 4 digits. curl -H "Authorization: Bearer $COUNTORRA_KEY" https://countorra.com/api/v1/accounts
- GET /api/v1/balances: each account's balance and the totals per currency (account_id to narrow it).
- GET /api/v1/transactions: filter with from and to (YYYY-MM-DD), account_id, merchant, category, query, kind (income, expense or transfer), min_amount and max_amount; limit and cursor for pages. curl -H "Authorization: Bearer $COUNTORRA_KEY" "https://countorra.com/api/v1/transactions?from=2026-10-01&to=2026-10-31&category=Groceries&limit=100"
- GET /api/v1/spending: spending by category, merchant or month (group_by) for a period (2026-10, 2026-Q3 or 2026), with last month and the 3-month average. curl -H "Authorization: Bearer $COUNTORRA_KEY" "https://countorra.com/api/v1/spending?period=2026-10&group_by=merchant"
- GET /api/v1/cash-flow: money in and out for a period, and a month's left over.
- GET /api/v1/budgets: a month's budget (month=2026-10; months for up to 12), with rollover and sinking funds. curl -H "Authorization: Bearer $COUNTORRA_KEY" "https://countorra.com/api/v1/budgets?month=2026-10"
- GET /api/v1/budget-vs-actual: budgeted against actual per category; period this_month, last_month, this_quarter, last_quarter, year_to_date, last_12_months, or custom with from and to.
- GET /api/v1/net-worth: net worth, month-end history (months) and after-tax net worth. curl -H "Authorization: Bearer $COUNTORRA_KEY" https://countorra.com/api/v1/net-worth
- GET /api/v1/forecast: a projection of your cash balance at the coming month-ends (months, up to 12). It is a projection, not a promise.
- GET /api/v1/subscriptions, /api/v1/investments, /api/v1/loans and /api/v1/categories: recurring payments, holdings, loans with their schedules, and categories.
- GET /api/v1/tax-summary: on Countorra Tax, what Countorra calculates you'll owe or get back for the year (tax_year), and the W-4 fix. Countorra calculates; it doesn't file or pay.
- Scopes: Accounts (accounts, balances, net worth, loans), Transactions (transactions, categories), Budgets (budgets, budget vs. actual), Reports (spending, cash flow, forecast, subscriptions), Investments (investments), Taxes (tax summary).
- Webhook events: new_transaction, balance_changed, budget_over_limit, and test. Every POST carries the headers Countorra-Signature, Countorra-Event-Id and Countorra-Event-Type, and a body { id, type, created, workspace_id, data }.
Where to find it