Stream Actual Budget changes over Server-Sent Events (SSE) and WebSockets by diffing consecutive syncs. Downstream services can subscribe for near real-time updates without polling.
/eventsSSE endpoint with resumableLast-Event-IDand rich filtering./wsWebSocket endpoint for bidirectional filter updates and ping/pong keepalive.- Optional
/nudgeendpoint to trigger an immediate scan. - Docker image with built-in health check and persistent budget cache volume.
- Node.js ≥ 22.
- Actual Budget server credentials (
ACTUAL_SERVER_URL,ACTUAL_PASSWORD,ACTUAL_SYNC_ID). - Suitable lookback window (
LOOKBACK_DAYS) for your dataset and import cadence.
git clone https://github.com/rjlee/actual-events.git
cd actual-events
npm installOptional git hooks:
npm run preparecp .env.example .env
docker build -t actual-events .
mkdir -p data/budget
docker run -d --env-file .env \
-p 4000:3000 \
-v "$(pwd)/data:/app/data" \
actual-eventsPublished images live at ghcr.io/rjlee/actual-events:<tag> (see Image tags).
If you prefer Docker Compose, docker-compose.yml exposes the API directly on
HTTP_PORT.
.env– primary configuration, copy from.env.example.config.yaml/config.yml/config.json– optional defaults, copy fromconfig.example.yaml.
Precedence: CLI flags > environment variables > config file.
| Setting | Description | Default |
|---|---|---|
BUDGET_DIR |
Budget cache directory | ./data/budget |
LOOKBACK_DAYS |
Historical window to diff for changes | 60 |
SCAN_INTERVAL_MS |
Periodic scan interval in milliseconds | 15000 |
HTTP_PORT |
HTTP listen port | 3000 |
LOG_LEVEL |
Pino log level | info |
EVENTS_AUTH_TOKEN |
Bearer token required for SSE/WS/nudge endpoints | unset |
CORS_ORIGINS |
Comma-separated CORS allowlist (* to allow all) |
* |
- Foreground server:
npm start - Daemonised server:
npm start -- --daemonize --pid-file ./data/events.pid --log-file ./data/events.log
GET /events– SSE stream with filters (entities,events,accounts,payees,categories,categoryGroups,rules) and optionaluseRegex=true.GET /ws– WebSocket stream; send{ "type": "filter", ... }to update subscriptions.POST /nudge– Trigger an immediate diff scan (requires auth whenEVENTS_AUTH_TOKENset).
See EVENTS.md for payload reference.
docker run --rm --env-file .env \
-p 4000:3000 \
-v "$(pwd)/data:/app/data" \
ghcr.io/rjlee/actual-events:latestnpm test
npm run lint
npm run lint:fix
npm run format
npm run format:checkghcr.io/rjlee/actual-events:<semver>– pinned to a specific@actual-app/apirelease.ghcr.io/rjlee/actual-events:latest– highest supported API version.
See rjlee/actual-auto-ci for tagging policy and release automation.
MIT © contributors.