HCC Docs

Consent

We keep what each number agreed to, when, and where it's written down, so you can show it later. Each dial attempt records the grant it relied on, or that there was none.

This records evidence. It is not legal clearance: we don't judge whether a grant is enough, and apart from a message on a machine it doesn't stop a dial.

Record it

If your CRM already holds it, map it, so nobody enters it twice. On the Integrations page, name the property, the values that mean yes and revoked, and the property with the date.

The same thing through the API, or from your own form:

await hcc.leads.upsert({
  phone: '+14155550123',
  consent: {
    type: 'express_written',
    scopes: ['human_calls', 'ai_voice'],
    source: 'Pricing page form',
    proofUrl: 'https://example.com/consent/42',
    effectiveAt: '2026-10-02T15:04:05Z',
  },
});

await hcc.leads.revokeConsent(leadId); // Every scope, which adds the number to Do Not Call
const { current, data } = await hcc.leads.consents(leadId);
current.ai_voice.state; // 'granted', 'revoked' or 'none'

A person can also state it on the dashboard's Add lead form, with where and when it was given. The row names who stated it. Anyone who can add a lead can do this.

A CSV import takes the same through the consent, consentDate, consentType, consentScopes, consentSource, consentProofUrl and consentProofText columns. A hook reads it as lead.consent, and decides what to do about it.

Which grant stands

  • It goes by phone number, and rows are never changed. For each scope, the latest by effectiveAt stands, so only a newer grant undoes a revocation.
  • A grant needs its date, everywhere. A date we chose could undo a revocation, so a CRM grant with no date isn't recorded, and neither is a CSV one. A date in the future is refused too.
  • Do Not Call moves one way. Revoking every scope adds the number to the list, and adding a number to the list revokes every scope. A grant never takes a number off the list: that stays a separate decision.
  • Rows outlive a deleted lead, as the number's history is the point.

From a CSV

  • A bare yes covers calls with a person, and nothing else. A plain no records nothing: only a word that says so (revoked, stop, opt out) revokes.
  • A cell we can't read never costs you the lead. The lead is imported, and the line is in the import's errors without counting as invalid.
  • A grant with a bad cell isn't recorded. A revocation still is: with a bad date it's dated at import, a bad link or source is dropped, and scopes we can't read revoke everything.
  • A CSV has no history. Upload a file again with an undated stop in it after a newer grant, and the stop counts again, dated at import. That can put the number back on the list. It's the safe side to be wrong on, so we leave it.

From your CRM

  • A revocation can take about 20 minutes to reach us, as customer-chosen properties arrive on the catch-up. If it can't wait, call hcc.leads.revokeConsent.
  • We date a revocation by the record's last change, and it counts only when that property moved to it, or the first time we read it from that property. So a re-read, or an edit to the contact's name, doesn't overrule a newer grant or put a number back on the list.
  • We never write it to your CRM. Only call activity goes back.

Who sees it

  • Reps don't, on the desk or in a preview: it's stripped before anything reaches their browser.
  • The dashboard shows it to everyone who can see leads but reps. The only thing that writes it there is a grant on the Add lead form.
  • Scopes are consent:read and consent:write. A lead sent with consent needs consent:write as well as leads:write.
  • Events are lead.consent.recorded and lead.consent.revoked, one per row and scope. They carry no proof: read it with hcc.leads.consents.