Guides

Compliance

Calling hours, a do-not-call list, consent, a daily cap, AI disclosure, PII redaction and a do-not-disturb check.

Warning: These are tools, not legal advice. You are responsible for complying with the laws and regulations that apply to your calls (telemarketing, consent, recording, data protection) in every place you call.

These controls are checked before every outbound call. None has had a legal review, and no official do-not-disturb registry is integrated: there is no connection to any regulator's registry or scrubbing service.

In the dashboard: Settings → Account → Compliance, and Deploy → Do-not-call List. Changing these needs the admin role or an API key.

When the rules run

Rules are checked when a call is created, and again just before it is dialled (scheduled calls, retries, batch rows, workflow calls).

RuleAt creationAt dial time
Do-not-call listRefused, 400Execution ends canceled
Do-not-disturb check (block)Refused, 400canceled
Daily capRefused, 429canceled
Calling hoursCreated as rescheduledRescheduled into the calling window
ConsentBatch row skippedNot re-checked

A refused or cancelled call says why, starting with Call not placed:. Batch rows are listed in skipped_rows instead.

Account settings

bash
curl -X PATCH https://api.kshyamai.space/compliance/settings \
  -H "Authorization: Bearer vk-0123456789abcdef0123456789abcdef" \
  -H "Content-Type: application/json" \
  -d '{"require_consent": true, "require_ai_disclosure": true, "max_daily_attempts_per_number": 3, "pii_redaction": "mask"}'
json
{"require_ai_disclosure": true, "require_consent": true, "max_daily_attempts_per_number": 3,
 "pii_redaction": "mask", "timezone": "Asia/Kolkata", "dnd_check": "off", "dnd_registry": "mock"}
SettingValuesDefault
require_ai_disclosuretrue / falsefalse
require_consenttrue / falsefalse
max_daily_attempts_per_number0 (no cap) to 503, unless the operator changed it
pii_redactionoff, mask, strictmask
timezoneAn IANA nameAsia/Kolkata
dnd_checkoff, block, warnoff

Calling hours

Calling hours belong to the agent:

json
{"agent_config": {"calling_guardrails": {"call_start_hour": 9, "call_end_hour": 21}}}

Hours are 0 to 23. The window is read in the recipient's timezone: calling_guardrails.timezone or agent_config.timezone if set, else guessed from the number's country code, else the account default.

A call outside the window is not dropped: it becomes rescheduled for the next start of the window, and POST /call answers with "rescheduled": true and the new scheduled_at. bypass_call_guardrails: true on a call or batch schedule skips this check.

Do-not-call list

Your own list of numbers that must never be called.

bash
curl -X POST https://api.kshyamai.space/suppression-list \
  -H "Authorization: Bearer vk-0123456789abcdef0123456789abcdef" \
  -H "Content-Type: application/json" \
  -d '{"phone_numbers": ["+919876500123", "+919876500124"], "reason": "Asked to opt out"}'
json
{"message": "success", "added": 2, "total_given": 2}
  • POST /suppression-list/upload takes a CSV with a phone_number column and an optional reason column. It answers with added, rows and a list of invalid values.
  • DELETE /suppression-list/{phone_number} removes a number.

A bare 10-digit number is read as Indian (+91). The send_sms tool and the workflow WhatsApp step honour the same list.

With require_consent on, every batch row needs a truthy consent column (yes, true, 1, y, consent, given, haan, हाँ). Rows without it are skipped with no consent: the row has no consent and the account requires it. See Batches.

Daily cap

max_daily_attempts_per_number limits outbound attempts to one number per day in the account's timezone. Retries count; calls that failed before dialling and mock engine calls do not. The cap applies only in live telephony mode.

AI disclosure

The agent's own task_config.ai_disclosure_message is spoken right after the welcome message. If the agent has none and require_ai_disclosure is on, outbound calls get a default line in the agent's language (English and Hindi are built in).

PII redaction

The policy is the agent's task_config.pii_redaction, else the account setting.

PolicyEffect
offNothing is masked
maskSensitive values are masked; the last four digits of cards, Aadhaar and account numbers are kept
strictNothing is kept, and any long digit run is masked

Detected: card numbers (Luhn-checked), Aadhaar numbers (Verhoeff-checked), PAN, bank account numbers after a cue such as "account number", and CVV, OTP or PIN digits after their cue word, whether written as digits or spoken as number words in English or Hindi.

On the own engine, masking happens before the text reaches the LLM, the logs or the platform. It covers transcripts, tool-call logs, extracted data, webhooks and the text sent to post-call models.

Keypad entries

A keypad entry marked sensitive is stored as [REDACTED], and the recording is silent for both sides while it is typed. Keypad turns of three or more digits are treated as sensitive automatically. See Graph agents.

Do-not-disturb check

An interface for a registry lookup, with two built-in sources. Neither is an official registry.

RegistryWhat it is
mockDevelopment only: numbers ending 9999 count as registered. Treated as "no registry" in production
fileNumbers your workspace uploaded from its own scrubbing run, plus an optional platform-wide file

Upload your list, then switch the check on:

bash
curl -X POST "https://api.kshyamai.space/compliance/dnd/upload?replace=true" \
  -H "Authorization: Bearer vk-0123456789abcdef0123456789abcdef" \
  -F "file=@registered-numbers.csv"
json
{"message": "success", "added": 1840, "rows": 1842, "invalid": 2, "total": 1840}

With dnd_check: "block", registered numbers are not called. With warn, they are called and the response and execution carry a warning. GET /compliance/dnd reports the registry in use and always "official_registry": false; POST /compliance/dnd/check looks up to 1,000 numbers.

If no registry is configured, dnd_check cannot be switched on (400), and an account already set to block fails closed: its calls are refused.

Limitations

  • No official registry is integrated. An uploaded list is only as current as your last upload, and keeping it current is your job.
  • Redaction is pattern-based and will miss things. It covers text only: spoken numbers stay audible in recordings.
  • The mock engine does not redact its own transcripts.
  • Consent is a column in your file. The platform does not collect or verify it.
  • The timezone guess uses one zone per country code. Set a timezone on the agent.