API reference
API: First-party signals
| Method | Path | What it does | Scope |
|---|---|---|---|
| GET | /v1/accounts/:id/first-party | An account's website visits (90 days), product use, Stripe customers with spend trend, and expansion proposals | accounts:read |
| GET | /v1/billing-signals | Stripe former-customer and spend-trend settings, the scopes the restricted key needs (read only), and the last pull | customers:read |
| 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 | billing:write |
| GET | /v1/billing-signals/customers | Stripe customers from the last pull: status (active, former), plan, MRR (lost), tenure, cancellation, spend trend | customers:read |
| GET | /v1/billing-signals/lost-moves | Contacts from closed-lost deals who now work at another account (or whose email bounces: may have moved) | customers:read |
| POST | /v1/billing-signals/pull | Pull Stripe now (read only; it also runs daily): customers, subscriptions and paid invoices | billing:write |
| 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) | — |
| GET | /v1/expansion-proposals | Expansion openings proposed from product use, newest first | customers:read |
| POST | /v1/expansion-proposals/:id/accept | Accept an expansion opening: creates the deal (owner: the account's owner) with what the current contract covers | customers:write |
| POST | /v1/expansion-proposals/:id/dismiss | Dismiss an expansion opening (no other proposal for that account and team for 90 days) | customers:write |
| GET | /v1/product-signals | Product signal settings: signup, plan-limit, seat, team and feature event names; spike and expansion thresholds | customers:read |
| PUT | /v1/product-signals | Change product signal settings (owner) | settings:write |
| 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 | customers:write |
| 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 | signals:read |
| PUT | /v1/site-tracking | Change website tracking (owner): turn it on, consent mode (EU/UK visitors, or everyone), allowed origins, retention and intent thresholds | settings:write |
| POST | /v1/site-tracking/rotate-key | Replace the site key (owner): the old snippet stops working at once | settings:write |
| GET | /v1/site-tracking/tags | Page tags: a path, a label and an intent weight (0 = never a signal) | signals:read |
| POST | /v1/site-tracking/tags | Tag a page (owner), e.g. /pricing as Pricing with weight 80 | settings:write |
| DELETE | /v1/site-tracking/tags/:id | Remove a page tag (owner) | settings:write |
| PATCH | /v1/site-tracking/tags/:id | Change a page tag (owner) | settings:write |
| 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 | signals:write |
| GET | /v1/site-tracking/visits | Recent 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.