Consent & PII policy

Consent & PII policy API

Two org-scoped surfaces that back the legal record of your calling: consent (may we dial this number, and what proves it) and PII policy (what personal data we strip from transcripts and recordings, and what proves that).

Both authenticate with a user JWT + X-Org-Id — not an API key. Both are org-scoped under /api/orgs/{orgId}/…. Concepts and obligations are in Telephony compliance, US calling compliance and Data protection; this page is the endpoints.

/api/orgs/{orgId}/consent

Proof-of-consent for outbound dialling (TCPA). Reads are open to any member — anyone in the workspace may ask whether a number is dialable. Writes need the manage tier: owner, admin or developer. That split matches DNC exactly, because the two are halves of one legal record.

MethodPathPurpose
POST/Record consent for a number
GET/coverageWhat enforcement would block right now — read-only
PUT/enforcementSet the org's dial-time enforcement mode
GET/{phone}Full consent history for one number
POST/{phone}/revokeRevoke and suppress — writes through to DNC
curl -X POST https://api.telenow.ai/api/orgs/$ORG/consent \
  -H "Authorization: Bearer $JWT" -H "X-Org-Id: $ORG" \
  -H "Content-Type: application/json" \
  -d '{
    "phoneNumber": "+15551234567",
    "consentType": "express_written",
    "scope": "marketing",
    "source": "web_form",
    "capturedAt": "2026-03-12T09:14:00Z",
    "evidence": { "formId": "signup-v3", "submissionId": "abc123" }
  }'
FieldRequiredValues
phoneNumberYesE.164
consentTypeYesexpress_written · express_oral · implied · existing_business_relationship
sourceYesweb_form · import · api · ivr_dtmf · verbal_recorded · paper
scopeNomarketing · transactional · service
evidenceNoFree-form object — form id, submission payload, recording reference
disclosureText, disclosureVersionNoThe exact wording the person agreed to, and its version
capturedAtNoDefaults to now
expiresAtNoWhen the consent lapses

Set capturedAt when importing historical consent. It defaults to now, so a bulk import that omits it backdates every record to the import date — which destroys the one thing the record exists to prove.

Your evidence is enriched, not trusted wholesale. The server merges in its own provenance — recordedVia, the request User-Agent, and the first X-Forwarded-For address — alongside what you send. Your keys are preserved, so an integration can still attach its own form id. The reason: a consent record whose only evidence is client-supplied is exactly as strong as the client's word, and in a dispute the client's word is the thing being challenged.

Enforcement

PUT /enforcement takes {"mode": "off" | "required"}. Any other value is a 400. The default for an org is off.

Call GET /coverage before you flip it. Enforcement is a dial-time allow-list: with required, a number without a valid consent record does not get dialled. Coverage tells you how many of your contacts would be blocked the moment you switch, so you find out before a campaign does. Enforcement changes are logged at warn with the actor.

Revoking through POST /{phone}/revoke also writes to DNC — one call, both records, so a revocation cannot be honoured in one system and missed in the other.

PII policy

/api/orgs/{orgId}/pii

Which categories of personal data are stripped from transcripts and recordings, who changed that, and what the policy was on any given call.

Every endpoint here returns 404 when the feature is switched off for the deployment — deliberately, rather than answering with an empty policy. An endpoint that responds for a disabled feature invites an integration against something that is not running.

Reads are open to any member — "what do you strip from our transcripts" is a question anyone in the workspace may ask. Writes are owner or admin only: a floor is a contractual commitment, and lowering one should not be available to whoever happens to be logged in.

MethodPathPurposeRole
GET/Every rule: what the platform allows, what this org setmember
GET/changesWho changed what, when, and whymember
GET/impact/{slug}?to=What raising a floor would clamp, before you do itmember
PUT/rules/{slug}Set this org's floor and its agents' defaultowner/admin
GET/evidence?from=&to=Per-call policy evidence over a date rangemember
GET/calls/{sessionId}/policyThe policy that call actually ran undermember
GET/calls/{sessionId}/collectedReveal the values a call captured under collectowner/admin, see below

Dispositions

Four, in increasing strictness:

ValueMeaning
offThe rule is not applied
collectThe value is captured and stored, retrievable through the reveal endpoint
redactThe value is masked before storage
never_storeThe value never reaches storage at all

Setting a rule

curl -X PUT https://api.telenow.ai/api/orgs/$ORG/pii/rules/aadhaar \
  -H "Authorization: Bearer $JWT" -H "X-Org-Id: $ORG" \
  -H "Content-Type: application/json" \
  -d '{ "floor": "redact", "defaultDisposition": "redact", "reason": "DPA with Acme" }'

floor is the strictest setting the org's agents may go below — it clamps them. defaultDisposition is what a new agent starts at. Sending null for either clears the override and returns to inheriting the platform value; omitting the key leaves it unchanged. reason is free text and lands in /changes.

The setting and its change-log entry are written in one transaction, so "who raised our floor, when, and why" can never be answered with a setting that has no log line.

Check GET /impact/{slug}?to=<disposition> first. It returns the agents that would be clamped by raising the floor, without changing anything. Omitting ?to= is a 400.

Revealing collected values

GET /calls/{sessionId}/collected is the tightest authorization on any call surface in the product, and deliberately so:

  • It requires owner or admin.
  • It is refused outright during a support session, with 403. A support operator acting on a customer's behalf carries the owner's identity, so a plain role check would have passed — and the access log would then have recorded the customer's own owner as the reader of their caller's card number, pointing the audit trail away from whoever actually read it. The account owner must retrieve these values themselves.

GET /evidence requires both from and to; omitting either is a 400. It answers the question an enterprise buyer actually asks — "prove redaction was on for our org on 12 March" — from the per-call policy snapshot rather than by re-deriving today's policy.