Skip to content

API reference

API: First-party signals

Markdown version

MethodPathWhat it doesScope
GET/v1/accounts/:id/first-partyAn account's website visits (90 days), product use, Stripe customers with spend trend, and expansion proposalsaccounts:read
GET/v1/billing-signalsStripe former-customer and spend-trend settings, the scopes the restricted key needs (read only), and the last pullcustomers:read
PUT/v1/billing-signalsChange Stripe signal settings (owner): on/off, spend window (30, 60 or 90 days), change threshold, minimum baseline, how far back lost deals countbilling:write
GET/v1/billing-signals/customersStripe customers from the last pull: status (active, former), plan, MRR (lost), tenure, cancellation, spend trendcustomers:read
GET/v1/billing-signals/lost-movesContacts from closed-lost deals who now work at another account (or whose email bounces: may have moved)customers:read
POST/v1/billing-signals/pullPull Stripe now (read only; it also runs daily): customers, subscriptions and paid invoicesbilling:write
POST/v1/collect/:keyThe website pixel's endpoint (public; the site key is in the snippet). Needs an allowed Origin and, where required, consent; honours Do Not Track and Global Privacy Control. Answers only ok (no sign-in)—
GET/v1/expansion-proposalsExpansion openings proposed from product use, newest firstcustomers:read
POST/v1/expansion-proposals/:id/acceptAccept an expansion opening: creates the deal (owner: the account's owner) with what the current contract coverscustomers:write
POST/v1/expansion-proposals/:id/dismissDismiss an expansion opening (no other proposal for that account and team for 90 days)customers:write
GET/v1/product-signalsProduct signal settings: signup, plan-limit, seat, team and feature event names; spike and expansion thresholdscustomers:read
PUT/v1/product-signalsChange product signal settings (owner)settings:write
POST/v1/product-signals/runCheck product events for expansion openings now (it also runs every 10 minutes). Proposals only: nothing is created in the CRMcustomers:write
GET/v1/site-trackingWebsite tracking: on/off, consent mode, allowed origins, retention, intent thresholds, the snippet to paste, page tags and the match rate over 30 dayssignals:read
PUT/v1/site-trackingChange website tracking (owner): turn it on, consent mode (EU/UK visitors, or everyone), allowed origins, retention and intent thresholdssettings:write
POST/v1/site-tracking/rotate-keyReplace the site key (owner): the old snippet stops working at oncesettings:write
GET/v1/site-tracking/tagsPage tags: a path, a label and an intent weight (0 = never a signal)signals:read
POST/v1/site-tracking/tagsTag a page (owner), e.g. /pricing as Pricing with weight 80settings:write
DELETE/v1/site-tracking/tags/:idRemove a page tag (owner)settings:write
PATCH/v1/site-tracking/tags/:idChange a page tag (owner)settings:write
POST/v1/site-tracking/tracked-linkA link for your own email to one contact (ra_t: a random token, 14 days, tied to the first browser that opens it; the contact id isn't in the URL). M5 email tracking adds it to links automaticallysignals:write
GET/v1/site-tracking/visitsRecent page views (company level: the account, how it was matched and with what confidence; never an IP address)signals:read

Examples

GET /v1/accounts/$ID/first-party

An account's website visits (90 days), product use, Stripe customers with spend trend, and expansion proposals

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

GET /v1/billing-signals

Stripe former-customer and spend-trend settings, the scopes the restricted key needs (read only), and the last pull

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

PUT /v1/billing-signals

Change Stripe signal settings (owner): on/off, spend window (30, 60 or 90 days), change threshold, minimum baseline, how far back lost deals count

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

Stripe customers from the last pull: status (active, former), plan, MRR (lost), tenure, cancellation, spend trend

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

GET /v1/billing-signals/lost-moves

Contacts from closed-lost deals who now work at another account (or whose email bounces: may have moved)

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

POST /v1/billing-signals/pull

Pull Stripe now (read only; it also runs daily): customers, subscriptions and paid invoices

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

The website pixel's endpoint (public; the site key is in the snippet). Needs an allowed Origin and, where required, consent; honours Do Not Track and Global Privacy Control. Answers only ok. No sign-in, so it sends no key.

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

GET /v1/expansion-proposals

Expansion openings proposed from product use, newest first

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

POST /v1/expansion-proposals/$ID/accept

Accept an expansion opening: creates the deal (owner: the account's owner) with what the current contract covers

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

Dismiss an expansion opening (no other proposal for that account and team for 90 days)

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

Product signal settings: signup, plan-limit, seat, team and feature event names; spike and expansion thresholds

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

PUT /v1/product-signals

Change product signal settings (owner)

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

Check product events for expansion openings now (it also runs every 10 minutes). Proposals only: nothing is created in the CRM

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

Website tracking: on/off, consent mode, allowed origins, retention, intent thresholds, the snippet to paste, page tags and the match rate over 30 days

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

PUT /v1/site-tracking

Change website tracking (owner): turn it on, consent mode (EU/UK visitors, or everyone), allowed origins, retention and intent thresholds

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

Replace the site key (owner): the old snippet stops working at once

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

Page tags: a path, a label and an intent weight (0 = never a signal)

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

POST /v1/site-tracking/tags

Tag a page (owner), e.g. /pricing as Pricing with weight 80

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

Remove a page tag (owner)

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

PATCH /v1/site-tracking/tags/$ID

Change a page tag (owner)

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

POST /v1/site-tracking/tracked-link

A link for your own email to one contact (ra_t: a random token, 14 days, tied to the first browser that opens it; the contact id isn't in the URL). M5 email tracking adds it to links automatically

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

Recent page views (company level: the account, how it was matched and with what confidence; never an IP address)

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