API reference
API: Replies
| Method | Path | What it does | Scope |
|---|---|---|---|
| GET | /v1/follow-ups | Follow-ups after one-off sends and callbacks people asked for, with their state | messages:read |
| PATCH | /v1/follow-ups/:id | Move a follow-up, or mark it done or cancelled | messages:write |
| GET | /v1/inbox | Conversations: needs reply, interested, replies, escalated or done, with a count per view | messages:read |
| GET | /v1/inbox-tags | The organization's conversation tags | messages:read |
| POST | /v1/inbox-tags | Create a tag | messages:write |
| DELETE | /v1/inbox-tags/:id | Delete a tag (it comes off every conversation) | messages:write |
| PATCH | /v1/inbox-tags/:id | Rename or recolor a tag | messages:write |
| GET | /v1/inbox/:contact_id | One conversation: messages in time order, each reply's labels and actions, and the side panel (research, CRM, sequences, meetings) | messages:read |
| POST | /v1/inbox/:contact_id/assign | Give a conversation to a teammate (an escalated one: its current person or an owner, signed in) | messages:write |
| POST | /v1/inbox/:contact_id/deescalate | Clear an escalation: the agent may draft and (within the autopilot rules) answer again (web app only) | messages:write |
| POST | /v1/inbox/:contact_id/status | Mark a conversation done, or reopen it (a new message reopens it too) | messages:write |
| PUT | /v1/inbox/:contact_id/tags | Set a conversation's tags | messages:write |
| PUT | /v1/me/reply-autopilot | Let eligible replies be answered from your mailbox without your approval of each (the organization's autopilot rules still apply) (web app only) | messages:send |
| POST | /v1/replies-eval | Run the reply-label eval set with your model: per-label precision and recall (web app only) | settings:write |
| GET | /v1/replies-stats | Reply handling: by label, time from receipt to answer (autopilot and approved), escalations | messages:read |
| GET | /v1/replies/:id | A reply: triage, labels with confidence and rationale, and what the labels did | messages:read |
| POST | /v1/replies/:id/category | Set a message's category yourself (prospect reply, customer, vendor, internal, automated, newsletter, spam, other): audited; automated, newsletter, spam and internal leave the inbox | messages:write |
| POST | /v1/replies/:id/labels | Correct a reply's labels: audited; actions that are safe to repeat run again | messages:write |
| POST | /v1/replies/:id/remind | Snooze a reply: you're told about it again in this many hours (1–168) unless it's answered or the conversation is done | messages:write |
| GET | /v1/reply-library | Approved answers to objections and questions (autopilot replies must be grounded in one) | messages:read |
| POST | /v1/reply-library | Add an entry (an owner approves it before it grounds a reply) | messages:write |
| DELETE | /v1/reply-library/:id | Delete an entry | messages:write |
| PATCH | /v1/reply-library/:id | Edit an entry (it needs approving again) | messages:write |
| POST | /v1/reply-library/:id/approve | Approve an entry (owners, signed in) (web app only) | settings:write |
| GET | /v1/routing-log | Why each email to a shared address went to whom | messages:read |
| GET | /v1/settings/replies | How replies are labeled, escalated, answered, routed and followed up | messages:read |
| PUT | /v1/settings/replies | Change the reply settings (owners, signed in) (web app only) | settings:write |
| GET | /v1/snoozes | Snoozed conversations coming up (yours, or everyone's for owners) | messages:read |
| POST | /v1/snoozes/:id/cancel | Cancel a snooze (the sequence stays stopped) | messages:write |
| POST | /v1/snoozes/:id/confirm | Confirm (or change) the date a snoozed conversation resumes | messages:write |
Examples
GET /v1/follow-ups
Follow-ups after one-off sends and callbacks people asked for, with their state
curl -s "https://api.closefinch.com/v1/follow-ups" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/follow-ups`, {
method: "GET",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();PATCH /v1/follow-ups/$ID
Move a follow-up, or mark it done or cancelled
curl -s -X PATCH "https://api.closefinch.com/v1/follow-ups/$ID" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/follow-ups/${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();GET /v1/inbox
Conversations: needs reply, interested, replies, escalated or done, with a count per view
curl -s "https://api.closefinch.com/v1/inbox" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/inbox`, {
method: "GET",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();GET /v1/inbox-tags
The organization's conversation tags
curl -s "https://api.closefinch.com/v1/inbox-tags" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/inbox-tags`, {
method: "GET",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();POST /v1/inbox-tags
Create a tag
curl -s -X POST "https://api.closefinch.com/v1/inbox-tags" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/inbox-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/inbox-tags/$ID
Delete a tag (it comes off every conversation)
curl -s -X DELETE "https://api.closefinch.com/v1/inbox-tags/$ID" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/inbox-tags/${id}`, {
method: "DELETE",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();PATCH /v1/inbox-tags/$ID
Rename or recolor a tag
curl -s -X PATCH "https://api.closefinch.com/v1/inbox-tags/$ID" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/inbox-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();GET /v1/inbox/$CONTACT_ID
One conversation: messages in time order, each reply's labels and actions, and the side panel (research, CRM, sequences, meetings)
curl -s "https://api.closefinch.com/v1/inbox/$CONTACT_ID" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/inbox/${contact_id}`, {
method: "GET",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();POST /v1/inbox/$CONTACT_ID/assign
Give a conversation to a teammate (an escalated one: its current person or an owner, signed in)
curl -s -X POST "https://api.closefinch.com/v1/inbox/$CONTACT_ID/assign" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/inbox/${contact_id}/assign`, {
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/inbox/$CONTACT_ID/status
Mark a conversation done, or reopen it (a new message reopens it too)
curl -s -X POST "https://api.closefinch.com/v1/inbox/$CONTACT_ID/status" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/inbox/${contact_id}/status`, {
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();PUT /v1/inbox/$CONTACT_ID/tags
Set a conversation's tags
curl -s -X PUT "https://api.closefinch.com/v1/inbox/$CONTACT_ID/tags" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/inbox/${contact_id}/tags`, {
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/replies-stats
Reply handling: by label, time from receipt to answer (autopilot and approved), escalations
curl -s "https://api.closefinch.com/v1/replies-stats" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/replies-stats`, {
method: "GET",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();GET /v1/replies/$ID
A reply: triage, labels with confidence and rationale, and what the labels did
curl -s "https://api.closefinch.com/v1/replies/$ID" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/replies/${id}`, {
method: "GET",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();POST /v1/replies/$ID/category
Set a message's category yourself (prospect reply, customer, vendor, internal, automated, newsletter, spam, other): audited; automated, newsletter, spam and internal leave the inbox
curl -s -X POST "https://api.closefinch.com/v1/replies/$ID/category" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/replies/${id}/category`, {
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/replies/$ID/labels
Correct a reply's labels: audited; actions that are safe to repeat run again
curl -s -X POST "https://api.closefinch.com/v1/replies/$ID/labels" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/replies/${id}/labels`, {
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/replies/$ID/remind
Snooze a reply: you're told about it again in this many hours (1–168) unless it's answered or the conversation is done
curl -s -X POST "https://api.closefinch.com/v1/replies/$ID/remind" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/replies/${id}/remind`, {
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/reply-library
Approved answers to objections and questions (autopilot replies must be grounded in one)
curl -s "https://api.closefinch.com/v1/reply-library" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/reply-library`, {
method: "GET",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();POST /v1/reply-library
Add an entry (an owner approves it before it grounds a reply)
curl -s -X POST "https://api.closefinch.com/v1/reply-library" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/reply-library`, {
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/reply-library/$ID
Delete an entry
curl -s -X DELETE "https://api.closefinch.com/v1/reply-library/$ID" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/reply-library/${id}`, {
method: "DELETE",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();PATCH /v1/reply-library/$ID
Edit an entry (it needs approving again)
curl -s -X PATCH "https://api.closefinch.com/v1/reply-library/$ID" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/reply-library/${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();GET /v1/routing-log
Why each email to a shared address went to whom
curl -s "https://api.closefinch.com/v1/routing-log" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/routing-log`, {
method: "GET",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();GET /v1/settings/replies
How replies are labeled, escalated, answered, routed and followed up
curl -s "https://api.closefinch.com/v1/settings/replies" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/settings/replies`, {
method: "GET",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();GET /v1/snoozes
Snoozed conversations coming up (yours, or everyone's for owners)
curl -s "https://api.closefinch.com/v1/snoozes" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/snoozes`, {
method: "GET",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();POST /v1/snoozes/$ID/cancel
Cancel a snooze (the sequence stays stopped)
curl -s -X POST "https://api.closefinch.com/v1/snoozes/$ID/cancel" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/snoozes/${id}/cancel`, {
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/snoozes/$ID/confirm
Confirm (or change) the date a snoozed conversation resumes
curl -s -X POST "https://api.closefinch.com/v1/snoozes/$ID/confirm" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/snoozes/${id}/confirm`, {
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();Request and response schemas: https://www.closefinch.com/openapi.json. All resources: API reference.