Settings reference
Sources:
- tenant validation:
src/tenants.js:12-76[bdo] - defaults:
src/tenants.jsDEFAULTS[bdo] - live-editable fields:
ALLOWEDatsrc/app.js:201[bdo] - owner briefing:
src/owner/config.js
"Editable" means the field is in ALLOWED, so PATCH /admin/tenants/<id>/config can change it.
Tenant JSON fields
| Field | Type / rule | Default | Notes | |
|---|---|---|---|---|
id | lowercase slug, required | — | ||
name | required | — | Spoken in the greeting and instructions | |
numbers | array of E.164 | — | The first one is the texting sender (src/twilio.js:57) | |
link_allowlist | bare domains, required | — | The only links the bot may send | |
owner_email | — | Owner notices. Editable | ||
support_email | — | Editable | ||
hours | {tz, open "HH:MM", close, days} | none (always open) | Drives after-hours wording. Editable | |
transfer_target | tel:+E164 or sip:… | none | Without it, transfers are off. Editable | |
transfer_hours_only | bool | — | Transfer only during hours (src/tools.js:88 [bdo]) | |
voice | Grok voice name | eve | Editable | |
disclosure | text | "Hi, you have reached {name}. This call may be recorded and is answered by an AI assistant." | Editable | |
keyterms | string[] | — | Transcription hints. Editable | |
extra_instructions | text | — | Owner guide added to the prompt. Live switches override it (src/xai.js:86-91). Editable | |
blocked_topics | string[] | [] | Editable | |
max_call_seconds | number | 900 | The call ends at this cap | |
approval_mode | bool | true | Queues outbound actions for approval (src/tools.js:240) | |
kb | {dirs:[…]} or {collection_id} | — | Editable | |
sms_enabled | bool | forced false at creation (src/app.js:177) | Only setSms turns it on (see texting.md) | |
email_enabled | bool | — | Adds email tools. Editable, also from /admin/channels | |
instant_link_reply | bool | — | Editable | |
order_lookup_enabled | bool | false | Shopify order lookup. Editable | |
shopify | {shop, mode, public_domain} | — | Not used by Best Deal On (out of scope). Editable | |
sar_lookup | object | — | Not used by Best Deal On (out of scope). Editable | |
known_callers | { "+E164": {name≤40, role?≤120, greeting?≤200} } | — | Changes the greeting only. Editable | |
returning_caller_greeting | bool | on (unless false) | Editable | |
returning_caller_include_unconfirmed | bool | false | [bdo] | |
welcome_back | text with {name}, ≤200 | built-in text | [bdo] | |
callback_offer | bool | false | [bdo] Offers "call you back or email you" | |
bdo_caller_lookup | bool, only for tenant bestdealon | false | [bdo] | |
bdo_claims | bool | — | [bdo] Needs BDO_INBOUND_CLAIM=on | |
bizinator_phone | listing id | — | [bdo] Links the owner dashboard to a Best Deal On listing | |
brand | {team_name, email_from, site, trademark_line?, kb_allow_domains?} | none (framework default text) | [bdo] src/brand.js | |
take_message | `{enabled, record_audio, deliver: outbox\ | email}` | enabled | [bdo] deliver: email needs brand.email_from |
twilio.account_sid | AC+32 hex | env | [bdo] | |
twilio.api_key_sid | SK+32 hex | — | [bdo] Needs secrets.twilio_api_key_secret | |
twilio.webhook_keys | { webhooks_sharedkey_…: secretName } | — | [bdo] | |
twilio.require_shared_key | bool | — | [bdo] Refuses auth-token-signed webhooks | |
twilio.messaging_service_sid | MG+32 hex | — | Set by setSms | |
secrets.* | env:NAME or store:key | — | Never a value. Names used: xai_webhook_secret, twilio_auth_token, twilio_api_key_secret, twilio_webhook_key, shopify_storefront_token | |
owner_briefing | object, see below | off | Editable | |
payments_enabled | — | — | Always rejected |
owner_briefing (src/owner/config.js:5-10)
| Key | Default |
|---|---|
enabled | false |
daily_call | true |
daily_time | "18:00" |
timezone | America/New_York |
copy_sms | false |
copy_email | false |
emergency_alerts | true |
alert_max_per_day | 3 |
alert_min_gap_minutes | 30 |
quiet_hours | 21:00–08:00 |
quiet_hours_allow | ["safety"] |
error_threshold | 5 |
error_window_minutes | 15 |
on_demand | true |
transfer_fallback | true |
voice | grok |
twilio_voice | Polly.Joanna |
grok_sip_domain | sip.voice.x.ai |
owner_numbers, daily_numbers and alert_numbers each take up to 5 E.164 numbers. If owner_numbers is empty, the owners are the known callers whose role mentions admin or owner.
Environment variables (names only)
| Name | Purpose |
|---|---|
PA_MODE | live or demo. Anything else means demo (bin/server.js:10) |
PORT, PUBLIC_BASE_URL, DATA_DIR, TENANTS_DIR, PA_LOG_FILE | Runtime, paths, and logs |
PA_ADMIN_TOKEN, PA_STATE_SECRET, PA_MASTER_KEY, ADMIN_LOGIN_EMAIL | Admin auth, signed state, and the secret-store key. ADMIN_LOGIN_EMAIL is where login links go |
XAI_API_KEY, XAI_TEXT_MODEL (default grok-4.7) | xAI voice and text |
BDO_XAI_WEBHOOK_SECRET | xAI webhook secrets for each tenant |
TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, TWILIO_PHONE_NUMBER, TWILIO_CONNECT_APP_SID | Twilio (framework defaults; Best Deal On uses the BDO_TWILIO_* names) |
BDO_TWILIO_ACCOUNT_SID, BDO_TWILIO_API_KEY_SID, BDO_TWILIO_API_KEY_SECRET, BDO_TWILIO_WEBHOOK_KEY | Twilio, Best Deal On [bdo] |
RESEND_API_KEY, PA_EMAIL_ALLOW_ONLY | Email, plus the test allowlist (comma-separated) |
NEWSLETTER_SECRET | Newsletter tokens |
RENDER_API_KEY | Usage page |
BDO_VERIFY_CALLS (default off; on in production), BDO_INBOUND_CLAIM (default off; off in production), BDO_CALLBOT_SHARED_SECRET, BDO_SITE_URL | [bdo] verify-by-call and claims |
BIZINATOR_URL (default https://bestdealon.app) | [bdo] Owner API (src/ownerapi.js:32) |
PA_DRAIN_MAX_MS (default 280000) | Only in [PR #42], which is unmerged |
Example: turn texting off and switch on email take-a-message (placeholders)
curl -X PATCH "$PUBLIC_BASE_URL/admin/tenants/acme-bakery/config" \
-H "Authorization: Bearer $PA_ADMIN_TOKEN" -H 'content-type: application/json' \
-d '{"email_enabled": true, "extra_instructions": "We do not quote prices; take a message."}'Only run a call like this after the owner approves the exact change.