A CLI tool that matches YNAB transactions to Amazon orders and annotates them with item details.
- Automatically matches YNAB transactions to Amazon orders by amount
- Generates detailed memos with item names, prices, and order numbers
- Supports dry-run mode to preview changes before applying
- Daemon mode with configurable scheduling (interval or time windows)
- Typed error handling with automatic retry on transient failures
- Notifications via Apprise (100+ services)
- Docker support for easy deployment
- Optional AI memo summarization with OpenAI
docker run --rm \
-e YNAB_API_KEY=your-key \
-e YNAB_BUDGET_ID=your-budget-id \
-e AMAZON_USER=your-email \
-e AMAZON_PASSWORD=your-password \
ghcr.io/bakerboy448/ynamazon:latestOr with docker-compose:
services:
ynamazon:
image: ghcr.io/bakerboy448/ynamazon:latest
environment:
- YNAB_API_KEY=${YNAB_API_KEY}
- YNAB_BUDGET_ID=${YNAB_BUDGET_ID}
- AMAZON_USER=${AMAZON_USER}
- AMAZON_PASSWORD=${AMAZON_PASSWORD}
volumes:
- ./config:/app/config:ro# Install uv if needed: https://github.com/astral-sh/uv
uv sync
# Run
uv run yna --helpCreate a .env file or set environment variables:
# Required
YNAB_API_KEY=your-ynab-api-key
YNAB_BUDGET_ID=your-budget-id
AMAZON_USER=your-amazon-email
AMAZON_PASSWORD=your-amazon-password
# Optional
AMAZON_OTP_SECRET_KEY=your-totp-secret # For automatic 2FA (TOTP secret from authenticator setup)
MATCH_EMPTY_MEMO=true # Match "Amazon" payee with empty memo (default: true)
AMAZON_FULL_DETAILS=true # Fetch item prices (slower, default: true)
AMAZON_DEBUG=false # Enable debug logging
YNAB_PAYEE_NAME_PROCESSING_COMPLETED=Amazon # Payee name for processed transactions
YNAB_APPROVED_STATUSES=["approved","unapproved"] # Which approval statuses to match (default: both)
AUTO_ACCEPT_DATE_MISMATCH=true # Auto-accept date mismatches without prompting (default: false)
DATE_MISMATCH_TOLERANCE_DAYS=2 # Allow date differences up to N days (default: 0 = exact match)
NON_INTERACTIVE=true # Skip all confirmation prompts (default: false, for daemon mode)Config loading order (later overrides earlier):
/app/config/.env(Docker).env(current directory)- Environment variables
# Default: match and update transactions interactively
yna ynamazon
# Preview changes without modifying anything
yna ynamazon --dry-run
# Process all transactions (including those with existing memos)
yna ynamazon --force --dry-run
# Limit lookback period (max 31 days due to Amazon API)
yna ynamazon --days 14
# Print YNAB transactions
yna print-ynab
# Print Amazon transactions
yna print-amazonRun as a long-lived daemon that syncs on a schedule:
# Run every 20 hours (default)
yna daemon
# Custom interval (min 12h, max 48h)
yna daemon --interval 24
# Use time windows for random scheduling (e.g., 6-8am and 6-8pm)
yna daemon --windows "6-8,18-20"
# Daemon with dry-run (preview only, no changes)
yna daemon --dry-runDaemon mode runs immediately on start, then at the configured interval or within time windows.
The daemon uses typed exceptions for intelligent error handling:
- Transient errors (network timeouts, 5xx responses) are retried up to 3 times with exponential backoff (5s, 10s, 20s)
- Fatal errors (auth failures, bad config) are reported immediately without retry
- All errors include partial sync progress in notifications when available
services:
ynamazon:
image: ghcr.io/bakerboy448/ynamazon:latest
command: ["yna", "daemon", "--interval", "20"]
environment:
- YNAB_API_KEY=${YNAB_API_KEY}
- YNAB_BUDGET_ID=${YNAB_BUDGET_ID}
- AMAZON_USER=${AMAZON_USER}
- AMAZON_PASSWORD=${AMAZON_PASSWORD}
- NON_INTERACTIVE=true
restart: unless-stoppedGet notified when syncs complete or fail using Apprise:
# Comma-separated Apprise URLs
APPRISE_URLS=discord://webhook_id/webhook_token,tgram://bot_token/chat_idApprise supports 100+ notification services including Discord, Telegram, Slack, Email, Pushover, and more. See the Apprise wiki for URL formats.
Notifications are sent for:
- Successful syncs with updates (match/update/skip counts)
- Transient failures after retry exhaustion (warning)
- Fatal failures requiring intervention (failure)
- Unexpected errors (failure)
Memos are formatted as: Item A ($XX.XX), Item B ($XX.XX) | Order #XXX-XXXXXXX-XXXXXXX
For partial orders (when Amazon splits shipments):
[Partial - order total $XX.XX] Item A, Item B | Order #XXX-XXXXXXX-XXXXXXX
- Create a payee named
Amazon(or your preferred name) - Create a rename rule to rename Amazon transactions to this payee
- The program will match transactions with empty memos and this payee
uv sync --extra aiSet in .env:
USE_AI_SUMMARIZATION=true
OPENAI_API_KEY=your-openai-api-keyIf your Amazon account has 2FA enabled, set AMAZON_OTP_SECRET_KEY to your TOTP secret:
- Go to Amazon > Account & Lists > Login & Security > Two-Step Verification
- Add a new authenticator app
- Click "Can't scan the barcode?" to reveal the secret key
- Use this secret key as
AMAZON_OTP_SECRET_KEY
The program will automatically generate OTP codes for login.
- Only supports amazon.com (US)
- Amazon API returns ~31 days of transaction history
- Relies on web scraping which may break with Amazon changes
# Install dev dependencies
uv sync --dev
# Run tests
uv run pytest -v
# Run pre-commit hooks
uv run pre-commit run --all-files
# Lint and format
uv run ruff check src/ tests/
uv run ruff format src/ tests/
# Type check
uv run pyright src/See CONTRIBUTING.md for detailed contribution guidelines.
MIT