External API
Last updated: October 22, 2026
The External API lets you add transactions to your Budget AI account from outside the app: Apple Shortcuts, scripts, bots, home automation or any tool that can send an HTTP request. Transactions arrive in the app automatically and are marked for review.
1. Get an API key
- Open Settings → Advanced → API in the app and tap Generate API key. The API is available with an active subscription.
- Choose the key’s expiry when you create it: For a set time — 30, 90 (default) or 180 days; or If unused — after 7, 30 (default), 90 or 180 days without a request. Keys without an expiry are not available. The app shows when the key expires. Each request extends the validity of a key with an inactivity limit. An expired key stops working; transactions sent with it that the app hasn't synced yet are deleted.
- Copy the key right away: it is shown only once. The app keeps only its first characters.
- Generating a new key revokes the previous one. You can revoke the key at any time on the same screen. When the subscription ends, the key is revoked automatically.
- Keep the key secret: anyone who has it can add transactions to your account.
2. Send a request
The endpoint URL is shown on the API screen in the app, for example https://external-api-budgetai.appwrite.network. All requests are POST with a JSON body to the path /add-transaction. The same screen has a request example with your own categories and account and a Request builder that makes a body from the fields you pick.
Pass the key in the body as apiKey or in the header Authorization: Bearer <key>.
curl -X POST "https://<endpoint from the app>/add-transaction" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer vf_your_key" \
-d '{
"mode": "manual",
"transaction": {
"type": "expense",
"amount": 4.5,
"currency": "USD",
"category": "Food",
"subCategory": "Coffee",
"account": "Card",
"note": "Latte"
}
}'
Apple Shortcuts
Use the Get Contents of URL action: set the URL to the endpoint with /add-transaction, Method to POST, add the header Authorization with the value Bearer vf_your_key, and pass the fields below as a JSON request body.
3. Manual mode
"mode": "manual" (the default). You pass the transaction fields yourself. Manual mode doesn't use AI tokens.
| Field | Required | Description |
|---|---|---|
amount | yes | Number, not zero. The sign is set by type: expenses are saved as negative, incomes as positive. |
currency | yes | 3-letter code, e.g. USD, EUR, RUB. |
type | yes | expense or income. |
dateTime | no | ISO 8601, e.g. 2026-10-13T09:30:00Z or 2026-10-13T12:30:00+03:00. Without it, the time of the request. |
note | no | Up to 500 characters. |
category, subCategory | no | Category and subcategory names exactly as in the app (case doesn't matter). A subcategory alone is enough: its category is found by it. An unknown name: the transaction is saved without a category. |
account | no | Account name exactly as in the app (case doesn't matter). Without it, or with an unknown name, the account selected in the app is used. |
Where the result goes: target
sync(default) — the transaction is saved for the app and appears there after sync.return— the processed transaction is only returned in the response, nothing is saved.syncreturn— both.
Response
{
"success": true,
"transactionsCount": 1,
"tokensUsed": 0,
"tokensRemaining": 999850,
"transactions": [ ... ] // only for target "return" and "syncreturn"
}
4. AI modes coming soon
These modes are not available yet; requests with them get 501 AI_MODE_DISABLED. When they are released:
"mode": "ai"— send text inrequest, e.g."coffee 4.5 and taxi 12", and AI turns it into one or more transactions with your categories."mode": "hybrid"— send a transaction with"category": "auto"(and optionally"subCategory": "auto"or"type": "auto") and anote; AI fills in only these fields.- Categories come from the app: it uploads their names to the server, so you don't need to know their IDs.
- AI requests spend tokens from your balance and count toward your daily token limit. Once the daily limit is reached, AI requests are rejected with
429 DAILY_LIMIT_EXCEEDEDuntil 00:00 UTC. A request is also rejected if the remaining limit is not enough for it, or with402 INSUFFICIENT_TOKENSif the balance is empty. The response shows the tokens used and the daily usage.
5. Limits
- Requests per minute and per day are limited for each key; the current values are shown on the API screen in the app.
- The number of transactions waiting for sync is limited. Open the app to sync them.
- A request over a limit gets status
429and the headerRetry-Afterwith the number of seconds to wait. - Limits may change; see the Terms of Service, section 6.8.
6. Errors
Errors come as {"error": "...", "code": "..."}.
| Status | Code | Meaning |
|---|---|---|
| 400 | INVALID_TRANSACTION, INVALID_MODE, INVALID_TARGET | The request body is invalid; error says what is wrong. |
| 401 | INVALID_API_KEY | The key is missing or unknown. |
| 401 | API_KEY_REVOKED | The key was revoked or replaced by a new one. |
| 401 | API_KEY_EXPIRED | The key has expired; create a new one in the app. |
| 401 | SUBSCRIPTION_EXPIRED | The subscription has ended; the key is revoked. |
| 402 | INSUFFICIENT_TOKENS | AI modes: the token balance is empty. |
| 409 | CONTEXT_MISSING | AI modes: categories are not synced yet. Open the app. |
| 429 | RATE_LIMIT_EXCEEDED, DAILY_REQUESTS_EXCEEDED | Too many requests per minute or per day. |
| 429 | PENDING_QUEUE_FULL | Too many transactions are waiting for sync. |
| 429 | DAILY_LIMIT_EXCEEDED | AI modes: the daily token limit is reached; resets at 00:00 UTC. |
| 501 | AI_MODE_DISABLED, ENCRYPTED_NOT_SUPPORTED | The mode is not available yet. |
| 5xx | INTERNAL_ERROR, AI_PROCESSING_ERROR | Server error; try again later. |
7. Terms
The API is a tool for advanced users, for your own account and personal use. You choose which tools and services get your key and what they send, and you are responsible for the requests made with it and their results: we don't check, set up or support third-party tools. Don't share your key or embed it in apps distributed to others. Check transactions added through the API like any other entries. Use of the API is subject to the Terms of Service (section 6.8) and the Privacy Policy. Questions: budgetai@agentmail.to.