Skip to content

API reference

API: Freshness

Markdown version

MethodPathWhat it doesScope
GET/v1/email-verificationAn address's cached verification (state, each check, when) and its bounce historycontacts:read
POST/v1/email-verification/bouncesReport a bounce of one of your sends (e.g. from your sending provider). Soft bounces: crm:write. A hard bounce suppresses the address everywhere, so it needs an owner (org:write). Who reported it is recorded.contacts:write
GET/v1/email-verification/settingsThe catch-all policy (block, reduce: allow at a reduced daily volume, second_signal: allow only with a second sign the address is real), the reduced-volume cap and how long each result is reusedcontacts:read
PUT/v1/email-verification/settingsSet the catch-all policy, the reduced-volume cap and the cache TTLs (owner; audited)settings:write
DELETE/v1/email-verification/suppressionsLift an address's suppression (owner; audited). Its next verification runs fresh.settings:write
POST/v1/email-verification/verifyVerify an address now (in-house checks, bounce history, and MillionVerifier when a key is set; a fresh cached result is reused unless max_age_days says otherwise), with the send decisioncontacts:write
GET/v1/freshness/settingsHow long each kind of field stays fresh (days), the pre-send email window and the cited-fact windowcontacts:read
PUT/v1/freshness/settingsChange the freshness TTLs and windows, or turn read-time re-checks off (owner)settings:write
DELETE/v1/phones/:idRemove a phone numbercontacts:write
PATCH/v1/phones/:idOverride a number's state or type (recorded as set by a person), or hand its state back to the format checkcontacts:write
GET/v1/records/:id/freshnessWhen each checked field (email, phone, domain, title, firmographics) was last verified or written, which are stale, and whether a re-check is queued. Reading it queues a re-check of stale ones, like reading the record.contacts:read
POST/v1/records/:id/freshness/recheckRe-check this record's email, phone and domain now with the in-house checks (syntax, MX/null MX, disposable and role addresses; phone format and country; domain resolves). Free; audited.contacts:write
GET/v1/records/:id/phonesA contact's, lead's or account's phone numbers: E.164, type, state (valid, invalid, unknown), why, source and when checked. Invalid ones are not dialable.contacts:read
POST/v1/records/:id/phonesAdd a phone number by hand. It's normalised to E.164 and given a state by the in-house format and country check (or the state you set). The same number twice is one entry.contacts:write
GET/v1/send-checks/:run_idThe latest pre-send check of a drafted email: each recipient's verification and each cited fact (still on its page, gone, changed or unreachable)agents:read
POST/v1/send-checks/:run_idCheck a drafted email now: re-verify stale recipient addresses and re-read the cited sources (each quote must still be there). The send runs the same check again right before sending.approvals:write
POST/v1/send-checks/:run_id/acknowledgeThe sender confirms a changed fact is out of the draft (or still right): it stops blocking the send. Recorded with who and when. (web app only)approvals:write
POST/v1/send-checks/:run_id/redraftRe-draft the email without the facts that changed (AI): the waiting item is rejected and a new one waits for your approval (web app only)approvals:write

Examples

GET /v1/email-verification

An address's cached verification (state, each check, when) and its bounce history

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

POST /v1/email-verification/bounces

Report a bounce of one of your sends (e.g. from your sending provider). Soft bounces: crm:write. A hard bounce suppresses the address everywhere, so it needs an owner (org:write). Who reported it is recorded.

curl -s -X POST "https://api.closefinch.com/v1/email-verification/bounces" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/email-verification/bounces`, {
  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/email-verification/settings

The catch-all policy (block, reduce: allow at a reduced daily volume, second_signal: allow only with a second sign the address is real), the reduced-volume cap and how long each result is reused

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

PUT /v1/email-verification/settings

Set the catch-all policy, the reduced-volume cap and the cache TTLs (owner; audited)

curl -s -X PUT "https://api.closefinch.com/v1/email-verification/settings" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/email-verification/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();

DELETE /v1/email-verification/suppressions

Lift an address's suppression (owner; audited). Its next verification runs fresh.

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

POST /v1/email-verification/verify

Verify an address now (in-house checks, bounce history, and MillionVerifier when a key is set; a fresh cached result is reused unless max_age_days says otherwise), with the send decision

curl -s -X POST "https://api.closefinch.com/v1/email-verification/verify" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/email-verification/verify`, {
  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/freshness/settings

How long each kind of field stays fresh (days), the pre-send email window and the cited-fact window

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

PUT /v1/freshness/settings

Change the freshness TTLs and windows, or turn read-time re-checks off (owner)

curl -s -X PUT "https://api.closefinch.com/v1/freshness/settings" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/freshness/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();

DELETE /v1/phones/$ID

Remove a phone number

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

PATCH /v1/phones/$ID

Override a number's state or type (recorded as set by a person), or hand its state back to the format check

curl -s -X PATCH "https://api.closefinch.com/v1/phones/$ID" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/phones/${id}`, {
  method: "PATCH",
  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/records/$ID/freshness

When each checked field (email, phone, domain, title, firmographics) was last verified or written, which are stale, and whether a re-check is queued. Reading it queues a re-check of stale ones, like reading the record.

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

POST /v1/records/$ID/freshness/recheck

Re-check this record's email, phone and domain now with the in-house checks (syntax, MX/null MX, disposable and role addresses; phone format and country; domain resolves). Free; audited.

curl -s -X POST "https://api.closefinch.com/v1/records/$ID/freshness/recheck" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/records/${id}/freshness/recheck`, {
  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/records/$ID/phones

A contact's, lead's or account's phone numbers: E.164, type, state (valid, invalid, unknown), why, source and when checked. Invalid ones are not dialable.

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

POST /v1/records/$ID/phones

Add a phone number by hand. It's normalised to E.164 and given a state by the in-house format and country check (or the state you set). The same number twice is one entry.

curl -s -X POST "https://api.closefinch.com/v1/records/$ID/phones" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
const res = await fetch(`https://api.closefinch.com/v1/records/${id}/phones`, {
  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/send-checks/$RUN_ID

The latest pre-send check of a drafted email: each recipient's verification and each cited fact (still on its page, gone, changed or unreachable)

curl -s "https://api.closefinch.com/v1/send-checks/$RUN_ID" \
  -H "Authorization: Bearer $RA_API_KEY"
const res = await fetch(`https://api.closefinch.com/v1/send-checks/${run_id}`, {
  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.