API reference
API: Scraping
| Method | Path | What it does | Scope |
|---|---|---|---|
| GET | /v1/scrape/domains | The owner's allow and block rules per domain (sites whose terms forbid scraping are refused whatever the rule) | prospecting:read |
| PUT | /v1/scrape/domains | Allow or block a domain for scraping (owner; audited). Allowed domains may be scraped by agents on any page without a query string | settings:write |
| DELETE | /v1/scrape/domains/:domain | Remove a domain's rule (owner; audited) | settings:write |
| POST | /v1/scrape/estimate | What a scrape would cost (model and Apify), without creating it | prospecting:read |
| POST | /v1/scrape/local/csv | Import a CSV of local businesses (name, address, phone, website, category, rating…): deduplicated and matched against the CRM's accounts, then previewed (nothing reaches the CRM until imported) | prospecting:write |
| GET | /v1/scrape/runs | Scrape runs, newest first, with row counts | prospecting:read |
| POST | /v1/scrape/runs | Set up a scrape: pages and fields, an Apify actor, a recipe, or a local-business search (Google Maps via Apify). Returns the cost preview; nothing runs until it's started | prospecting:write |
| GET | /v1/scrape/runs/:id | A run: its input, status, notes (partial results, refusals, caps), cost and row counts | prospecting:read |
| PUT | /v1/scrape/runs/:id/criteria | Set a run's fit criteria (field, op, value): every row gets a pass / fail / unsure verdict with its reason, judged again now | prospecting:write |
| POST | /v1/scrape/runs/:id/import | Import a local-business run's rows (all, or the chosen ones) into a static list of accounts: new businesses become accounts, ones already in the CRM are linked, never duplicated | prospecting:write |
| GET | /v1/scrape/runs/:id/rows | The rows: values with the page's exact words, source URL and fetch time; for local businesses, the CRM account each matches | prospecting:read |
| POST | /v1/scrape/runs/:id/start | Start a previewed run in the background | prospecting:write |
| GET | /v1/scrape/settings | Scraping status: whether Apify is on (it waits for approval and a key), this month's Apify cap and spend, the allowlisted actors, the recipes and the sites never scraped | prospecting:read |
| PUT | /v1/scrape/settings | Set the organization's monthly Apify cap in USD (owner; audited) | settings:write |
Examples
GET /v1/scrape/domains
The owner's allow and block rules per domain (sites whose terms forbid scraping are refused whatever the rule)
curl -s "https://api.closefinch.com/v1/scrape/domains" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/scrape/domains`, {
method: "GET",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();PUT /v1/scrape/domains
Allow or block a domain for scraping (owner; audited). Allowed domains may be scraped by agents on any page without a query string
curl -s -X PUT "https://api.closefinch.com/v1/scrape/domains" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/scrape/domains`, {
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/scrape/domains/$DOMAIN
Remove a domain's rule (owner; audited)
curl -s -X DELETE "https://api.closefinch.com/v1/scrape/domains/$DOMAIN" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/scrape/domains/${domain}`, {
method: "DELETE",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();POST /v1/scrape/estimate
What a scrape would cost (model and Apify), without creating it
curl -s -X POST "https://api.closefinch.com/v1/scrape/estimate" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/scrape/estimate`, {
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/scrape/local/csv
Import a CSV of local businesses (name, address, phone, website, category, rating…): deduplicated and matched against the CRM's accounts, then previewed (nothing reaches the CRM until imported)
curl -s -X POST "https://api.closefinch.com/v1/scrape/local/csv" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/scrape/local/csv`, {
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/scrape/runs
Scrape runs, newest first, with row counts
curl -s "https://api.closefinch.com/v1/scrape/runs" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/scrape/runs`, {
method: "GET",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();POST /v1/scrape/runs
Set up a scrape: pages and fields, an Apify actor, a recipe, or a local-business search (Google Maps via Apify). Returns the cost preview; nothing runs until it's started
curl -s -X POST "https://api.closefinch.com/v1/scrape/runs" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/scrape/runs`, {
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/scrape/runs/$ID
A run: its input, status, notes (partial results, refusals, caps), cost and row counts
curl -s "https://api.closefinch.com/v1/scrape/runs/$ID" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/scrape/runs/${id}`, {
method: "GET",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();PUT /v1/scrape/runs/$ID/criteria
Set a run's fit criteria (field, op, value): every row gets a pass / fail / unsure verdict with its reason, judged again now
curl -s -X PUT "https://api.closefinch.com/v1/scrape/runs/$ID/criteria" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/scrape/runs/${id}/criteria`, {
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();POST /v1/scrape/runs/$ID/import
Import a local-business run's rows (all, or the chosen ones) into a static list of accounts: new businesses become accounts, ones already in the CRM are linked, never duplicated
curl -s -X POST "https://api.closefinch.com/v1/scrape/runs/$ID/import" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/scrape/runs/${id}/import`, {
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/scrape/runs/$ID/rows
The rows: values with the page's exact words, source URL and fetch time; for local businesses, the CRM account each matches
curl -s "https://api.closefinch.com/v1/scrape/runs/$ID/rows" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/scrape/runs/${id}/rows`, {
method: "GET",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();POST /v1/scrape/runs/$ID/start
Start a previewed run in the background
curl -s -X POST "https://api.closefinch.com/v1/scrape/runs/$ID/start" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/scrape/runs/${id}/start`, {
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/scrape/settings
Scraping status: whether Apify is on (it waits for approval and a key), this month's Apify cap and spend, the allowlisted actors, the recipes and the sites never scraped
curl -s "https://api.closefinch.com/v1/scrape/settings" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/scrape/settings`, {
method: "GET",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();PUT /v1/scrape/settings
Set the organization's monthly Apify cap in USD (owner; audited)
curl -s -X PUT "https://api.closefinch.com/v1/scrape/settings" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/scrape/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();Request and response schemas: https://www.closefinch.com/openapi.json. All resources: API reference.