Compliance

Built-in compliance

KaiCalls checks every call and text you send through the API before it goes out. You don't have to build calling-hours logic, a do-not-call list or STOP handling. If a check fails, nothing is sent, and the error says which rule stopped it.

Every check at a glance

CheckCallsTextsWhat you get back
Calling hours: 8am to 9pm where the person isCheckedCheckedCall: 409 blockedBy: "tcpa" with next_allowed_time. Text: tcpa_violation, or queued with queue_if_needed.
Your business's do-not-call listCheckedCheckedCall: 409 blockedBy: "dnc". Text: number_on_dnc.
STOP replies and spoken opt-outsCheckedCheckedCall: 409 blockedBy: "consent". Text: number_opted_out.
The person agreed to textsNot applicableCheckedconsent_required
AI and recording disclosure at the start of the callCheckedNot applicableAdded for you. Nothing to send.
Per-number and per-account volume limitsCheckedCheckedCall: 409 blockedBy: "fraud_guard". Text: rate_limit_exceeded or sms_send_failed.
Destination is in the US, Canada or Puerto RicoCheckedNot applicable409 blockedBy: "geo_not_permitted" or "fraud_guard"

A refused call returns 409 with error.code: "blocked" and a blockedBy field naming the rule. A refused text returns 400 with the code shown above. Either way, nothing was placed or sent.

Call outside calling hours · 409
{
  "error": {
    "code": "blocked",
    "message": "Compliance violation: Call time 22:00 is outside 8:00-21:00 in America/Chicago (United States)"
  },
  "blockedBy": "tcpa",
  "next_allowed_time": "2026-11-12T14:00:00.000Z",
  "retryable": true
}
Text without consent · 400
{
  "error": {
    "code": "consent_required",
    "message": "SMS consent is required. For a confirmation the customer just requested, include purpose: 'booking_confirmation', their actual sms_consent: true, and an Idempotency-Key."
  }
}

Calling hours

Calls and texts to the US and Canada go out only between 8am and 9pm in the person's time zone, every day. KaiCalls works out their time zone from the area code of the number you are calling.

A blocked call comes back with next_allowed_time and retryable: true, so you can try again then. A call you place for an errand (with context and no lead_id) is scheduled for you instead: you get 202 with status: "scheduled" and scheduled_for.

For texts, send "dispatch_policy": "queue_if_needed" and a text outside the window is queued for the morning (202 with scheduled_for) instead of refused.

Do-not-call and opt-outs

Each business has its own do-not-call list. Every call and text checks it first. If the list can't be read, the call is held rather than placed.

STOP replies are handled for you. When someone texts STOP, UNSUBSCRIBE, CANCEL, END, QUIT or a similar word, KaiCalls marks them opted out, adds them to the do-not-call list for texts and sends the confirmation. START or UNSTOP opts them back in. HELP gets an automatic reply. You get an sms.opted_out webhook so your own system can update too.

If someone asks not to be contacted during a call, they are opted out of both calls and texts. A person who has opted out of calls can't be called through the API.

Call disclosures

By default, Kai says at the start of every call that it is an AI assistant for the business. Where state law needs it, Kai also says the call may be recorded. The business can change these in its settings.

Some states require everyone on a call to agree to recording. Kai does not place errand calls to numbers in those states.

Volume limits

To protect your number's reputation and the people you call, each account has limits. By default, one number can get at most 5 calls a day, and an account can place up to 15 calls an hour and 50 a day. Texts allow 40 an hour and 150 a day. Calls only go to the US, Canada and Puerto Rico. A call over a limit comes back with blockedBy: "fraud_guard". Ask support if you need higher limits.

Scheduled runs

POST /communication-runs/validate checks the shape of a run: ids are real, the agent and number belong to the business, a call run names an agent_id, text touches have a message, and timestamps are valid.

The compliance checks above run when each touch goes out, not at validation. A call touch scheduled outside calling hours is moved to the next allowed time. A touch to someone on the do-not-call list, or who has opted out, is not sent.

What is still on you

  • Permission to contact people. KaiCalls blocks people who opted out, but it can't know whether you had permission in the first place.
  • The national Do Not Call Registry. KaiCalls checks your business's own list, not the national registry. Scrub sales lists against it before you call.
  • Your own message content. What Kai says comes from your agent's instructions and the context you send.

Questions? See the error reference or the quickstart.