Configuration
Every environment variable and admin-panel setting in Reception AI, with defaults, what each one actually does, and which ones are not used yet.
7 min readUpdated Oct 17, 2026Applies to Reception AI 1.0.0
On this page
Reception AI is configured in two places:
- Environment variables bootstrap the app: the database, the encryption key, sign-in secrets and OAuth app registrations. They are read when the process starts.
- Admin settings at
/admin/settings(the Configuration tab) hold everything an operator would expect to change without a redeploy: provider keys, branding, feature switches, billing rates and abuse limits.
Most admin settings can also be given as an environment variable of the same name, which acts as the fallback.
How a setting is resolved
For any key on the Configuration screen:
- If a value has been saved in the admin panel, it wins.
- If a value was saved and then cleared (saved empty), the setting is off. The environment is not consulted.
- If nothing was ever saved, the environment variable of the same name is used.
- Otherwise the built-in default applies.
The screen labels each value as Set here, From environment, Turned off or Not set. Changes take effect within about a minute, with no restart: each process caches settings for 60 seconds. Secret values are encrypted with CREDENTIAL_ENCRYPTION_KEY, shown masked, and every change is written to the audit log (for secrets, only "set" or "cleared", never the value). Only super-admins can open this screen.
Note
On/off switches currently display Off when the key has never been set, even though their default is on. Saving the switch once makes the display match.
Environment-only variables
These cannot be set from the admin panel.
Core
| Variable | Required | Default | What it does |
|---|---|---|---|
DATABASE_URL |
Production | Embedded in-memory PGLite | Postgres connection string. Without it, all data is lost on restart. Shown read-only on the Configuration screen. |
CREDENTIAL_ENCRYPTION_KEY |
With a database | Random per process when there is no database | 32 bytes as base64, base64url or 64 hex characters (openssl rand -base64 32). Encrypts connector credentials, phone-number credentials and secret settings with AES-256-GCM. With a database and no key, saving a credential fails. Shown read-only. |
BETTER_AUTH_SECRET |
Production | Random per process | Signs sessions, OAuth state and call-stream tokens. Without it, everyone is signed out on every restart. |
BETTER_AUTH_URL |
Recommended | Worked out per request | The public origin used for sign-in. When unset, requests are accepted for localhost and for the host in APP_URL. Set it to the same value as APP_URL in production. |
ADMIN_EMAILS |
For the first admin | None | Comma- or space-separated addresses that may become super-admins once verified. See First admin. |
JOBS_SECRET |
Recommended | None | Bearer token for /api/jobs/run. Without it, that endpoint only answers requests from the same machine. |
DEMO_MODE |
No | Off | true, 1, yes or on turns on the public showroom. See Demo mode. |
Server
| Variable | Default | What it does |
|---|---|---|
PORT |
3000 for the built server (the Docker image sets 8080); the dev server is always 8080 |
Listening port. NITRO_PORT is also accepted. |
HOST |
All interfaces | Listening address. NITRO_HOST is also accepted. |
NITRO_SSL_CERT, NITRO_SSL_KEY |
Unset (plain HTTP) | When both are set, the server speaks HTTPS itself. Each is a PEM string or a file path. |
VITE_AUTH_ENABLED |
Sign-in on | Development only. The exact value false disables sign-in when there is no database. With a database it refuses to run without sign-in. |
Sign-in and OAuth apps
| Variable | What it does |
|---|---|
VITE_GOOGLE_CLIENT_ID |
Google OAuth client ID for "Sign in with Google". Needed at build time (it is compiled into the browser bundle) and at runtime. |
GOOGLE_CLIENT_SECRET |
The matching secret. Google sign-in appears only when both are set. Redirect URI: <origin>/api/auth/callback/google. |
GOOGLE_CONNECTOR_CLIENT_ID, GOOGLE_CONNECTOR_CLIENT_SECRET |
A second Google client for the Gmail, Calendar and Sheets connectors. Falls back to the sign-in client. Redirect URI: <APP_URL>/api/connect/google/callback. |
GOOGLE_ENABLE_GMAIL_READ |
Exactly true adds the gmail.readonly scope so the Gmail connector can search the inbox. Google classes this scope as restricted. |
MICROSOFT_CLIENT_ID, MICROSOFT_CLIENT_SECRET |
Outlook connector OAuth. Redirect URI: <APP_URL>/api/connect/microsoft/callback. |
MICROSOFT_TENANT |
Tenant ID or domain for single-tenant apps. Default common. |
SALESFORCE_CLIENT_ID, SALESFORCE_CLIENT_SECRET |
Salesforce connector OAuth. Callback: <APP_URL>/api/connect/salesforce/callback. |
SALESFORCE_LOGIN_URL |
Default https://login.salesforce.com; use https://test.salesforce.com for sandboxes. |
ALLOW_PRIVATE_CONNECTOR_URLS |
Exactly true lets connector and MCP URLs point at private or loopback addresses. Leave it off on a multi-tenant install. |
Google sign-in and Google connectors are deliberately separate clients: the connector scopes need Google's verification review, and putting them on the sign-in client would block logins until that review completes. Connectors has the setup steps.
Admin settings
Grouped as they appear on the Configuration screen. Every key also accepts an environment variable of the same name as a fallback.
Branding
| Key | Default | What it does |
|---|---|---|
BRAND_NAME |
Reception AI |
Product name in the app shell, sign-in page, marketing site, browser tab and install manifest. |
SUPPORT_EMAIL |
Empty | Contact link on the sign-in page, the marketing footer and the plan enquiry screen. |
BRAND_TAGLINE |
Never miss a call again. |
Stored, but not displayed anywhere in 1.0.0. |
Site and search
| Key | Default | What it does |
|---|---|---|
SITE_TITLE |
The brand name | Page <title> and Open Graph title. |
SITE_DESCRIPTION |
Built-in description | Meta and Open Graph description. |
SITE_OG_IMAGE |
Empty | Social preview image URL. |
SITE_FAVICON |
/favicon.svg |
Favicon URL (served as SVG). |
SITE_NOINDEX |
Off | Asks search engines not to index the site. |
ANALYTICS_GA_ID |
Empty | Google Analytics measurement ID. |
ANALYTICS_PLAUSIBLE_DOMAIN |
Empty | Plausible Analytics domain. |
Legal
| Key | Default | What it does |
|---|---|---|
TERMS_URL |
Empty | Terms link in the marketing-site footer. |
PRIVACY_URL |
Empty | Privacy link in the marketing-site footer. |
COMPANY_NAME |
Brand name | Name in the footer copyright line. |
COMPANY_ADDRESS |
Empty | Not used in 1.0.0. |
Features
| Key | Default | What it does |
|---|---|---|
FEATURE_SIGNUPS |
On | Off closes public sign-up, enforced on the server. |
FEATURE_OUTBOUND |
On | Off refuses every outbound call and campaign. |
FEATURE_WIDGET |
On | Off stops website-widget chat and the homepage live voice demo. |
MAX_AGENTS_PER_WORKSPACE |
Empty | Not enforced in 1.0.0. Use plan limits instead. |
Billing rates
How many plan minutes each kind of usage costs. See Selling it as SaaS.
| Key | Default | Charged for |
|---|---|---|
RATE_VOICE_MINUTE |
1 |
Each minute of a live call |
RATE_PHONE_TURN |
0.25 |
Each exchange on the turn-based phone path |
RATE_TEXT_MESSAGE |
0.025 |
Each website-widget chat message |
Abuse limits
Fixed windows per minute or per day. A value of zero or less means "use the default".
| Key | Default | Limits |
|---|---|---|
LIMIT_WIDGET_IP |
12 per minute |
Widget messages from one visitor IP (the receptionist's owner is exempt) |
LIMIT_WIDGET_AGENT |
90 per minute |
Widget messages to one receptionist, all visitors combined |
LIMIT_WIDGET_WORKSPACE_DAY |
2000 per day |
Widget messages across one workspace |
LIMIT_FORM_IP |
6 per minute |
Public form submissions from one IP |
LIMIT_FORM_FORM |
120 per minute |
Submissions to one form |
The homepage voice demo has its own fixed limits (2 sessions per minute and 6 per day per visitor, 30 per day in total). They are not configurable.
AI
| Key | Secret | What it does |
|---|---|---|
OPENAI_API_KEY |
Yes | Live phone calls, the homepage voice demo and OpenAI-voice speech. |
REALTIME_MODEL |
No | gpt-realtime-2.1 (the default when blank) or gpt-realtime-2.1-mini. See AI models. |
OPENAI_PROJECT_ID |
No | Your OpenAI project ID, used for SIP trunking. Despite being labelled optional, Plivo calls also require it in 1.0.0. |
OPENAI_WEBHOOK_SECRET |
Yes | Verifies OpenAI's SIP call webhooks (whsec_…). |
XAI_API_KEY |
Yes | Chat, the widget, transcription, voice previews, rehearsals, the AI builder and the turn-based phone path. Required for all of them. |
Telephony
| Key | Secret | What it does |
|---|---|---|
PLIVO_AUTH_TOKEN |
Yes | Verifies Plivo webhook signatures. Every Plivo webhook is rejected without it. |
PLIVO_AUTH_ID |
No | Not used in 1.0.0: Plivo numbers use the Auth ID entered when the number is imported. |
| Key | Default | What it does |
|---|---|---|
SMTP_HOST |
Empty (mail off) | Mail server. |
SMTP_PORT |
587 |
465 uses implicit TLS; any other port upgrades with STARTTLS when the server offers it. |
SMTP_USER, SMTP_PASS |
Empty | Credentials. Sent only when a user is set. |
SMTP_FROM |
SMTP_USER |
Sender address. |
Email is used for one thing only in 1.0.0: the first admin's confirmation link. Without SMTP, that link is printed in the server log instead.
Payments
| Key | Secret | What it does |
|---|---|---|
STRIPE_SECRET_KEY |
Yes | Checkout and the customer portal. |
STRIPE_WEBHOOK_SECRET |
Yes | Verifies POST /api/billing/stripe. |
PAYPAL_CLIENT_ID, PAYPAL_CLIENT_SECRET, PAYPAL_MODE |
Mixed | Shown on the screen but not used in 1.0.0. PayPal checkout is not implemented. |
Platform
| Key | Secret | What it does |
|---|---|---|
APP_URL |
No | Your public HTTPS origin. Builds carrier webhook and stream URLs, is what carrier signatures are checked against, and is where Stripe returns customers. Also set it in the environment. |
QSTASH_TOKEN |
Yes | Optional Upstash QStash integration. Not needed: the built server drains the job queue every minute on its own. Its on-screen help ("campaigns do not send without it") is out of date. |
DATABASE_URL, CREDENTIAL_ENCRYPTION_KEY |
Yes | Shown locked; environment only. |
Settings that do nothing yet
For clarity, these appear on the Configuration screen but have no effect in version 1.0.0:
PAYPAL_CLIENT_ID,PAYPAL_CLIENT_SECRET,PAYPAL_MODEMAX_AGENTS_PER_WORKSPACECOMPANY_ADDRESSPLIVO_AUTH_IDBRAND_TAGLINE(saved, not displayed)
A complete production example
# --- Environment only ---
DATABASE_URL=postgres://user:password@db-host:5432/receptionai
CREDENTIAL_ENCRYPTION_KEY=base64-32-bytes
BETTER_AUTH_SECRET=base64-32-bytes
BETTER_AUTH_URL=https://reception.example.com
JOBS_SECRET=random-string
ADMIN_EMAILS=you@example.com
PORT=8080
# Google sign-in (also pass VITE_GOOGLE_CLIENT_ID as a build argument)
VITE_GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
# --- Admin settings (environment fallback; can move to the admin panel) ---
APP_URL=https://reception.example.com
OPENAI_API_KEY=sk-...
XAI_API_KEY=xai-...
REALTIME_MODEL=
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USER=postmaster@example.com
SMTP_PASS=...
SMTP_FROM=Reception AI <no-reply@example.com>
STRIPE_SECRET_KEY=sk_live_...
STRIPE_WEBHOOK_SECRET=whsec_...