# API: Meetings

| Method | Path | What it does | Scope |
|---|---|---|---|
| POST | `/v1/activities/:id/collateral` | Draft collateral from this meeting into a document canvas for you to review: a recap, proposal outline, mutual action plan or competitor comparison | `transcripts:write` |
| GET | `/v1/activities/:id/outcome` | A conversation's outcome: summary, action items (with their tasks), follow-up draft, sentiment, disposition, tags, analyzer results — each item citing the transcript | `transcripts:read` |
| POST | `/v1/activities/:id/outcome/rerun` | Make the conversation's outcome again (e.g. after changing analyzers or tags) | `transcripts:write` |
| PUT | `/v1/activities/:id/outcome/tags` | Set a conversation's tags by hand (kept when the outcome is made again) | `transcripts:write` |
| POST | `/v1/activities/:id/outcome/tasks` | Turn a conversation's action items (all, or the ones named by key) into tasks | `transcripts:write` |
| GET | `/v1/conversation-analyzers` | Post-call analyzers: structured values pulled from every conversation (or those with a tag) | `transcripts:read` |
| POST | `/v1/conversation-analyzers` | Add an analyzer (owner) | `settings:write` |
| DELETE | `/v1/conversation-analyzers/:id` | Delete an analyzer (owner); past results stay on their outcomes | `settings:write` |
| PATCH | `/v1/conversation-analyzers/:id` | Change or turn off an analyzer (owner) | `settings:write` |
| GET | `/v1/conversation-tags` | Conversation tags (the description guides auto-tagging) | `transcripts:read` |
| POST | `/v1/conversation-tags` | Add a tag (owner) | `settings:write` |
| DELETE | `/v1/conversation-tags/:id` | Delete a tag (owner) | `settings:write` |
| POST | `/v1/conversations/reanalyze` | Make outcomes for conversations in a date range (optionally on a record) (owner): an estimate first (count, tokens, cost), then confirm to queue them | `settings:write` |
| DELETE | `/v1/conversations/reanalyze/:id` | Cancel a re-analysis batch (what hasn't started yet) (owner) | `settings:write` |
| GET | `/v1/conversations/reanalyze/:id` | A re-analysis batch's progress (jobs by status) | `transcripts:read` |
| GET | `/v1/deals/:id/contact-roles` | Each contact's role on a deal (champion, economic buyer…): set by a person or proposed from a conversation | `deals:read` |
| PUT | `/v1/deals/:id/contact-roles` | Set (or clear, role null) a contact's role on a deal; a person's call isn't replaced by conversations | `deals:write` |
| GET | `/v1/insight-themes` | The insight taxonomy (themes per kind; grows as conversations name new ones, editable) | `transcripts:read` |
| PATCH | `/v1/insight-themes/:id` | Rename a theme or merge it into another (its insights move) (owner) | `settings:write` |
| GET | `/v1/insights` | Insights from conversations (feedback, feature requests, objections, competitors, product gaps, lost/churn reasons), each with its quote | `transcripts:read` |
| GET | `/v1/insights/summary` | Insight counts by kind and theme (and competitor), over a period, with deals won/lost/open alongside | `transcripts:read` |
| GET | `/v1/meetings` | List meetings (filters: q, owner_id, list_id, linked_to, dismissed, filter[field]=value, filter[field][gte\|lte\|gt\|lt\|in\|exists]=value) | `activities:read` |
| POST | `/v1/meetings` | Create a meeting | `activities:write` |
| DELETE | `/v1/meetings/:id` | Archive a record (restore with POST …/restore) | `activities:write` |
| GET | `/v1/meetings/:id` | Get a record (as_of=ISO time for its values at that moment). A merged record answers 301 with the survivor's id. | `activities:read` |
| PATCH | `/v1/meetings/:id` | Update values or owner. A merged record answers 410. Pass version for optimistic concurrency. | `activities:write` |
| POST | `/v1/meetings/:id/dismiss` | Dismiss a noise record so it stops resurfacing (undo with dismissed: false) | `activities:write` |
| GET | `/v1/meetings/: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. | `activities:read` |
| POST | `/v1/meetings/:id/merge` | Merge other records into this one. They redirect here afterwards. | `activities:write` |
| GET | `/v1/meetings/: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. | `activities:read` |
| POST | `/v1/meetings/:id/restore` | Restore an archived record | `activities:write` |
| GET | `/v1/meetings/:id/timeline` | Activity about this record, newest first (deleted-at-source items hidden) | `activities:read` |
| POST | `/v1/meetings/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. | `activities:read` |
| POST | `/v1/meetings/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. | `activities:write` |
| POST | `/v1/meetings/dismiss` | Dismiss (or undo with dismissed: false) many noise records at once | `activities:write` |
| POST | `/v1/meetings/duplicates` | Check for existing records before creating or updating (same email, domain, phone, LinkedIn or name) | `activities:read` |
| GET | `/v1/meetings/possible-duplicates` | Groups of records that look like the same thing (shared email, domain, phone, LinkedIn or exact name), to review and merge | `activities:read` |
| GET | `/v1/meetings/schema` | JSON Schemas for create and update bodies, including this organization's custom fields | `activities:read` |
| GET | `/v1/settings/collateral-templates` | The template each kind of collateral follows (the org's, or the built-in default) | `transcripts:read` |
| PUT | `/v1/settings/collateral-templates/:kind` | Set the org's template for a kind of collateral (owner; body null = back to the default) | `settings:write` |

## Examples

### POST /v1/activities/$ID/collateral

Draft collateral from this meeting into a document canvas for you to review: a recap, proposal outline, mutual action plan or competitor comparison

```bash
curl -s -X POST "https://api.closefinch.com/v1/activities/$ID/collateral" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/activities/${id}/collateral`, {
  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/activities/$ID/outcome

A conversation's outcome: summary, action items (with their tasks), follow-up draft, sentiment, disposition, tags, analyzer results — each item citing the transcript

```bash
curl -s "https://api.closefinch.com/v1/activities/$ID/outcome" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/activities/${id}/outcome`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### POST /v1/activities/$ID/outcome/rerun

Make the conversation's outcome again (e.g. after changing analyzers or tags)

```bash
curl -s -X POST "https://api.closefinch.com/v1/activities/$ID/outcome/rerun" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/activities/${id}/outcome/rerun`, {
  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/activities/$ID/outcome/tags

Set a conversation's tags by hand (kept when the outcome is made again)

```bash
curl -s -X PUT "https://api.closefinch.com/v1/activities/$ID/outcome/tags" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/activities/${id}/outcome/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();
```

### POST /v1/activities/$ID/outcome/tasks

Turn a conversation's action items (all, or the ones named by key) into tasks

```bash
curl -s -X POST "https://api.closefinch.com/v1/activities/$ID/outcome/tasks" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/activities/${id}/outcome/tasks`, {
  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/conversation-analyzers

Post-call analyzers: structured values pulled from every conversation (or those with a tag)

```bash
curl -s "https://api.closefinch.com/v1/conversation-analyzers" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/conversation-analyzers`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### POST /v1/conversation-analyzers

Add an analyzer (owner)

```bash
curl -s -X POST "https://api.closefinch.com/v1/conversation-analyzers" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/conversation-analyzers`, {
  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/conversation-analyzers/$ID

Delete an analyzer (owner); past results stay on their outcomes

```bash
curl -s -X DELETE "https://api.closefinch.com/v1/conversation-analyzers/$ID" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/conversation-analyzers/${id}`, {
  method: "DELETE",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### PATCH /v1/conversation-analyzers/$ID

Change or turn off an analyzer (owner)

```bash
curl -s -X PATCH "https://api.closefinch.com/v1/conversation-analyzers/$ID" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/conversation-analyzers/${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/conversation-tags

Conversation tags (the description guides auto-tagging)

```bash
curl -s "https://api.closefinch.com/v1/conversation-tags" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/conversation-tags`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### POST /v1/conversation-tags

Add a tag (owner)

```bash
curl -s -X POST "https://api.closefinch.com/v1/conversation-tags" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/conversation-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/conversation-tags/$ID

Delete a tag (owner)

```bash
curl -s -X DELETE "https://api.closefinch.com/v1/conversation-tags/$ID" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/conversation-tags/${id}`, {
  method: "DELETE",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### POST /v1/conversations/reanalyze

Make outcomes for conversations in a date range (optionally on a record) (owner): an estimate first (count, tokens, cost), then confirm to queue them

```bash
curl -s -X POST "https://api.closefinch.com/v1/conversations/reanalyze" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/conversations/reanalyze`, {
  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/conversations/reanalyze/$ID

Cancel a re-analysis batch (what hasn't started yet) (owner)

```bash
curl -s -X DELETE "https://api.closefinch.com/v1/conversations/reanalyze/$ID" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/conversations/reanalyze/${id}`, {
  method: "DELETE",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### GET /v1/conversations/reanalyze/$ID

A re-analysis batch's progress (jobs by status)

```bash
curl -s "https://api.closefinch.com/v1/conversations/reanalyze/$ID" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/conversations/reanalyze/${id}`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### GET /v1/deals/$ID/contact-roles

Each contact's role on a deal (champion, economic buyer…): set by a person or proposed from a conversation

```bash
curl -s "https://api.closefinch.com/v1/deals/$ID/contact-roles" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/deals/${id}/contact-roles`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### PUT /v1/deals/$ID/contact-roles

Set (or clear, role null) a contact's role on a deal; a person's call isn't replaced by conversations

```bash
curl -s -X PUT "https://api.closefinch.com/v1/deals/$ID/contact-roles" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/deals/${id}/contact-roles`, {
  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/insight-themes

The insight taxonomy (themes per kind; grows as conversations name new ones, editable)

```bash
curl -s "https://api.closefinch.com/v1/insight-themes" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/insight-themes`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### PATCH /v1/insight-themes/$ID

Rename a theme or merge it into another (its insights move) (owner)

```bash
curl -s -X PATCH "https://api.closefinch.com/v1/insight-themes/$ID" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/insight-themes/${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/insights

Insights from conversations (feedback, feature requests, objections, competitors, product gaps, lost/churn reasons), each with its quote

```bash
curl -s "https://api.closefinch.com/v1/insights" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/insights`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### GET /v1/insights/summary

Insight counts by kind and theme (and competitor), over a period, with deals won/lost/open alongside

```bash
curl -s "https://api.closefinch.com/v1/insights/summary" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/insights/summary`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### GET /v1/meetings

List meetings (filters: q, owner_id, list_id, linked_to, dismissed, filter[field]=value, filter[field][gte|lte|gt|lt|in|exists]=value)

```bash
curl -s "https://api.closefinch.com/v1/meetings" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/meetings`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### POST /v1/meetings

Create a meeting

```bash
curl -s -X POST "https://api.closefinch.com/v1/meetings" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/meetings`, {
  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/meetings/$ID

Archive a record (restore with POST …/restore)

```bash
curl -s -X DELETE "https://api.closefinch.com/v1/meetings/$ID" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/meetings/${id}`, {
  method: "DELETE",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### GET /v1/meetings/$ID

Get a record (as_of=ISO time for its values at that moment). A merged record answers 301 with the survivor's id.

```bash
curl -s "https://api.closefinch.com/v1/meetings/$ID" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/meetings/${id}`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### PATCH /v1/meetings/$ID

Update values or owner. A merged record answers 410. Pass version for optimistic concurrency.

```bash
curl -s -X PATCH "https://api.closefinch.com/v1/meetings/$ID" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/meetings/${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/meetings/$ID/dismiss

Dismiss a noise record so it stops resurfacing (undo with dismissed: false)

```bash
curl -s -X POST "https://api.closefinch.com/v1/meetings/$ID/dismiss" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/meetings/${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/meetings/$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.

```bash
curl -s "https://api.closefinch.com/v1/meetings/$ID/history" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/meetings/${id}/history`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### POST /v1/meetings/$ID/merge

Merge other records into this one. They redirect here afterwards.

```bash
curl -s -X POST "https://api.closefinch.com/v1/meetings/$ID/merge" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/meetings/${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/meetings/$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.

```bash
curl -s "https://api.closefinch.com/v1/meetings/$ID/provenance" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/meetings/${id}/provenance`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### POST /v1/meetings/$ID/restore

Restore an archived record

```bash
curl -s -X POST "https://api.closefinch.com/v1/meetings/$ID/restore" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/meetings/${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/meetings/$ID/timeline

Activity about this record, newest first (deleted-at-source items hidden)

```bash
curl -s "https://api.closefinch.com/v1/meetings/$ID/timeline" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/meetings/${id}/timeline`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### POST /v1/meetings/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.

```bash
curl -s -X POST "https://api.closefinch.com/v1/meetings/analyze-write" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/meetings/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/meetings/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.

```bash
curl -s -X POST "https://api.closefinch.com/v1/meetings/bulk" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/meetings/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/meetings/dismiss

Dismiss (or undo with dismissed: false) many noise records at once

```bash
curl -s -X POST "https://api.closefinch.com/v1/meetings/dismiss" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/meetings/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/meetings/duplicates

Check for existing records before creating or updating (same email, domain, phone, LinkedIn or name)

```bash
curl -s -X POST "https://api.closefinch.com/v1/meetings/duplicates" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/meetings/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/meetings/possible-duplicates

Groups of records that look like the same thing (shared email, domain, phone, LinkedIn or exact name), to review and merge

```bash
curl -s "https://api.closefinch.com/v1/meetings/possible-duplicates" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/meetings/possible-duplicates`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### GET /v1/meetings/schema

JSON Schemas for create and update bodies, including this organization's custom fields

```bash
curl -s "https://api.closefinch.com/v1/meetings/schema" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/meetings/schema`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### GET /v1/settings/collateral-templates

The template each kind of collateral follows (the org's, or the built-in default)

```bash
curl -s "https://api.closefinch.com/v1/settings/collateral-templates" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/settings/collateral-templates`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### PUT /v1/settings/collateral-templates/$KIND

Set the org's template for a kind of collateral (owner; body null = back to the default)

```bash
curl -s -X PUT "https://api.closefinch.com/v1/settings/collateral-templates/$KIND" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/settings/collateral-templates/${kind}`, {
  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](https://www.closefinch.com/openapi.json). All resources: [API reference](https://www.closefinch.com/docs/api).
