AnswerLoopsAnswerLoops Docs
Reference

Environment Variables

Complete reference for every environment variable recognised by AnswerLoops.

All variables are set in your .env file (local) or in your hosting provider's environment configuration (production). Variables marked Required must be present or the app will refuse to start.

AnswerLoops uses Auth.js v5. The correct variable names are AUTH_SECRET and AUTH_URLnot NEXTAUTH_SECRET / NEXTAUTH_URL. If you are migrating from an older deployment, rename them.

Core (required)

VariableDescription
DATABASE_URLPostgreSQL connection string, e.g. postgresql://user:pass@host:5432/dbname
DIRECT_DATABASE_URLNon-pooled connection string for LISTEN/NOTIFY only. Required whenever DATABASE_URL is a pooled connection (Neon -pooler, PgBouncer, etc.) — falls back to DATABASE_URL otherwise
AUTH_SECRETRandom 32-byte secret used to sign Auth.js v5 session tokens. Generate with openssl rand -hex 32
AUTH_URLFull public URL of your deployment, e.g. https://answerloops.com. Used by Auth.js for OAuth callbacks
ENCRYPTION_KEY32-byte hex key used to encrypt stored API keys at rest. Generate with openssl rand -hex 32

Networking

VariableDescription
TRUST_PROXY_HOPSNumber of proxies between the public internet and the app. Defaults to 1. Rate limiters resolve the client IP by counting this many entries in from the right of x-forwarded-for, so a caller-supplied prefix on that header can't be used to mint a fresh bucket per request. Set to 2 for Cloudflare in front of a platform load balancer. cf-connecting-ip takes precedence when present
ORIGIN_VERIFY_SECRETOptional. When set, every public pre-auth POST route (/api/mcp, /api/agent/*, /api/widget/chat) rejects any request missing a matching x-origin-verify header — without it, the proxy-supplied client-IP header can be spoofed by hitting the origin directly instead of through your edge proxy. Requires a matching rule on your CDN/edge proxy; see the self-hosting guide

Multi-domain

VariableDescription
NEXT_PUBLIC_APP_URLOptional. Base URL of a dedicated dashboard subdomain (e.g. https://app.example.com) that shares the same deployment as your root domain. When set, marketing-page CTAs link there instead of a relative /dashboard path. Unset by default — most deployments serve everything from one domain
AUTH_COOKIE_DOMAINOptional. Shares the Auth.js session cookie across every subdomain of your apex (e.g. .example.com). Required alongside NEXT_PUBLIC_APP_URL, since a session cookie is host-only by default — without it, a user signed in on the root domain appears logged out on the app subdomain

OAuth providers

At least one OAuth provider must be configured so users can sign in.

VariableDescription
AUTH_GITHUB_IDGitHub OAuth App client ID
AUTH_GITHUB_SECRETGitHub OAuth App client secret
AUTH_DISCORD_IDDiscord OAuth2 client ID
AUTH_DISCORD_SECRETDiscord OAuth2 client secret
AUTH_GOOGLE_IDGoogle OAuth client ID
AUTH_GOOGLE_SECRETGoogle OAuth client secret

Callback URLs to register with each provider:

  • GitHub: https://<your-domain>/api/auth/callback/github
  • Discord: https://<your-domain>/api/auth/callback/discord
  • Google: https://<your-domain>/api/auth/callback/google

AI providers

These are platform-wide defaults. Individual orgs can override the AI model in Settings → AI Model.

VariableDescription
OPENAI_API_KEYOpenAI API key — enables GPT models and OpenAI embeddings
ANTHROPIC_API_KEYAnthropic API key — enables Claude models
GOOGLE_GENERATIVE_AI_API_KEYGoogle AI API key — enables Gemini models
GROQ_API_KEYGroq API key — enables fast open-weight model inference
MISTRAL_API_KEYMistral API key — enables Mistral models

At least one AI provider key is strongly recommended. Without one, AI draft replies are disabled and KB search falls back to keyword matching.

Discord

VariableDescription
DISCORD_TOKENBot token from the Discord Developer Portal. Required on both the app service (for the channel picker UI) and the bot service
DISCORD_CLIENT_IDDiscord application client ID. Must be from the same application as DISCORD_TOKEN
DISCORD_CLIENT_SECRETDiscord application client secret (used for OAuth)
DISCORD_APPLICATION_IDDiscord application ID (same value as DISCORD_CLIENT_ID in most setups)
DISCORD_GUILD_IDID of the Discord server to monitor
BOT_SECRETShared secret between the bot and the app for authenticating ingest requests
BOT_TARGET_URLBase URL the bot posts ingested messages to, e.g. https://answerloops.com — no trailing slash

Slack

VariableDescription
SLACK_CLIENT_IDSlack app client ID
SLACK_CLIENT_SECRETSlack app client secret
SLACK_SIGNING_SECRETUsed to verify that incoming Slack events are genuine
SLACK_POLL_INTERVAL_SECONDSHow often (in seconds) the app polls Slack for new messages. Defaults to 60

Google Chat

VariableDescription
GOOGLE_CHAT_SERVICE_ACCOUNT_JSONFull service-account JSON key, as a single-line string. Authenticates outgoing replies to the Chat API.
GOOGLE_CHAT_ENDPOINT_URLPublic HTTP endpoint URL for the Chat app's connection settings. Must exactly match what's configured in Google Cloud — used to verify incoming request tokens.

GitHub

VariableDescription
GITHUB_APP_IDNumeric ID of your GitHub App
GITHUB_APP_PRIVATE_KEYPEM-encoded private key generated in the GitHub App settings
GITHUB_WEBHOOK_SECRETSecret used to verify GitHub webhook payloads. Generate with openssl rand -hex 32 — paste without trailing newline
GITHUB_APP_SLUGURL slug for your GitHub App, e.g. answerloops

Telegram

VariableDescription
TELEGRAM_BOT_TOKENBot token from @BotFather on Telegram

Resend (email)

VariableDescription
RESEND_API_KEYResend API key — used for both outbound transactional email and the email ingest channel
RESEND_FROMDefault sender address for transactional emails, e.g. [email protected]
RESEND_WAITLIST_FROMSender address for waitlist emails (can be the same as RESEND_FROM)
RESEND_WEBHOOK_SECRETSvix signing secret (whsec_...) for Resend's inbound email webhook — required for the platform-hosted (zero-setup) email channel
EMAIL_INBOUND_DOMAINDomain used when generating platform-hosted inbound addresses, e.g. inbox.answerloops.app (optional — has a default)

Firecrawl

VariableDescription
FIRECRAWL_API_KEYFirecrawl API key — required for KB URL crawl imports

Web Push (VAPID)

VariableDescription
VAPID_PUBLIC_KEYVAPID public key for browser push notifications
VAPID_PRIVATE_KEYVAPID private key
VAPID_EMAILContact email included in VAPID headers, e.g. mailto:[email protected]

Generate a VAPID key pair with:

npx web-push generate-vapid-keys

Billing / deployment mode

VariableDescription
DEPLOYMENT_MODESet to cloud only on AnswerLoops' own managed SaaS deployment. Determines whether plan-tier feature gating (Discord/Slack integrations, CSAT scoring, simulation, knowledge gap dashboard, custom AI model config) applies at all. Any other value, or unset, means self-hosted: unmetered, every feature unlocked, no Stripe required
STRIPE_SECRET_KEYStripe secret API key. Required when DEPLOYMENT_MODE=cloud — its absence there is treated as a misconfiguration (billing shows an error state) rather than falling back to self-hosted/unlimited
STRIPE_WEBHOOK_SECRETSigning secret for the Stripe webhook endpoint (/api/billing/webhook), used to verify subscription lifecycle events
STRIPE_PRICE_PRO / STRIPE_PRICE_SCALE / STRIPE_PRICE_ENTERPRISEStripe Price IDs for each paid plan's checkout session

DEPLOYMENT_MODE was introduced to stop deployment type from being inferred from whether STRIPE_SECRET_KEY happened to be set — a missing or rotated key on the cloud deployment used to silently degrade every paying org to unmetered/unlimited instead of surfacing as a misconfiguration.

Access control

VariableDescription
ALLOWED_EMAILSComma-separated list of email addresses permitted to sign in. When set, only these addresses can log in — all others are rejected. Used during waitlist / private-beta mode. Leave unset to allow any authenticated user

On this page