API reference
API: Freshness
| Method | Path | What it does | Scope |
|---|---|---|---|
| GET | /v1/email-verification | An address's cached verification (state, each check, when) and its bounce history | contacts:read |
| 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. | contacts:write |
| 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 | contacts:read |
| PUT | /v1/email-verification/settings | Set the catch-all policy, the reduced-volume cap and the cache TTLs (owner; audited) | settings:write |
| DELETE | /v1/email-verification/suppressions | Lift an address's suppression (owner; audited). Its next verification runs fresh. | settings:write |
| 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 | contacts:write |
| GET | /v1/freshness/settings | How long each kind of field stays fresh (days), the pre-send email window and the cited-fact window | contacts:read |
| PUT | /v1/freshness/settings | Change the freshness TTLs and windows, or turn read-time re-checks off (owner) | settings:write |
| DELETE | /v1/phones/:id | Remove a phone number | contacts:write |
| 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 | contacts:write |
| 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. | contacts:read |
| 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. | contacts:write |
| 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. | contacts:read |
| 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. | contacts:write |
| 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) | agents:read |
| POST | /v1/send-checks/:run_id | Check 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/acknowledge | The 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/redraft | Re-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.