Skip to content

API reference

API: Scraping

Markdown version

MethodPathWhat it doesScope
GET/v1/scrape/domainsThe owner's allow and block rules per domain (sites whose terms forbid scraping are refused whatever the rule)prospecting:read
PUT/v1/scrape/domainsAllow or block a domain for scraping (owner; audited). Allowed domains may be scraped by agents on any page without a query stringsettings:write
DELETE/v1/scrape/domains/:domainRemove a domain's rule (owner; audited)settings:write
POST/v1/scrape/estimateWhat a scrape would cost (model and Apify), without creating itprospecting:read
POST/v1/scrape/local/csvImport 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/runsScrape runs, newest first, with row countsprospecting:read
POST/v1/scrape/runsSet 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 startedprospecting:write
GET/v1/scrape/runs/:idA run: its input, status, notes (partial results, refusals, caps), cost and row countsprospecting:read
PUT/v1/scrape/runs/:id/criteriaSet a run's fit criteria (field, op, value): every row gets a pass / fail / unsure verdict with its reason, judged again nowprospecting:write
POST/v1/scrape/runs/:id/importImport 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 duplicatedprospecting:write
GET/v1/scrape/runs/:id/rowsThe rows: values with the page's exact words, source URL and fetch time; for local businesses, the CRM account each matchesprospecting:read
POST/v1/scrape/runs/:id/startStart a previewed run in the backgroundprospecting:write
GET/v1/scrape/settingsScraping 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 scrapedprospecting:read
PUT/v1/scrape/settingsSet 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.

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.