API reference
API: Deals
| Method | Path | What it does | Scope |
|---|---|---|---|
| GET | /v1/deals | List deals (filters: q, owner_id, list_id, linked_to, dismissed, filter[field]=value, filter[field][gte|lte|gt|lt|in|exists]=value) | deals:read |
| POST | /v1/deals | Create a deal | deals:write |
| DELETE | /v1/deals/:id | Archive a record (restore with POST …/restore) | deals:write |
| GET | /v1/deals/:id | Get a record (as_of=ISO time for its values at that moment). A merged record answers 301 with the survivor's id. | deals:read |
| PATCH | /v1/deals/:id | Update values or owner. A merged record answers 410. Pass version for optimistic concurrency. | deals:write |
| POST | /v1/deals/:id/dismiss | Dismiss a noise record so it stops resurfacing (undo with dismissed: false) | deals:write |
| GET | /v1/deals/:id/history | Every change to this record, newest first, with field-level before and after. Values that came from an item now private (or metadata-only) to someone else show as null with redacted: true. | deals:read |
| POST | /v1/deals/:id/merge | Merge other records into this one. They redirect here afterwards. | deals:write |
| GET | /v1/deals/:id/provenance | Where each current value came from (user, API, import, activity, agent or sync). link points at the activity, import row or record behind it. | deals:read |
| POST | /v1/deals/:id/restore | Restore an archived record | deals:write |
| GET | /v1/deals/:id/timeline | Activity about this record, newest first (deleted-at-source items hidden) | activities:read |
| POST | /v1/deals/analyze-write | Before creating or updating: does this record already exist? Returns create, update (with the record to update) or review, with every match (same email, domain, phone, LinkedIn, same or similar name), rows of a batch that repeat each other, and for updates the values that would be overwritten. Agents' creates run this check and are refused when the record exists. | deals:read |
| POST | /v1/deals/bulk | Create up to 25 records. Each row_key (yours alone) is idempotent: the same key and data replays the record it created; the same key with different data is a conflict. | deals:write |
| POST | /v1/deals/dismiss | Dismiss (or undo with dismissed: false) many noise records at once | deals:write |
| POST | /v1/deals/duplicates | Check for existing records before creating or updating (same email, domain, phone, LinkedIn or name) | deals:read |
| GET | /v1/deals/possible-duplicates | Groups of records that look like the same thing (shared email, domain, phone, LinkedIn or exact name), to review and merge | deals:read |
| GET | /v1/deals/schema | JSON Schemas for create and update bodies, including this organization's custom fields | deals:read |
Examples
GET /v1/deals
List deals (filters: q, owner_id, list_id, linked_to, dismissed, filter[field]=value, filter[field][gte|lte|gt|lt|in|exists]=value)
curl -s "https://api.closefinch.com/v1/deals" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/deals`, {
method: "GET",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();POST /v1/deals
Create a deal
curl -s -X POST "https://api.closefinch.com/v1/deals" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/deals`, {
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/deals/$ID
Archive a record (restore with POST …/restore)
curl -s -X DELETE "https://api.closefinch.com/v1/deals/$ID" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/deals/${id}`, {
method: "DELETE",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();GET /v1/deals/$ID
Get a record (as_of=ISO time for its values at that moment). A merged record answers 301 with the survivor's id.
curl -s "https://api.closefinch.com/v1/deals/$ID" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/deals/${id}`, {
method: "GET",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();PATCH /v1/deals/$ID
Update values or owner. A merged record answers 410. Pass version for optimistic concurrency.
curl -s -X PATCH "https://api.closefinch.com/v1/deals/$ID" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/deals/${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/deals/$ID/dismiss
Dismiss a noise record so it stops resurfacing (undo with dismissed: false)
curl -s -X POST "https://api.closefinch.com/v1/deals/$ID/dismiss" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/deals/${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/deals/$ID/history
Every change to this record, newest first, with field-level before and after. Values that came from an item now private (or metadata-only) to someone else show as null with redacted: true.
curl -s "https://api.closefinch.com/v1/deals/$ID/history" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/deals/${id}/history`, {
method: "GET",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();POST /v1/deals/$ID/merge
Merge other records into this one. They redirect here afterwards.
curl -s -X POST "https://api.closefinch.com/v1/deals/$ID/merge" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/deals/${id}/merge`, {
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/deals/$ID/provenance
Where each current value came from (user, API, import, activity, agent or sync). link points at the activity, import row or record behind it.
curl -s "https://api.closefinch.com/v1/deals/$ID/provenance" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/deals/${id}/provenance`, {
method: "GET",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();POST /v1/deals/$ID/restore
Restore an archived record
curl -s -X POST "https://api.closefinch.com/v1/deals/$ID/restore" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/deals/${id}/restore`, {
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/deals/$ID/timeline
Activity about this record, newest first (deleted-at-source items hidden)
curl -s "https://api.closefinch.com/v1/deals/$ID/timeline" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/deals/${id}/timeline`, {
method: "GET",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();POST /v1/deals/analyze-write
Before creating or updating: does this record already exist? Returns create, update (with the record to update) or review, with every match (same email, domain, phone, LinkedIn, same or similar name), rows of a batch that repeat each other, and for updates the values that would be overwritten. Agents' creates run this check and are refused when the record exists.
curl -s -X POST "https://api.closefinch.com/v1/deals/analyze-write" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/deals/analyze-write`, {
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/deals/bulk
Create up to 25 records. Each row_key (yours alone) is idempotent: the same key and data replays the record it created; the same key with different data is a conflict.
curl -s -X POST "https://api.closefinch.com/v1/deals/bulk" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/deals/bulk`, {
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/deals/dismiss
Dismiss (or undo with dismissed: false) many noise records at once
curl -s -X POST "https://api.closefinch.com/v1/deals/dismiss" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/deals/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();POST /v1/deals/duplicates
Check for existing records before creating or updating (same email, domain, phone, LinkedIn or name)
curl -s -X POST "https://api.closefinch.com/v1/deals/duplicates" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/deals/duplicates`, {
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/deals/possible-duplicates
Groups of records that look like the same thing (shared email, domain, phone, LinkedIn or exact name), to review and merge
curl -s "https://api.closefinch.com/v1/deals/possible-duplicates" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/deals/possible-duplicates`, {
method: "GET",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();GET /v1/deals/schema
JSON Schemas for create and update bodies, including this organization's custom fields
curl -s "https://api.closefinch.com/v1/deals/schema" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/deals/schema`, {
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.