# Call Clearance API

Base URL: `https://api.callclearance.com`. All agency routes take `Authorization: Bearer cc_live_...`. Bodies are JSON. Phone numbers are US, in any common format; responses return E.164.

Every check, consent, and opt-out is written to a hash-chained audit log and is billed at one cent per check. A block is a successful check.

## Check a number before you dial

```
POST /v1/check
{ "client_id": "cl_8f2a", "to": "+14105550123", "channel": "voice" }
```

Optional fields: `require_consent` (default: true for `sms`, false for `voice`), `consent_overrides_dnc` (default false; when true, a consent record on file lets a DNC hit through, which is your call to make under the established-business-relationship or prior-express-consent rules).

Response, 200:

```
{
  "decision": "block",
  "reason": "national_dnc",
  "retryable": false,
  "checked": [
    { "name": "optout", "result": "pass" },
    { "name": "litigator", "result": "pass" },
    { "name": "national_dnc", "result": "hit", "detail": "ftc_san_12345 loaded 2026-09-01T00:00:00Z" }
  ],
  "evidence_id": "ev_10422",
  "to": "+14105550123",
  "client_id": "cl_8f2a"
}
```

Reasons: `opted_out`, `litigator`, `national_dnc`, `state_dnc`, `no_consent`, `outside_calling_hours` (retryable, with `retry_after_seconds` and a `Retry-After` header), `invalid_number`.

A check result of `skipped` means the check could not run and says why (no registry data loaded for that area code, no state list, no timezone). Skipped is never treated as pass.

Checks run in this order and stop at the first hit: opt-out, litigator, national DNC, state DNC, consent, calling hours.

402 means the account has no credit. 404 means the client id is not on your account.

## Record consent

```
POST /v1/consent
{
  "client_id": "cl_8f2a",
  "phone": "+14105550123",
  "channel": "sms",                 // voice | sms | any
  "source": "web_form",             // free text: web_form, sms_reply, verbal, written
  "captured_at": "2026-09-10T14:22:00Z",
  "evidence_ref": "https://forms.example.com/submissions/88213",
  "evidence": "{...raw form payload or transcript excerpt...}",
  "scope": "solar quote follow-up"
}
```

`evidence` is hashed (SHA-256) and the hash is stored; the body is not. Keep the original yourself. `evidence_ref` is stored as given.

Revoke for one client: `POST /v1/consent/revoke` with `client_id`, `phone`, `reason`.

## Record an opt-out

```
POST /v1/optout
{ "phone": "+14105550123", "source": "sms_stop", "client_id": "cl_8f2a" }
```

Opt-outs are account-wide: the number is blocked for every client on your account, and any live consent under any client is revoked. `client_id` records where it was heard.

## Evidence

```
GET /v1/evidence/+14105550123?client_id=cl_8f2a          JSON
GET /v1/evidence/+14105550123.pdf?client_id=cl_8f2a      PDF
```

Returns every consent record, the opt-out if any, and every audit event for that number under that client, each with its chain hashes, plus whether the full chain verifies.

`GET /v1/audit/verify` re-walks the whole log and reports the first broken row, if any.

## Clients

```
GET  /v1/clients
POST /v1/clients            { "name": "Sunny Solar LLC", "state": "MD" }
PATCH /v1/clients/:id       { "san": "1234567", "san_status": "active" }
```

Each client is a separate seller under the Telemarketing Sales Rule and needs its own FTC Subscription Account Number for national registry access. We handle that registration; until `san_status` is `active`, national DNC checks run only against area codes already loaded on this deployment and report `skipped` otherwise.

## Retell pre-call webhook

Point Retell's pre-call webhook at `POST /v1/adapters/retell` with your key in the Authorization header and `client_id` in the call metadata. The adapter reads `to_number` and answers `200 {"allow": true}` or `403 {"allow": false, "reason": "..."}`. Each call is a billed check.

## Vapi, Bland, ElevenLabs, your own dialer

Call `POST /v1/check` before you place the call and place it only on `allow`. Five lines:

```
curl -s https://api.callclearance.com/v1/check \
  -H "Authorization: Bearer $CC_KEY" -H 'content-type: application/json' \
  -d '{"client_id":"cl_8f2a","to":"+14105550123","channel":"voice"}' \
  | jq -e '.decision == "allow"' && vapi_call.sh +14105550123
```

## Account

`GET /account` shows balance and price. `POST /account/topup {"amount_dollars": 100}` returns a Stripe Checkout URL.

## Errors

`{ "error": "<code>", "message": "<plain English>" }` with 400, 401, 402, 403, 404, or 500.
