Options and settings
Every option that exists in the code, its default and its state on Nov 3, 2026. See also feature-flags.md. Values shown as <…> are placeholders: never put real secrets in docs, tickets or chat.
1. bestdealon.app environment
| Variable | Default | Current | Notes |
|---|---|---|---|
APP_URL | http://localhost:8080 | https://bestdealon.app | Used in links and canonicals |
APP_ENV | production | default | |
ADMIN_EMAILS | empty | set | Comma list; these accounts get the admin role |
INDEXING | off | on | Search-engine indexing of public pages |
NOINDEX_PHONES | empty | not set | Listings kept out of search |
LEGAL_PAGES | off | on | /privacy, /terms, SMS consent box |
CALL_VERIFY | off | on | off / dryrun / on |
INBOUND_CLAIM | off | off | Claims offer on inbound calls |
CALLER_LOOKUP | off | on | Caller-profile endpoint |
PHONE_VERIFY_SMS | off | off | SMS verification codes |
PHONE_BOT_URL | https://callbots-bdo.onrender.com | default | Must be https (or localhost) |
CALLBOT_SHARED_SECRET | empty | set | HMAC secret; callbot API returns 503 without it |
RESEND_API_KEY, MAIL_FROM | empty, Best Deal On <no-reply@bestdealon.app> | set | Mail transport |
MAIL_ALLOWLIST | empty = anyone | set | QA guard |
TWILIO_* | empty | set | Verify service, API key, numbers |
STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, STRIPE_PRICE_ID | empty | not set | Billing (test mode only) |
API_WRITES_PER_HOUR | 60 | default | Sync API write limit per token |
CORS_ORIGINS | empty | set | Extra origins for the extension |
One-off boot hooks (set for one deploy, then delete): SEED_DEMO, SET_BUSINESS_CITY, FIX_LISTING_CONTACT, REMOVE_QXT_BUTTON, UPDATE_BIZINATOR_LINKS, CALLER_DIAG (read-only), ATTACH_OWNER_1188, GRANT_ADMIN_EMAIL, PURGE_E2E_USERS.
# Render → bestdealon.app → Environment (example values)
CALL_VERIFY=dryrun # test without dialling
CALLER_LOOKUP=on
CALLBOT_SHARED_SECRET=<shared-secret-from-the-vault>Admin settings (/admin/settings, stored in the database)
| Setting | Effect |
|---|---|
Email via Resend (mail_resend) | Turns on all site email; turning it on sends the admin a test email first |
Magic link (magic_link) | Enables "email me a sign-in link" |
2. callbots-bdo tenant file (deploy/bestdealon/tenants/bestdealon.json)
| Key | Default | Best Deal On | Meaning |
|---|---|---|---|
id, name, numbers | required | bestdealon, "Best Deal On", +17276320002 | Slug, display name, E.164 numbers |
voice | eve | eve | Grok Voice voice |
disclosure | "Hi, you have reached {name}. This call may be recorded…" | custom | First line for new callers |
hours | — | set | tz, open, close, days |
link_allowlist | required | set | Only these domains may be sent |
blocked_topics | [] | — | Topics to refuse |
approval_mode | true | — | Owner approval for sensitive tools |
order_lookup_enabled | false | false | Order status tool |
max_call_seconds | 900 | default | Hard call limit |
sms_enabled | — | false | Texting |
email_enabled | — | set | Email links/summaries |
take_message | — | {enabled:true, record_audio:false, deliver:"email"} | Leave-a-message |
known_callers | none | none | E.164 → {name, role?, greeting?} |
returning_caller_greeting | on unless false | true | Welcome-back greeting |
returning_caller_include_unconfirmed | false | true | Match unconfirmed contacts |
bdo_caller_lookup | false | true | Site lookup (only allowed for bestdealon) |
callback_offer | false | true | Call-back-or-email offer |
welcome_back | built-in text | set | Must contain {name}, one line, ≤200 chars |
brand | RF Safe wording | Best Deal On | Brand swap for shared prompts |
secrets | — | env:BDO_* refs | References only, never values |
payments_enabled | — | never | Rejected by validation |
{
"id": "bestdealon",
"numbers": ["+17276320002"],
"voice": "eve",
"sms_enabled": false,
"take_message": { "enabled": true, "record_audio": false, "deliver": "email" },
"returning_caller_greeting": true,
"returning_caller_include_unconfirmed": true,
"bdo_caller_lookup": true,
"callback_offer": true,
"welcome_back": "Welcome back{name}! This is the Best Deal On AI assistant. How can I help?",
"secrets": { "xai_webhook_secret": "env:BDO_XAI_WEBHOOK_SECRET", "twilio_webhook_key": "env:BDO_TWILIO_WEBHOOK_KEY" }
}callbots-bdo env: BDO_VERIFY_CALLS (off/dryrun/live; live), BDO_SITE_URL, BDO_CALLBOT_SHARED_SECRET, BDO_TWILIO_*, BDO_XAI_WEBHOOK_SECRET, TENANTS_DIR.
3. Account settings (owners)
| Where | What you can do |
|---|---|
/signup | Business or personal account; SMS consent (optional, unchecked) |
/account | Status, listings, verify phone (Verify by call), "I own this business", resend confirmation |
/account/tokens | Create/revoke API keys (one business or all; scopes) |
/device | Approve the Best Deal On Bot extension for one business |
/account/phone-bot | Phone-bot dashboard (read-only) |
/forgot, /login/link | Reset password, email sign-in link |
4. Signed callbot API request
POST /api/callbot/caller-profile HTTP/1.1
Host: bestdealon.app
Content-Type: application/json
X-BDO-Signature: t=<unix-seconds>,v1=<hex HMAC-SHA256(secret, "<t>.<raw body>")>
{"caller":"+1<10 digits>"}const crypto = require('crypto');
const body = JSON.stringify({ caller: '+15555550123' });
const t = Math.floor(Date.now() / 1000);
const v1 = crypto.createHmac('sha256', process.env.BDO_CALLBOT_SHARED_SECRET).update(`${t}.${body}`).digest('hex');
// headers: { 'content-type': 'application/json', 'x-bdo-signature': `t=${t},v1=${v1}` }Unsigned, wrongly signed, or older than 300 s → 401.