Skip to content

Environment variables

Grouped by concern. Secrets are marked; never put a marked variable in a frontend bundle, a commit, or a log line.

.env on the production VM is never overwritten by a deploy

deploy.gcp.sh excludes .env from the rsync. New variables must be added on the VM manually, then the process restarted. Forgetting this is the most common cause of "the code deployed but the feature does not work".

bz-backend — core

VariablePurpose
PORTListen port (5000)
NODE_ENVproduction on the VM
MONGO_URI / MONGO_URLMongoDB Atlas connection string
MONGO_DB_NAME, MONGO_TOKEN_DB_NAMEDatabase names
REDIS_URLRedis connection
DISABLE_REDISForce the in-memory fallback
CRONSet to false to disable every cron. Anything else enables them
AGENT_URLWhere bz-agent lives (http://localhost:4000)
FRONTEND_URL, ADMIN_FRONTEND_URL, APP_BASE_URL, CALLBACK_BASE_URLLink and redirect bases
JWT_SECRET, JWT_ADMIN_SECRET 🔒Token signing
ADMIN_SECRET 🔒Admin gate
ENCRYPTION_KEY, ENCRYPTION_MASTER_KEY 🔒At-rest encryption
SENTRY_DSNError reporting
ENABLE_MONITORING, LOG_TARGET, LOG_TARGETSObservability

CRON=false in a local .env is strongly recommended

Local dev points at production Atlas by default. With crons enabled, your laptop becomes a second CSIP and Autopilot executor competing with production — submitting duplicate transactions with the same keys. See local development.

Signing keys 🔒

VariableAddressRole
TX_SIGNER0x75a8b522FC3195e3a3570F11f111AC89c0D35975Signs relayer meta-transactions on all chains except Polygon; also the relayer owner
POL_TX_SIGNERPolygon-specific signer (chain 137)
PRIVATE_KEY_EXECUTOR0x5935745431D1385ae1a9CE2644fb5f5d1f140459CSIP + Autopilot executor; also DCA vault owner
BACKEND_PRIVATE_KEY0x2Ed05570214f6C0F7612B580aB37C163076e0162Autopilot vault owner and deployer
BACKEND_SIGNER_PRIVATE_KEYBackend attestations
AUTOPILOT_EXECUTOR_KEYAutopilot-specific executor override
DCA_OWNER_KEYUsed by the DCA upgrade script (hardhat network arbitrum_dca_owner)
PRIVATE_KEY, PRIVATE_KEY1Legacy deploy keys
PRESALE_MASTER_SEED 🔒Presale wallet derivation
CLIPPERS_PAYOUT_PRIVATE_KEY 🔒Creator payouts
PRIVATE_KEY_CHANGELLY, CHANGELLY_PRIVATE_KEY 🔒Changelly request signing

Contract addresses

VariableDefault
AUTOPILOT_ADDRESS_ARBITRUM0x689AaEc7E3012d84226e7c5F4DEeFdC01C86d23e
AUTOPILOT_ADDRESS_BASE(empty — cron skips)
AUTOPILOT_ADDRESS_ROBINHOOD0x4dE7CD522f1715b2a48F3ad6612924841d450A0F
TREASURY_ADDRESS, TREASURY_WALLET
NFT_STAKING_ADDRESS, BZ_NFT_STAKING_ADDRESS
MARKETPLACE_CONTRACT_ADDRESS, MARKETPLACE_NFT_ADDRESS
POLYGON_CLAIM_CONTRACT, QUBETICS_CLAIM_CONTRACT, MONAD_CLAIM_CONTRACT_ADDRESS, MONAD_CHAIN_ID
{ARBITRUM,BASE,BSC,LINEA}_DEPOSIT_CONTRACT
{ARBITRUM,BASE,BSC,LINEA}_{USDC,USDT,DAI}_ADDRESSStablecoin addresses per chain

RPC URLs

VariableChain
DEFAULT_RPC_URLFallback
ETHEREUM_RPC_URL1
ARBITRUM_RPC_URL42161
ARBITRUM_SEPOLIA_RPC_URL421614
BASE_RPC_URL8453
BSC_RPC_URL, BSC_TESTNET_RPC_URL56
POLYGON_RPC_URL137
QUBETICS_RPC_URLQubetics

Most chains get their RPC from Mongo, not from env

Network.metamask.rpcUrls[0] is the source for signing, the fee summary and vault interaction. These env vars cover the chains where automation and deployment scripts need a direct URL. A dead RPC in the Mongo record takes that chain down silently.

Aggregator / provider keys 🔒

VariableProvider
ONE_INCH_KEY1inch
OPEN_OCEAN_API_KEY, OPEN_OCEAN_REFERREROpenOcean — also supplies gas prices
UNIZEN_API_KEYUnizen
ODOS_API_KEYOdos
OKX_API_KEY, OKX_SECRET_KEY, OKX_PASSPHRASE, OKX_PROJECT_ID, OKX_API_URLOKX
UNISWAP_API_KEY, UNISWAP_API_URLUniswap
RELAY_API_KEYRelay
RANGO_API_KEYRango
ACROSS_API_KEY, ACROSS_INTEGRATOR_IDAcross
NEAR_1CLICK_API_KEYNear 1Click
GASZIP_API_URLGasZip
RHINO_API_KEY, RHINO_API_URLRhinoFi
HOUDINI_API_KEYHoudini
CHANGE_NOW_API_KEYChangeNow
SWAP_SDK_BASE_URLOverride the SDK's baseApiUrl
KIMA_BACKEND_URLDefaults to https://kima.blazpay.com

Squid's integrator id (blazpay-db534a27-fefd-4504-b5bd-a7e6407bd656) and 1inch's referrer (0x5222…1D35) are hardcoded in their controllers.

Fiat ramp keys 🔒

VariableProvider
SECRET_KEY_ONRAMPOnRamp.money
SECRET_KEY_ALCHEMYAlchemyPay
CHANGELLY_PRIVATE_KEY, PRIVATE_KEY_CHANGELLYChangelly

Transak and MoonPay use public catalogue endpoints; check their controllers before assuming no key is needed.

Explorer / data APIs 🔒

VariablePurpose
ETHERSCAN_API_KEYEtherscan v2 unified — one key, all chains. Used by the auditor, token safety, approval scan and wallet card
ARBISCAN_API_KEY, BSCSCAN_API_KEY, POLYGONSCAN_API_KEY, BASESCAN_API_KEY, OPSCAN_API_KEYPer-chain verification
COINMARKETCAP_API_KEY, _2, _3Autopilot price series — three keys for rate-limit headroom
MORALIS_API_KEY, _2, _3Balance lookups
OPENSEA_KEYNFT metadata

CoinGecko (fee summary) and Zerion (portfolio) are called without a key in the current code.

Model providers 🔒

Blazpay's intent engine addresses models by tier, not by vendor — see agent graph. These variables are the credentials and overrides behind those tiers. The variable names are what they are in code; the prose in these docs deliberately refers to roles instead.

VariableRole
OPENAI_API_KEYCredential for the audit and token-safety models
GROQ_API_KEY, GROQ_MODELCredential + model for Autopilot policy drafting
AUTOPILOT_LLM_MODELModel override for Autopilot drafting
LLM_BASE_URLPoint a tier at a self-hosted or alternate endpoint
GOOGLE_SERVICE_ACCOUNTManaged-provider service account
RASA_ENDPOINT, RASA_TOKENSelf-hosted Rasa NLU service (legacy swap-ai chat path)
WIT_TOKENwit.ai NLU (legacy)
STREAM_TOKEN_DELAY_MSArtificial SSE token pacing

Repointing a tier

LLM_BASE_URL plus the LLM_MODEL_* overrides are the seam for moving a tier onto self-hosted inference without touching bz-agent. The Rasa service is already self-hosted and is the precedent for running NLU in-house.

bz-agent

VariablePurpose
LLM_OPENAI_API_KEY 🔒 (falls back to OPENAI_API_KEY)Credential for the extraction tier
LLM_MODEL_EXTRACTIONModel serving the extraction tier
LLM_MODEL_CONVERSATIONModel serving the conversation tier
LLM_MODEL_COMPLEXModel serving the complex tier
LLM_GOOGLE_PROJECT_IDManaged conversation provider — project
LLM_GOOGLE_CLIENT_EMAILManaged conversation provider — service account
LLM_GOOGLE_PRIVATE_KEY 🔒PEM with \n escapes
LLM_GOOGLE_PRIVATE_KEY_ID, LLM_GOOGLE_CLIENT_IDOptional

Plus Mongo, PostgreSQL (PGVector) and Redis connection strings.

All three Google variables or none

getConversationLLM() requires LLM_GOOGLE_PROJECT_ID, LLM_GOOGLE_CLIENT_EMAIL and LLM_GOOGLE_PRIVATE_KEY. With any one missing it silently falls back to the extraction model instead of the conversation tier. Answer quality degrades with no error.

Storage & media 🔒

VariableService
AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION, AWS_BUCKET_NAMES3
AWS_KEY_ID_KMSKMS key for Orderly ed25519 encryption
AWS_SES_ACCESS_KEY_ID, AWS_SES_SECRET_ACCESS_KEY, AWS_SES_REGION, AWS_SES_ENDPOINT, AWS_SES_FROM_ADDRESSEmail
CLOUDINARY_CLOUD_NAME, CLOUDINARY_API_KEY, CLOUDINARY_API_SECRETImages
R2_ACCOUNT_ID, R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY, R2_BUCKET_NAME, R2_PUBLIC_URL, R2_MEDIA_BUCKET_NAME, R2_MEDIA_PUBLIC_URLCloudflare R2
PINATA_JWTIPFS pinning
NFT_IMAGE_BASE_URL, NFT_METADATA_APINFT assets

Messaging & community 🔒

VariableService
TELEGRAM_BOT, TELEGRAM_BOT_TOKEN, TELEGRAM_ALERTS_CHAT_ID, COMMUNICATION_TELEGRAM_BOT_TOKENTelegram
DISCORD_BOT_TOKEN, DISCORD_CLIENT_ID, DISCORD_CLIENT_SECRET, DISCORD_2X_BOOSTER_ROLE_IDDiscord
EMAIL_USER, EMAIL_PASSWORD, ZOHO_EMAIL_USER, ZOHO_EMAIL_PASSWORDSMTP
GALXE_API_KEY, ZEALY_API_KEY, INTRACT_API_KEY, SMM_API_KEYQuest platforms
APIFY_API_TOKEN, APIFY_ACTOR_IDScraping
BOLT_API_KEY

Feature flags & tuning

VariableEffect
AUDIT_PUBLIC_BASE_URLShare-link prefix. Defaults to https://audit.blazpay.ai
DISABLE_BRIDGE_STATUS_CRONDisable just that cron
CSP_ENABLEDContent-Security-Policy
STAKE_RETRYStaking retry behaviour
USE_LEGACY_REWARDSRewards path selection
REWARDS_HUB_FORCE_PROXY, REWARDS_HUB_PROXY_GROUPS, REWARDS_HUB_PROXY_PREFIXES, REWARDS_ADMIN_FORCE_PROXY, REWARDS_ADMIN_PROXY_GROUPS, REWARDS_ADMIN_NATIVE_WRITE_GROUPS, THREADS_FORCE_PROXY, THREADS_PROXY_GROUPSMicroservice routing toggles
POKER_PLATFORM_FEE_ENABLED, POKER_PLATFORM_FEE_BPS, POKER_FEE_TO, POKER_ESCROW_TOPoker economics
PREDICTION_MIN_STAKE, PREDICTION_MAX_STAKE, PREDICTION_DAILY_LIMIT, PREDICTION_LOCK_BEFORE_END_SECONDS, PREDICTION_{MIN,MAX}_{UP,DOWN}_POOL, PREDICTION_SEED_ENABLED, PREDICTION_FAKE_PARTICIPANTSPrediction market tuning
BINANCE_PROXY_URLPrice proxy
ARB_GAMES_KEYGames

PREDICTION_FAKE_PARTICIPANTS and PREDICTION_SEED_ENABLED

These seed synthetic participants into prediction markets. Whatever the product rationale, know that they exist before making claims about market depth.

defi-dex (frontend)

Only VITE_-prefixed variables reach the bundle. Never put a secret here.

VariablePurpose
VITE_SITEdefi | ai — picks the app shell. Inlined, so Rollup tree-shakes the other
VITE_API_URLAPI base. Falls back to http://localhost:5000/api on localhost, https://api.blazpay.com/api otherwise
VITE_GA_MEASUREMENT_IDGA4. Analytics is a no-op without it

.env.ai holds the AI-site build's values; netlify.toml and netlify.ai.toml hold the per-site production values.

System settings (not env)

Runtime-tunable values live in Mongo, not the environment:

js
await SystemSetting.getValue('audit_free_limit_per_wallet')     // default 3
await SystemSetting.setValue('audit_free_limit_per_wallet', 5)
await SystemSetting.getByCategory('limits')

Categories: bridge, security, network, fees, limits, general. Four Autopilot settings are seeded by scripts/seed-autopilot-settings.js.

Prefer a system setting over a new env var

Changing an env var needs an SSH session and a process restart. Changing a system setting is a database write. Use env vars for secrets and infrastructure; use system settings for limits and flags.

Auditing your environment

bash
# Which env vars does the code actually read?
grep -rhoE 'process\.env\.[A-Z0-9_]+' --include='*.js' \
  controllers services utils middleware v1 routes index.js \
  | sed 's/process\.env\.//' | sort -u

Run it from bz-backend. Note that archive/, new-backend/ and microservices-backend/ are not mounted, so exclude them — they contribute variables nothing reads.

Internal + developer documentation. Usage figures are point-in-time snapshots — re-verify before publishing them.