Skip to content

API reference

API: Calling compliance

Markdown version

MethodPathWhat it doesScope
GET/v1/calling-complianceThe organization's calling and texting rules: window and states, opt-out scope, replies, disclosures, the DNC registry files, emergency blocks and the state rules tablesettings:read
GET/v1/calling-compliance/announcementsThe call announcements, word for word: start (with the recording notice and opt-out), transfer, voicemail drop, recording on and off. Versioned with the disclosures; none can be removed.settings:read
POST/v1/calling-compliance/checkWould a text or call to this number be allowed now? Allow, deny or queue (with when), and every reason. Nothing is sent.calls:read
GET/v1/calling-compliance/consent-wordingThe consent wording each channel shows when someone gives consent (forms, the SMS opt-in), with its versionsettings:read
PUT/v1/calling-compliance/consent-wording/:channelReword a channel's consent text (owners; versioned, checked: business name, opt-out, and for SMS help and rates, for calls automated or AI voice and not a condition of purchase)settings:write
PUT/v1/calling-compliance/disclosureReword the mandatory disclosures (owners). They can't be turned off: each must still name the business, say it's an AI and keep the opt-out. Saved as a new version; marked for counsel review.settings:write
GET/v1/calling-compliance/disclosure/previewWhat's said or sent first: the voice opening lines, the SMS first-message line, or the email line and sender namesettings:read
POST/v1/calling-compliance/emergenciesBlock calls and texts to states or area codes for a state of emergency (owners; dates inclusive, contact-local)settings:write
DELETE/v1/calling-compliance/emergencies/:idLift a state-of-emergency block (owners)settings:write
GET/v1/calling-compliance/opt-out-reviewsTexts that may be opt-outs, waiting for an owner to decide (oldest first), each with its 10-business-day due date and whether it's overduecalls:read
POST/v1/calling-compliance/opt-out-reviews/:idDecide a held text (owners, from the app; a reason is required and audited): an opt-out (applied under the organization's scope) or not one (the agent may answer again) (web app only)settings:write
GET/v1/calling-compliance/queueThe quiet-hours queue: texts and calls held by the calling window, a holiday, an emergency block or a state cap, with why and when each goes (numbers masked)calls:read
POST/v1/calling-compliance/queue/:id/cancelCancel a held text or call before it's releasedcalls:write
POST/v1/calling-compliance/queue/:id/unmaskShow a held item's number in full (owners, from the app; audited) (web app only)settings:write
PUT/v1/calling-compliance/settingsChange the rules (owners). The window can be narrowed inside 08:00–20:00 contact-local, never widened; state rules always apply.settings:write
GET/v1/dncThe organization's internal do-not-call list (numbers masked; an owner reveals one from the app, audited)calls:read
POST/v1/dncAdd numbers to the internal do-not-call list (calls and texts stop at once; kept at least five years)calls:write
DELETE/v1/dnc/:idTake a number off the internal do-not-call list (owners; audited). A number they asked to stop stays opted out in the ledger.settings:write
POST/v1/dnc/:id/unmaskShow a do-not-call entry's number in full (owners, from the app; audited) (web app only)settings:write
GET/v1/dnc/registryRegistry coverage per area code: last refresh, age and whether it's stale (over 31 days)settings:read
POST/v1/dnc/registryUpload the organization's own National Do Not Call Registry download (CSV or text, one number per line; up to 20 MB per upload). Stored hashed per area code. mode=replace (default) clears and refills the area codes it covers; mode=merge adds the next part of the same download (within 24 hours). Refresh at least every 31 days, or marketing calls and texts to those area codes stop.settings:write
POST/v1/opt-outsRecord an opt-out someone asked for (by phone, in person, a spoken "don't call me"). Applied at once, under the organization's scope.calls:write
POST/v1/opt-outs/liftLift an opt-out block on one channel for a number (owners; audited). Texts or calls reopen without counting as their consent; email: the number's opt-out suppression is removed. Their objection stays in the ledger.settings:write
GET/v1/phone-ledgerA number's opt-out ledger (STOP, START, HELP, manual and spoken requests) and its consent entries, with the current status per channelcalls:read
POST/v1/phones/:id/unmaskShow a do-not-call number in full (owners; audited) (web app only)settings:write
POST/v1/records/:id/unmask-phonesShow a record's do-not-call phone fields in full (owners; audited) (web app only)settings:write

Examples

GET /v1/calling-compliance

The organization's calling and texting rules: window and states, opt-out scope, replies, disclosures, the DNC registry files, emergency blocks and the state rules table

curl -s "https://api.closefinch.com/v1/calling-compliance" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/calling-compliance`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

GET /v1/calling-compliance/announcements

The call announcements, word for word: start (with the recording notice and opt-out), transfer, voicemail drop, recording on and off. Versioned with the disclosures; none can be removed.

curl -s "https://api.closefinch.com/v1/calling-compliance/announcements" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/calling-compliance/announcements`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

POST /v1/calling-compliance/check

Would a text or call to this number be allowed now? Allow, deny or queue (with when), and every reason. Nothing is sent.

curl -s -X POST "https://api.closefinch.com/v1/calling-compliance/check" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/calling-compliance/check`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

The consent wording each channel shows when someone gives consent (forms, the SMS opt-in), with its version

curl -s "https://api.closefinch.com/v1/calling-compliance/consent-wording" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/calling-compliance/consent-wording`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

Reword a channel's consent text (owners; versioned, checked: business name, opt-out, and for SMS help and rates, for calls automated or AI voice and not a condition of purchase)

curl -s -X PUT "https://api.closefinch.com/v1/calling-compliance/consent-wording/$CHANNEL" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/calling-compliance/consent-wording/${channel}`, {
  method: "PUT",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

PUT /v1/calling-compliance/disclosure

Reword the mandatory disclosures (owners). They can't be turned off: each must still name the business, say it's an AI and keep the opt-out. Saved as a new version; marked for counsel review.

curl -s -X PUT "https://api.closefinch.com/v1/calling-compliance/disclosure" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/calling-compliance/disclosure`, {
  method: "PUT",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

GET /v1/calling-compliance/disclosure/preview

What's said or sent first: the voice opening lines, the SMS first-message line, or the email line and sender name

curl -s "https://api.closefinch.com/v1/calling-compliance/disclosure/preview" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/calling-compliance/disclosure/preview`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

POST /v1/calling-compliance/emergencies

Block calls and texts to states or area codes for a state of emergency (owners; dates inclusive, contact-local)

curl -s -X POST "https://api.closefinch.com/v1/calling-compliance/emergencies" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/calling-compliance/emergencies`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

DELETE /v1/calling-compliance/emergencies/$ID

Lift a state-of-emergency block (owners)

curl -s -X DELETE "https://api.closefinch.com/v1/calling-compliance/emergencies/$ID" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/calling-compliance/emergencies/${id}`, {
  method: "DELETE",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

GET /v1/calling-compliance/opt-out-reviews

Texts that may be opt-outs, waiting for an owner to decide (oldest first), each with its 10-business-day due date and whether it's overdue

curl -s "https://api.closefinch.com/v1/calling-compliance/opt-out-reviews" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/calling-compliance/opt-out-reviews`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

GET /v1/calling-compliance/queue

The quiet-hours queue: texts and calls held by the calling window, a holiday, an emergency block or a state cap, with why and when each goes (numbers masked)

curl -s "https://api.closefinch.com/v1/calling-compliance/queue" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/calling-compliance/queue`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

POST /v1/calling-compliance/queue/$ID/cancel

Cancel a held text or call before it's released

curl -s -X POST "https://api.closefinch.com/v1/calling-compliance/queue/$ID/cancel" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/calling-compliance/queue/${id}/cancel`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

PUT /v1/calling-compliance/settings

Change the rules (owners). The window can be narrowed inside 08:00–20:00 contact-local, never widened; state rules always apply.

curl -s -X PUT "https://api.closefinch.com/v1/calling-compliance/settings" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/calling-compliance/settings`, {
  method: "PUT",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

GET /v1/dnc

The organization's internal do-not-call list (numbers masked; an owner reveals one from the app, audited)

curl -s "https://api.closefinch.com/v1/dnc" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/dnc`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

POST /v1/dnc

Add numbers to the internal do-not-call list (calls and texts stop at once; kept at least five years)

curl -s -X POST "https://api.closefinch.com/v1/dnc" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/dnc`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

DELETE /v1/dnc/$ID

Take a number off the internal do-not-call list (owners; audited). A number they asked to stop stays opted out in the ledger.

curl -s -X DELETE "https://api.closefinch.com/v1/dnc/$ID" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/dnc/${id}`, {
  method: "DELETE",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

GET /v1/dnc/registry

Registry coverage per area code: last refresh, age and whether it's stale (over 31 days)

curl -s "https://api.closefinch.com/v1/dnc/registry" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/dnc/registry`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

POST /v1/dnc/registry

Upload the organization's own National Do Not Call Registry download (CSV or text, one number per line; up to 20 MB per upload). Stored hashed per area code. mode=replace (default) clears and refills the area codes it covers; mode=merge adds the next part of the same download (within 24 hours). Refresh at least every 31 days, or marketing calls and texts to those area codes stop.

curl -s -X POST "https://api.closefinch.com/v1/dnc/registry" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/dnc/registry`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

POST /v1/opt-outs

Record an opt-out someone asked for (by phone, in person, a spoken "don't call me"). Applied at once, under the organization's scope.

curl -s -X POST "https://api.closefinch.com/v1/opt-outs" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/opt-outs`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

POST /v1/opt-outs/lift

Lift an opt-out block on one channel for a number (owners; audited). Texts or calls reopen without counting as their consent; email: the number's opt-out suppression is removed. Their objection stays in the ledger.

curl -s -X POST "https://api.closefinch.com/v1/opt-outs/lift" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/opt-outs/lift`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();

GET /v1/phone-ledger

A number's opt-out ledger (STOP, START, HELP, manual and spoken requests) and its consent entries, with the current status per channel

curl -s "https://api.closefinch.com/v1/phone-ledger" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/phone-ledger`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();

Request and response schemas: https://www.closefinch.com/openapi.json. All resources: API reference.

Send feedback

Tell us what's broken, confusing or missing on this page, or an idea. It goes to the team that builds the product.

Please don't include passwords or card numbers.
Only to reply about this. Never added to any mailing list.