@emilfrom/n8n-nodes-actual-budget
v2.4.0
Published
personal project for keeping track of my expenses. Thank you to jhonderson for the actual-http-api and Actual Budget for the software. Thank you Jan Oberhauser for the incredible n8n project.
Maintainers
Readme
@emilfrom/n8n-nodes-actual-budget
This is an n8n community node for working with Actual Budget through actual-http-api.
n8n is a workflow automation platform.
personal project for keeping track of my expenses. Thank you to jhonderson for the actual-http-api and Actual Budget for the software. Thank you Jan Oberhauser for the incredible n8n project. This was just for fun but let's see how it goes. I have learned so much about github actions and the npm registry now.
Installation
Follow the n8n community node installation guide.
For local development in this repository:
npm install
npm run devPrerequisites
Run actual-http-api somewhere n8n can reach it. The API service needs access to
your Actual server and should be configured with an API_KEY,
ACTUAL_SERVER_URL, and ACTUAL_SERVER_PASSWORD.
Example:
docker run -d --name actualhttpapi \
-v "$PWD/data:/data:rw" \
-p 5007:5007 \
-e ACTUAL_SERVER_URL="http://actual-server:5006/" \
-e ACTUAL_SERVER_PASSWORD="your-actual-password" \
-e API_KEY="your-api-key" \
jhonderson/actual-http-api:26.5.0Credentials
Create an Actual HTTP API credential in n8n with:
Base URL: Host (and optional path) where actual-http-api listens — for examplehttp://localhost:5007,http://actualhttpapi:5007, orhttp://localhost:5007/v1. Host-only URLs (no path) automatically use the API root/v1, matching actual-http-api OpenAPI defaults.API Key: TheAPI_KEYconfigured for actual-http-apiBudget Sync ID: The Sync ID from Actual Budget settings under advanced settingsBudget Encryption Password: Optional, only for encrypted budgets
The credential test calls GET /v1/budgets/{budgetSyncId}/accounts (or the same path under your custom base URL).
Troubleshooting
| Symptom | What to check |
|--------|----------------|
| 404 on /budgets/... | Budget Sync ID must match the budget file on the Actual server that actual-http-api uses. Confirm with curl against the same host (routes live under /v1/budgets/...). |
| ECONNREFUSED to ::1 or 127.0.0.1 | n8n runs in Docker: localhost inside the container is not your host. Use the container/service DNS name (e.g. http://actualhttpapi:5007) or the LAN IP n8n can reach. |
| Works in curl but not in n8n | Same Base URL shape as curl (host/service name), same sync id and API key. See Debugging (logs). |
Node version 2 (breaking change)
Version 2 of the Actual Budget node removes the old Import operation (which used
POST .../transactions/import and imported_id dedupe). Workflows must use Transaction: Create
and amounts as integer minor units, matching the actual-http-api
contract (value * 100 for most currencies).
Actions
Pick an Action on the node:
Transaction: Create
Creates one transaction per input item using the official single-create endpoint:
POST /budgets/{budgetSyncId}/accounts/{accountId}/transactions
Request body matches the API: learnCategories, runTransfers, and transaction with
account, category, amount, payee_name, date, cleared, and optionally notes.
- Account / Category: selectable lists from
GET /accountsandGET /categories - Amount: integer minor units (for example
-7374for-73.74in a two-decimal currency) - Date: stored as
YYYY-MM-DD - Payee Name: plain text (for example
Amazon) - Notes: optional; when non-empty, sent as
transaction.notes(memo on the transaction) - Cleared, Learn Categories, Run Transfers: booleans
Budget: Get Month
GET /budgets/{budgetSyncId}/months/{month} — pass Month as YYYY-MM. Output includes the API
data payload (totals, category groups, etc.).
Account: List
GET /budgets/{budgetSyncId}/accounts — returns the API response (including data).
Account: Get Balance
GET /budgets/{budgetSyncId}/accounts/{accountId}/balance — returns { "data": <integer> } in minor units (same as amounts elsewhere). Pick the Account from the list or by ID. Balance Cutoff Date is optional: maps to query cutoff_date=YYYY-MM-DD (balance as of that date). Leave it empty to rely on actual-http-api’s default (typically “today”).
Category: List
GET /budgets/{budgetSyncId}/categories — returns the API response (including data).
Category: Create
POST /budgets/{budgetSyncId}/categories with body { category: { name, group_id, is_income, hidden } }. Pick a category group from the searchable list (same groups as in Actual). Response includes data (new category id); the node also exposes categoryId on the output item for convenience.
Transaction: Create — category UX
Under Transaction: Create, Category controls how the category is chosen:
- Existing Category — same as before: pick a category (list or UUID).
- Create New Category — the node calls POST /categories with your name and group, reads the new id from the API response, then creates the transaction with that category. The execution output includes
categoryCreate(request/response and resolved id) next to the transactionrequest/ API response.
Debugging (logs)
This node uses n8n’s LoggerProxy from n8n-workflow (same approach as n8n’s logging docs): each outbound call logs at info (method, resource, URL with the sync id redacted as _syncId_), extra hints at debug, and warn if the request fails (HTTP status when present; 404 entries may include a short troubleshootingHint). You do not need to add /v1 manually when using a host-only Base URL — it is applied automatically.
Where to read logs: server stdout/stderr (Docker/Kubernetes logs) or the log file if you enable file output — not the workflow execution panel in the editor.
Environment variables (optional; defaults are usually enough until you need more detail):
| Variable | Typical value | Purpose |
|----------|-----------------|--------|
| N8N_LOG_LEVEL | info (default) | Use debug to include Logger.debug lines (credential-shape hints). |
| N8N_LOG_OUTPUT | console (default) | Use console,file and set N8N_LOG_FILE_LOCATION if you want a persistent log file. |
| N8N_LOG_FILE_LOCATION | e.g. /home/node/.n8n/logs/n8n.log | Path when N8N_LOG_OUTPUT includes file. |
After changing env vars, restart n8n.
Development
npm run build
npm run lint