Skip to content

Configuration

Copy .env.example to .env and set what you use. Features whose variables are unset stay off and say so, rather than failing at startup. Never commit a real .env.

Variable Purpose
DATABASE_URL Postgres connection (local default postgres://payvy:payvy@127.0.0.1:5446/payvy)
PAYVY_BIND Listen address (local default 127.0.0.1:7430)
PAYVY_API_KEY API key, at least 32 characters: openssl rand -hex 32
PAYVY_PUBLIC_URL Public URL of the web app; sign-in links point here
Variable Purpose
PAYVY_S3_ENDPOINT, PAYVY_S3_BUCKET, PAYVY_S3_REGION Store location (R2, B2, S3, Garage, SeaweedFS…)
PAYVY_S3_ACCESS_KEY, PAYVY_S3_SECRET_KEY Store credentials
PAYVY_S3_PATH_STYLE Path-style addressing (needed by most self-run stores)
PAYVY_S3_CREATE_BUCKET Create the bucket at startup (local stores only)

Without storage, document commands say storage isn’t set up.

Variable Purpose
PAYVY_INBOUND_DOMAIN e.g. in.example.com
PAYVY_INBOUND_SECRET At least 32 characters; the email worker signs with it

Leave unset to turn intake off. See Bills by email.

Variable Purpose
PAYVY_EXTRACT_PROVIDER anthropic or openai-compatible
PAYVY_EXTRACT_API_KEY Provider key (not needed for a local model)
PAYVY_EXTRACT_MODEL Model name (required for openai-compatible; Claude default claude-opus-5-5)
PAYVY_EXTRACT_BASE_URL Provider endpoint, e.g. http://127.0.0.1:11434/v1 for Ollama
PAYVY_EXTRACT_AUTO Read new inbox documents in the background (default on)
Variable Purpose
PAYVY_SECRETS_KEY 64 hex characters (openssl rand -hex 32). Seals bank tokens. Losing it means reconnecting every bank.

One sender: Cloudflare Email Service (PAYVY_CLOUDFLARE_ACCOUNT_ID, PAYVY_CLOUDFLARE_EMAIL_TOKEN, PAYVY_MAIL_FROM), or Amazon SES (PAYVY_SES_REGION, PAYVY_SES_ACCESS_KEY_ID, PAYVY_SES_SECRET_ACCESS_KEY, with the From domain verified in SES). With no sender configured, links are written to the server log — fine for local use.

Tests use the separate PAYVY_TEST_* variables from .env.example.