Compliance
The checks every outbound email, call and message passes, in code - consent, suppressions, calling windows, caps and contact pressure.
ZeroReach checks compliance in code, before every outbound action: sequence steps, one-off emails, calls, callbacks and speed-to-lead. The checks don't depend on a prompt. They are the same whether the action comes from the app, the API, MCP or an agent, and whatever an agent's autonomy.
GET /api/v1/leads/{lead_id}/contactability answers "may we contact this lead, and if not, why?" for each channel. Zero and MCP clients can ask the same question with the can_contact tool.
The contact check
For a lead, a channel (email, phone, sms or linkedin) and a purpose (marketing or transactional), the rules run in this order. Every failing rule adds a reason, and contact is allowed only if none fail:
| # | Rule | Reason when it fails |
|---|---|---|
| 1 | The lead has an address on the channel | no_address:<channel> |
| 2 | No suppression matches (email, phone, LinkedIn URL, email domain or a parent domain, company domain) for this channel | suppressed:<kind>:<reason> |
| 3 | No revoked consent without a newer one | consent_revoked |
| 4 | A consent basis exists for the channel and purpose | consent_required:<types> |
| 5 | Phone and SMS only: the calling window is open and the caps allow it | outside_calling_window:..., holiday:..., frequency_cap:... |
| 6 | Contact pressure allows another touch | contact_pressure:... |
Reasons from rules 5 and 6 are temporary: when they are the only reasons, the answer carries next_allowed_at, and senders defer the action to that time instead of dropping it.
Consent
Consent is recorded per lead, channel and purpose in a ledger (/api/v1/leads/{lead_id}/consents). The types are express_written, express, implied, legitimate_interest and existing_relationship.
What the default policy accepts:
| Channel | Marketing | Transactional |
|---|---|---|
| legitimate interest (no record needed) | no consent required | |
| legitimate interest (no record needed) | no consent required | |
| Phone: mobile, VoIP or unknown line | express_written | express_written or express |
| Phone: other lines | no consent required | no consent required |
| SMS | express_written | express_written or express |
AI voice calls are stricter. Calls by the voice agent use a policy that requires prior express written consent for every line type, landlines included, because an AI voice is an "artificial voice" under the TCPA. Web forms can record that consent with the lead through the inbound lead webhook (phone_consent: the consent text and the page URL).
Marketing consent also covers transactional contact, but not the other way round. Revoking transactional consent also revokes marketing. An opt-out on any channel suppresses every channel.
Suppressions
The suppression list (/api/v1/suppressions) blocks contact by email, phone, domain or linkedin, for some or all channels. Reasons are opt_out, bounce, complaint, dnc, manual and legal.
Suppressions are added automatically by:
- unsubscribe links;
unsubscribeand angry replies;- bounces and spam complaints;
- opt-outs during a call.
A privacy erasure leaves a hashed suppression, so an erased person is never contacted again.
Calling windows and caps
Calls and texts are allowed only inside the calling hours of the recipient's country, in their local time, and below the per-lead and per-number caps. Rules come from policy packs shared by both backends; see Calling windows by country.
The recipient's time zone is the lead's, else the phone number's, else the workspace's, else UTC. If a number spans several time zones, every one of them must be open. National public holidays close the whole local day.
A workspace can add its own rules (PUT /api/v1/workspaces/current/calling-policy, admins): narrower hours, lower caps and closed dates. Workspace rules can only restrict.
Contact pressure
Contact pressure limits how often one person, one company and one email domain are touched across all channels. A touch is an outbound email, call (answered or not), SMS or LinkedIn message.
| Rule | Default |
|---|---|
| Touches per person per window | 4 per 7 days |
| Minimum gap between two touches of one person | 60 minutes |
| Touches per company per 24 hours | 6 |
| Touches per recipient email domain per 24 hours (freemail excluded) | 6 |
| No cold touch after a negative reply | 90 days |
Conversations are treated differently from cold outreach:
| Kind of touch | Rules |
|---|---|
| Cold (sequence steps) | Every rule applies. |
| Manual (one-off actions by a person) | Every rule applies, unless the lead wrote to you in the last 30 days. Then it is a conversation. |
| Conversation (reply drafts, callbacks the lead asked for, speed-to-lead calls to a form the lead just submitted, call recaps) | Exempt. |
Transactional messages are never throttled. Consent, suppressions, calling windows and call caps still apply to every kind. A workspace can only tighten these rules (PUT /api/v1/workspaces/current/contact-pressure).
Unsubscribe
Every marketing email carries a signed one-click unsubscribe link and List-Unsubscribe headers, plus a CAN-SPAM footer with the workspace's postal address. Without a postal address, marketing email can't be sent (409 missing_postal_address).