> ## Documentation Index
> Fetch the complete documentation index at: https://docs.salesfinity.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# API Reference

> Authenticate, page, handle errors and receive webhooks with the Salesfinity REST API, and find every operation in one index.

The Salesfinity API is a JSON-over-HTTPS REST API for the Salesfinity parallel dialer. Use it to
manage contact lists, run outbound sequences end to end, read call logs and AI call scores, pull
team and SDR analytics, work with notes, and enrich phone numbers and email addresses. Everything
on this page is plain text, so a person skimming, a search crawler, and an autonomous agent all
get the same answer without running any JavaScript.

<CardGroup cols={3}>
  <Card title="Make your first call" icon="rocket" href="/developers">
    Get a key and read your team in five minutes.
  </Card>

  <Card title="Handle errors" icon="triangle-exclamation" href="/api-reference/errors">
    The JSON error body and what to do about each status.
  </Card>

  <Card title="Stay under the limits" icon="gauge" href="/api-reference/rate-limits">
    Per-team budgets and how to pace a bulk job.
  </Card>
</CardGroup>

## At a glance

| | |
| - | - |
| **Base URL** | `https://client-api.salesfinity.co` |
| **Authentication** | `x-api-key` request header |
| **Media type** | `application/json` on requests and responses |
| **Rate limits** | Per team, per minute, shared by every key on the team. See [Rate limits](/api-reference/rate-limits) |
| **OpenAPI description** | [`/api-reference/openapi.json`](/api-reference/openapi.json) (OpenAPI 3.0.1) |
| **Changes** | [Changelog](/changelog) |
| **Developer portal** | [Keys, quickstarts, testing, client patterns](/developers) |
| **Support** | [hello@salesfinity.co](mailto:hello@salesfinity.co) · [support.salesfinity.ai](https://support.salesfinity.ai) |

## Quickstart

Generate a key in the Salesfinity dashboard under
[Settings → Connections → API & Webhooks](https://web.salesfinity.co/dashboard/settings?tab=connections)
(**Create New API Key**), then confirm it works by reading the team it belongs to. Every key is
scoped to exactly one team, and every response is filtered to that team.

```bash theme={"system"}
curl https://client-api.salesfinity.co/v1/team \
  --header 'x-api-key: YOUR_API_KEY'
```

A successful call returns the team under `data`, with each member's user record, status and
license:

```json theme={"system"}
{
  "data": {
    "_id": "64b7f0c2e4a1f2a3b4c5d6e7",
    "name": "Acme Outbound",
    "users": [
      {
        "user": {
          "_id": "507f1f77bcf86cd799439011",
          "email": "dana@acme.com",
          "first_name": "Dana",
          "last_name": "Reyes"
        },
        "status": "active",
        "license": "gold"
      }
    ]
  }
}
```

Keep the member `user._id` values: writes that act as a person, such as creating a list, writing
a note, or any Sequencer write, take one as `user_id`. If the key is missing or wrong you get an
HTTP 403 with a JSON body rather than an HTML error page — see [Errors](/api-reference/errors).

Once the key works, the usual next step is to list the team's contact lists and then read one:

```bash theme={"system"}
# Page 1 of the team's CSV contact lists
curl 'https://client-api.salesfinity.co/v1/contact-lists/csv?page=1&limit=10' \
  --header 'x-api-key: YOUR_API_KEY'

# One list, including the contacts inside it (50 per page by default)
curl 'https://client-api.salesfinity.co/v1/contact-lists/csv/CONTACT_LIST_ID' \
  --header 'x-api-key: YOUR_API_KEY'
```

## Authentication

Every operation requires an API key in the `x-api-key` header. There is no OAuth flow and no
bearer token. Keys are long-lived until you revoke them in the dashboard.

A missing, malformed, revoked, or wrong-team key returns **HTTP 403 `Forbidden`**, not 401. That
is worth encoding in client code, because the conventional "retry auth on 401" branch will never
fire against this API.

```json theme={"system"}
{
  "message": "Forbidden resource",
  "error": "Forbidden",
  "statusCode": 403,
  "request_id": "0f6d3c52-9f3e-4c1a-a4b8-2b1f7e5d9c10"
}
```

Because a key is team-scoped, requesting a resource that belongs to a different team returns
**404 Not Found** rather than 403 — the API does not confirm that records outside your team exist.

Some requests fail before the key is read. A path that matches no route returns **404** with a
`message` of the form `Cannot GET /v1/...`, with or without a key. A body that is not valid JSON
returns **400**, and one over the size limit returns **413**.

There is no separate sandbox host. See the [developer portal](/developers#test-safely) for how
to test against live data safely.

## Conventions

| Concern | Convention |
| - | - |
| Media type | `application/json` on requests and responses |
| Request size | Up to 10 MB on `/v1/contact-lists` and `/v2/sequencer`, 1 MB everywhere else. A larger body gets **413** |
| Unknown fields | A body field the operation does not define is rejected with **400** (`property <name> should not exist`). Most endpoints treat an unknown query parameter the same way. The exceptions are `GET /v1/call-log`, `GET /v1/scored-calls`, `GET /v1/contact-lists/csv` and `GET /v1/contact-lists/csv/{id}`: they do not validate their query, so an unknown parameter is ignored and a value outside the documented range is not refused |
| Acting as a person | Writes that record a person take `user_id`, a team member's user ID from [`GET /v1/team`](/api-reference/endpoint/get-team). Contact lists and notes answer **400** for someone not on the team; the Sequencer answers **403** unless the member is active |
| Success status | A `POST` returns **201** unless its reference page says **200**. Treat any 2xx as success |
| Pagination | `page` (1-based) and `limit`. Defaults, maximums and the response envelope differ by endpoint family. See [Pagination](#pagination) |
| Sorting | `sort=field` ascending, `sort=-field` descending, for example `sort=-createdAt`, on the v1 lists that take `sort`. `GET /v2/sequencer/tasks` takes a named `sort` with a separate `direction` |
| Filtering | Call logs and CSV contact lists take bracketed parameters such as `filters[start_date]`, `filters[user_ids]` and `filters[user]`. Every other endpoint takes plain query parameters such as `user_ids` or `state` |
| IDs | Most IDs are 24-character hexadecimal strings. Exceptions: disposition IDs and sending-mailbox IDs are integers, CRM sequence IDs are the CRM's own, and enrollment-run IDs are `enroll_` followed by 24 hexadecimal characters |
| Errors | Always JSON, always `{ message, error, statusCode, request_id }` |
| Request IDs | Every response carries an `X-Request-Id` header. Send your own to trace a request |
| Rate limits | Per team, per minute, shared by every key on the team. See [Rate limits](/api-reference/rate-limits) |
| Retrying writes | Sequencer `POST`s accept an `Idempotency-Key` header. Other `POST`s are not idempotent |
| Browsers | Any origin may call the API, and `X-RateLimit-*`, `Retry-After` and `X-Request-Id` are readable from scripts. A key in browser code is visible to anyone who loads the page, so call the API from a server |

## Pagination

List endpoints take `page` (1-based) and `limit` as query parameters. Each operation's `limit`
parameter states its default and maximum. Most v1 lists default to 10, the contacts inside a list
to 50, and CRM sequences to 100. A `limit` above the maximum is treated as the maximum: 100 on
every list, 200 for sending mailboxes and 25 for enrollment runs. Every page says the `limit` it
used, so compare it with what you asked for. A `limit` that is not a positive number, or a
`/v2/sequencer` `page` over 10,000, fails with **400**.

The response envelope depends on the endpoint family:

| Endpoints | Response shape | You have the last page when |
| - | - | - |
| Scored calls, and every paged `/v2/sequencer` list | `{ data, pagination: { total, page, limit, pages } }` | `page` is at least `pagination.pages` |
| Call logs | `{ data, pagination: { total, page, limit, pages } }` when any `filters[...]` parameter is sent; `{ data, pagination: { total, page, limit, next } }` when none is | `page × limit` is at least `pagination.total` |
| CSV contact lists, the contacts inside one list, follow-up tasks | `{ data, pagination: { total, page, limit, next } }` | `pagination.next` is `null` |
| Snoozed contacts | `{ data, total, page, limit, next }` | `next` is `null` |
| Analytics by contact list and by SDR | `{ totalCount, data, page, limit, next, prev }` | `next` is `null` |
| CRM sequences (`GET /v1/sequences`) | `{ data, pagination: { total, page, limit } }` | `page × limit` is at least `pagination.total` |

A few short `/v2/sequencer` lists are not paged and return a plain array: a sequence's steps, the
team's policies, a task's events (the latest 200), and enrollment runs (the most recent, up to
`limit`, default 10, at most 25).

```bash theme={"system"}
# Walk every page of a Sequencer list
page=1
while :; do
  body=$(curl -s "https://client-api.salesfinity.co/v2/sequencer/tasks?page=$page&limit=100" \
    --header 'x-api-key: YOUR_API_KEY')
  echo "$body" | jq -c '.data[]'
  [ "$page" -ge "$(echo "$body" | jq '.pagination.pages')" ] && break
  page=$((page + 1))
done
```

## Errors

Every error response, on every endpoint and every status code, uses the same JSON envelope:

| Field | Type | Description |
| - | - | - |
| `message` | string or string array | Human-readable description. An array with one entry per invalid field when request validation fails. |
| `error` | string | Stable HTTP reason phrase, for example `Forbidden` or `Not Found`. Branch on this rather than on `message`. |
| `statusCode` | integer | HTTP status code, repeated in the body so it survives transports that drop it. |
| `request_id` | string | Identifies the request; the same value as the `X-Request-Id` response header. Include it when you contact support. |

| Status | `error` | When it happens | What to do |
| - | - | - | - |
| 400 | `Bad Request` | Body or query parameters failed validation, or the body is not valid JSON | Read `message`; a validation failure lists each field |
| 402 | `Payment Required` | Team has no enrichment credits left | Ask Salesfinity to add team enrichment credits, then retry |
| 403 | `Forbidden` | API key missing, malformed, revoked, or for another team; or the acting `user_id` may not do this | Fix the `x-api-key` header, or act as a member who may |
| 404 | `Not Found` | Unknown route, or a resource another team owns | Check the path and the ID |
| 409 | `Conflict` | An `Idempotency-Key` was reused for a different request or its first request is still running, or the record's state rules the action out | Send a new key, retry the same one after a moment, or change the record first |
| 413 | `Payload Too Large` | Body over 10 MB (contact lists, Sequencer) or 1 MB (everything else) | Send fewer records per request |
| 422 | `Unprocessable Entity` | The Sequencer's rules refuse the request, for example enabling a sequence with no steps | Fix what `message` names |
| 429 | `Too Many Requests` | The team went over a [rate limit](/api-reference/rate-limits) | Wait for the seconds in `Retry-After`, then retry |
| 500 | `Internal Server Error` | Fault on the Salesfinity side | Retry with backoff, then contact support |
| 502, 504 | `Bad Gateway`, `Gateway Timeout` | The Sequencer or the enrichment service could not be reached (502), or the Sequencer did not answer within 55 seconds (504) | Retry with backoff; check state before retrying a create |

Two rarer statuses are covered on the [Errors](/api-reference/errors#other-statuses) page: **405**
from `/v2/sequencer` during planned maintenance, and **503** when enabling a sequence briefly cannot
set up email sending. Retry both later.

Branch on `error` or `statusCode` rather than on `message`. Retry **429** and **5xx** with
exponential backoff; **400**, **402**, **403**, **404**, **413** and **422** will not succeed on an
identical retry. Outside the Sequencer, `POST` endpoints are not idempotent, so confirm state with
a `GET` before retrying a create. Sequencer `POST`s accept an `Idempotency-Key` header that makes
a retry safe. The full envelope, per-status examples, and recovery steps are on the
[Errors](/api-reference/errors) page.

## Rate limits

Limits are per team and per minute, and every API key on the team shares them. Every response to an
authenticated request reports what is left in `X-RateLimit-*` headers, and a **429** says how long
to wait in `Retry-After`. [Rate limits](/api-reference/rate-limits) lists the limit for each group
of routes and shows how to pace a bulk job.

## Webhooks

Webhook subscriptions are created and managed in the Salesfinity dashboard, not through this API:
[Settings → Connections → API & Webhooks](https://web.salesfinity.co/dashboard/settings?tab=connections),
then **Create new** under **Webhooks**. A
subscription has a name, one or more events, the call dispositions it applies to, and a public
`http` or `https` URL; `localhost` and private, loopback or link-local addresses are refused.
Click a subscription in that list to see its delivery log.

| Event | Sent when |
| - | - |
| `CALL_LOGGED` | A rep logs a call. Sent only for calls whose disposition is one of those ticked on the subscription |
| `CONTACT_SNOOZED` | A contact is snoozed |
| `SEQUENCE_CONTACT_ENROLLED` | A contact is added to a sequence |
| `SEQUENCE_CONTACT_PAUSED` | An enrollment is paused, by a rep or by a rule |
| `SEQUENCE_CONTACT_FINISHED` | A contact leaves a sequence: replied, un-enrolled, or past the last step |
| `SEQUENCE_APPROVAL_REQUESTED` | A rule holds an enrollment for approval |
| `SEQUENCE_TASK_CREATED` | A step comes due and creates a task for the enrollment's owner |
| `SEQUENCE_TASK_COMPLETED` | A to-do or email task is completed. A completed call task is recorded as a call and does not send this event |
| `SEQUENCE_TASK_SKIPPED` | A task is skipped by a rep, expires at its auto-skip deadline, or is cancelled because the enrollment ended (`details.cancelled` is then `true`) |
| `SEQUENCE_EMAIL_SENT` | A sequence email is sent |
| `SEQUENCE_EMAIL_REPLIED` | A contact replies to a sequence email |
| `SEQUENCE_EMAIL_BOUNCED` | A sequence email bounces |
| `SEQUENCE_EMAIL_OPTED_OUT` | A contact unsubscribes; they are added to the suppression list |

Each delivery is a `POST` with a JSON body of the form `{ "event": "...", "payload": { ... } }`.
For `CALL_LOGGED` and `CONTACT_SNOOZED`, `payload` is the call log or the snoozed contact. For
the `SEQUENCE_*` events it has the same shape every time:

```json theme={"system"}
{
  "event": "SEQUENCE_EMAIL_REPLIED",
  "payload": {
    "occurred_at": "2026-10-02T14:03:11.000Z",
    "sequence_id": "66f1c0a2b3d4e5f601234567",
    "sequence_step_id": "66f1c0a2b3d4e5f601234568",
    "enrollment_id": "66f1c0a2b3d4e5f601234569",
    "task_id": null,
    "contact": {
      "id": "66f1c0a2b3d4e5f60123456a",
      "first_name": "Dana",
      "last_name": "Reyes",
      "email": "dana@acme.com",
      "company": "66f1c0a2b3d4e5f60123456b",
      "title": "VP Sales"
    },
    "details": { "category": "interested", "confidence": 0.94 }
  }
}
```

The IDs that do not apply to an event are `null`, and `occurred_at` is an ISO 8601 time in UTC.
`contact` is a short identifier, not the full record: its `company` is the company's ID, and a
field the contact does not have is left out. It is `null` when the event has no contact, and only
`{ "id": ... }` when the contact no longer exists. `details` carries event-specific data, such as a
reply's `category` and `confidence` in the example, is `null` when there is none, and can gain keys
over time, so treat every key in it as optional. For a task event written by the cadence engine,
`task_id` is `null` and the task's ID is in `details.task`; read both.

Delivery rules:

* **Headers.** Every delivery has `content-type: application/json` and an
  `x-salesfinity-event-id` header, `evt_` followed by 32 hexadecimal characters.
* **Retries.** An attempt that times out, cannot connect, or gets a 429 or a 5xx is retried, up to
  3 attempts in total: after about half a second, then after about one second, each plus up to half
  a second of jitter. Every attempt for one event finishes within about 30 seconds, so an endpoint
  that is down for longer misses it; reconcile through the API after an outage. Any other 4xx is
  not retried; the event is dropped and recorded in the delivery log.
* **Duplicates.** The event ID is the same on every attempt and on any redelivery of one event, so
  the same event can arrive more than once. Record the IDs you have processed and skip repeats.
* **Timeouts.** Each attempt waits at most 10 seconds for your response. Answer with a 2xx
  quickly and do the work afterwards.
* **Ordering.** Subscriptions are delivered independently and events are not ordered. Use
  `occurred_at`, not arrival order.
* **Signatures.** Subscriptions created since signing was introduced also send
  `x-salesfinity-signature`: `sha256=` followed by the HMAC-SHA256 of the raw body. The dashboard
  does not show the signing secret, so the signature cannot be checked yet. Until it can, put a
  long random token in the subscription URL and reject requests that do not carry it.

The enrichment endpoints are separate from webhooks: they accept a per-request `callback_url`
rather than a standing subscription, and those callbacks carry neither header above. See
[Start an email enrichment](/api-reference/endpoint/enrich-email) and
[Start a phone enrichment](/api-reference/endpoint/enrich-phone).

## What you can do with the API

The REST API exposes 114 operations across 21 groups. Every operation has a unique `operationId`, a
description, typed parameters, and a JSON response schema in the OpenAPI description.

| Group | Operations | What it covers |
| - | - | - |
| [Contact Lists](/api-reference/endpoint/get-contact-lists-csv) | 8 | Create, read, merge, and delete CSV contact lists; add and remove the contacts inside them; refill a list's dialing queue from its saved contacts |
| [Notes](/api-reference/endpoint/create-note) | 5 | Attach freeform notes to a person or company, list them, edit or delete your own, and toggle pins |
| [Snoozed Contacts](/api-reference/endpoint/get-snoozed-contacts) | 5 | Read and manage contacts held out of the dialing queue, by ID or LinkedIn username |
| [Enrichment](/api-reference/endpoint/enrich-email) | 5 | Start an asynchronous phone or email lookup, poll its result, and check credit balance |
| [Analytics](/api-reference/endpoint/analytics-overview) | 3 | Aggregated call metrics with growth rates, plus breakdowns by contact list and by SDR |
| [Call Logs](/api-reference/endpoint/call-log) | 2 | Paginated call history with filtering and sorting, and single-call lookup |
| [Scored Calls](/api-reference/endpoint/scored-calls) | 2 | AI-scored calls with per-facet scoring and coaching recommendations |
| [Dispositions](/api-reference/endpoint/get-dispositions) | 2 | Default and custom call outcomes configured for the team |
| [CRM Sequences](/api-reference/endpoint/get-sequences) | 2 | Sequence names observed on the team's call logs, from an external CRM. Not the Sequencer — see below |
| [Sequencer Sequences](/api-reference/endpoint/list-sequencer-sequences) | 12 | Build, configure, enable and duplicate cadences, add contacts, and read analytics |
| [Sequencer Steps](/api-reference/endpoint/list-sequencer-steps) | 6 | The ordered steps that make up a cadence |
| [Sequencer Templates](/api-reference/endpoint/list-sequencer-templates) | 6 | Reusable email subjects and bodies |
| [Sequencer Enrollments](/api-reference/endpoint/list-sequencer-enrollments) | 16 | Contacts inside a sequence, their timelines, and the verbs that move them |
| [Sequencer Enrolment Runs](/api-reference/endpoint/preview-sequencer-enrolment) | 5 | Preview a batch, then enroll up to 5,000 contacts in the background |
| [Sequencer Tasks](/api-reference/endpoint/list-sequencer-tasks) | 17 | The rep task queue, including call tasks and one-off tasks |
| [Sequencer Suppression](/api-reference/endpoint/list-sequencer-suppression) | 4 | The team do-not-contact list |
| [Sequencer Policies](/api-reference/endpoint/list-sequencer-policies) | 8 | Rules of engagement: what may be enrolled, and what happens at each step |
| [Sequencer Settings](/api-reference/endpoint/get-sequencer-settings) | 3 | Sequencer settings and sending mailboxes, read-only |
| [Teams](/api-reference/endpoint/get-team) | 1 | The team that owns the API key, with members, statuses, and licenses |
| [Follow-up Tasks](/api-reference/endpoint/get-follow-ups) | 1 | Follow-up tasks created from call outcomes |
| [Custom Fields](/api-reference/endpoint/get-custom-fields) | 1 | Custom field mappings configured for the team |

<Note>
  The groups that start with **Sequencer** run the Salesfinity Sequencer, which is in early access.
  Changes that can affect an integration are listed in the [changelog](/changelog).
</Note>

## Complete endpoint index

Every operation in the API, with its HTTP method, path, and reference page. This table is
generated from the OpenAPI description, so it is always in sync with the spec.

### Contact Lists

| Method | Path | Operation | Description |
| - | - | - | - |
| `POST` | `/v1/contact-lists` | [Create a contact list](/api-reference/endpoint/create-list) | Creates a contact list owned by the team member in `user_id` and fills its dialing queue with the same contacts |
| `POST` | `/v1/contact-lists/{id}` | [Add a contact to a list](/api-reference/endpoint/add-contact) | Appends one contact to a saved list |
| `DELETE` | `/v1/contact-lists/{id}/contacts/{contactId}` | [Remove a contact from a list](/api-reference/endpoint/remove-contact) | Removes one contact from a saved list |
| `POST` | `/v1/contact-lists/{id}/merge` | [Merge contact lists](/api-reference/endpoint/merge-lists) | Appends the contacts of each source list to the target's saved list, keeping each contact's `_id` |
| `GET` | `/v1/contact-lists/csv` | [List contact lists](/api-reference/endpoint/get-contact-lists-csv) | Returns the team's saved contact lists, newest first, without their contacts |
| `DELETE` | `/v1/contact-lists/csv/{id}` | [Delete a contact list](/api-reference/endpoint/delete-contact-list) | Deletes a saved list and its dialing queue permanently |
| `GET` | `/v1/contact-lists/csv/{id}` | [Get a contact list](/api-reference/endpoint/get-contact-list-by-id) | Returns one saved list and a page of its contacts |
| `POST` | `/v1/contact-lists/csv/{id}/reimport` | [Reimport a contact list into the dialing queue](/api-reference/endpoint/reimport-contacts) | Replaces every contact in a list's dialing queue with the saved list's current contacts, exactly as saved |

### Teams

| Method | Path | Operation | Description |
| - | - | - | - |
| `GET` | `/v1/team` | [Get the current team](/api-reference/endpoint/get-team) | Returns the team the API key belongs to: its ID, its name, and every member with their status and license |

### Dispositions

| Method | Path | Operation | Description |
| - | - | - | - |
| `GET` | `/v1/dispositions` | [List dispositions](/api-reference/endpoint/get-dispositions) | Returns every disposition the team can log a call with, default and custom, sorted by `id` |
| `GET` | `/v1/dispositions/{id}` | [Get a disposition](/api-reference/endpoint/get-disposition-by-id) | Returns the disposition with this integer `id` |

### Sequences

| Method | Path | Operation | Description |
| - | - | - | - |
| `GET` | `/v1/sequences` | [List CRM sequences](/api-reference/endpoint/get-sequences) | Returns the sales engagement and CRM sequences seen on the team's call logs, with call counts |
| `GET` | `/v1/sequences/{id}` | [Get a CRM sequence](/api-reference/endpoint/get-sequence-by-id) | Returns one CRM sequence, with its call count and first and last call dates |

### Call Logs

| Method | Path | Operation | Description |
| - | - | - | - |
| `GET` | `/v1/call-log` | [List call logs](/api-reference/endpoint/call-log) | Returns the team's call history, newest first, with filters, sorting and pagination |
| `GET` | `/v1/call-log/{id}` | [Get a call log](/api-reference/endpoint/get-call-log-by-id) | Returns one call log by its `_id` |

### Analytics

| Method | Path | Operation | Description |
| - | - | - | - |
| `GET` | `/v1/analytics/list-performance` | [List call performance by contact list](/api-reference/endpoint/analytics-list-performance) | Returns call metrics per contact list for a period, most-called list first, with pagination |
| `GET` | `/v1/analytics/overview` | [Get analytics overview](/api-reference/endpoint/analytics-overview) | Returns the team's headline call metrics for a period, with growth against the previous period |
| `GET` | `/v1/analytics/sdr-performance` | [List call performance by SDR](/api-reference/endpoint/analytics-sdr-performance) | Returns call metrics per rep for a period, most calls first, with pagination |

### Snoozed Contacts

| Method | Path | Operation | Description |
| - | - | - | - |
| `GET` | `/v1/snoozed-contacts` | [List snoozed contacts](/api-reference/endpoint/get-snoozed-contacts) | Returns the team's snooze records, newest first |
| `DELETE` | `/v1/snoozed-contacts/{id}` | [Delete a snoozed contact](/api-reference/endpoint/delete-snoozed-contact) | Deletes a snooze record permanently |
| `GET` | `/v1/snoozed-contacts/{id}` | [Get a snoozed contact](/api-reference/endpoint/get-snoozed-contact-by-id) | Returns one snooze record by its `_id` |
| `PUT` | `/v1/snoozed-contacts/{id}` | [Update a snoozed contact](/api-reference/endpoint/update-snoozed-contact) | Changes the identifiers stored on a snooze record |
| `GET` | `/v1/snoozed-contacts/by-linkedin/{username}` | [Get a snoozed contact by LinkedIn username](/api-reference/endpoint/get-snoozed-contact-by-linkedin) | Returns the snooze record for a LinkedIn username, such as `jane-doe-4b21a3` from `linkedin.com/in/jane-doe-4b21a3` |

### Follow-up Tasks

| Method | Path | Operation | Description |
| - | - | - | - |
| `GET` | `/v1/follow-up` | [List follow-up tasks](/api-reference/endpoint/get-follow-ups) | Returns the team's follow-up tasks for every rep, newest first |

### Custom Fields

| Method | Path | Operation | Description |
| - | - | - | - |
| `GET` | `/v1/custom-fields` | [List custom field mappings](/api-reference/endpoint/get-custom-fields) | Returns the team's custom field mappings: one record for each source (a CRM, or `csv` for CSV uploads) whose… |

### Scored Calls

| Method | Path | Operation | Description |
| - | - | - | - |
| `GET` | `/v1/scored-calls` | [List scored calls](/api-reference/endpoint/scored-calls) | Returns the team's AI-scored calls, newest first, each with its scorecard |
| `GET` | `/v1/scored-calls/{id}` | [Get a scored call](/api-reference/endpoint/get-scored-call-by-id) | Returns one call scorecard by its `_id` |

### Notes

| Method | Path | Operation | Description |
| - | - | - | - |
| `GET` | `/v2/notes` | [List notes](/api-reference/endpoint/list-notes) | Returns every note attached to one person or company, which Salesfinity looks up from the identifiers you send |
| `POST` | `/v2/notes` | [Create a note](/api-reference/endpoint/create-note) | Attaches a plain-text note to a person (a Contact) or a company (a Company) |
| `DELETE` | `/v2/notes/{id}` | [Delete a note](/api-reference/endpoint/delete-note) | Permanently deletes a note |
| `PATCH` | `/v2/notes/{id}` | [Update a note](/api-reference/endpoint/update-note) | Replaces the text of a note |
| `POST` | `/v2/notes/{id}/pin` | [Pin or unpin a note](/api-reference/endpoint/pin-note) | Flips a note between pinned and unpinned |

### Enrichment

| Method | Path | Operation | Description |
| - | - | - | - |
| `GET` | `/v1/api/enrichment/credits` | [Get enrichment credit balance](/api-reference/endpoint/get-enrichment-credits) | Returns the enrichment credit balance of the team that owns the API key |
| `POST` | `/v1/api/enrichment/email` | [Start an email enrichment](/api-reference/endpoint/enrich-email) | Starts an asynchronous lookup of a work or personal email address for one LinkedIn profile |
| `GET` | `/v1/api/enrichment/email/{id}` | [Get an email enrichment result](/api-reference/endpoint/get-email-enrichment) | Returns the current state of an email lookup |
| `POST` | `/v1/api/enrichment/phone` | [Start a phone enrichment](/api-reference/endpoint/enrich-phone) | Starts an asynchronous lookup of mobile and direct-dial phone numbers for one LinkedIn profile |
| `GET` | `/v1/api/enrichment/phone/{id}` | [Get a phone enrichment result](/api-reference/endpoint/get-phone-enrichment) | Returns the current state of a phone lookup |

### Sequencer Sequences

| Method | Path | Operation | Description |
| - | - | - | - |
| `GET` | `/v2/sequencer/sequences` | [List sequences](/api-reference/endpoint/list-sequencer-sequences) | Returns the team's Sequencer sequences, newest first, 10 per page unless you set `limit` |
| `POST` | `/v2/sequencer/sequences` | [Create a sequence](/api-reference/endpoint/create-sequencer-sequence) | Creates a sequence with no steps |
| `DELETE` | `/v2/sequencer/sequences/{id}` | [Delete a sequence](/api-reference/endpoint/delete-sequencer-sequence) | Permanently deletes the sequence, its steps, and the enrollment records of everyone who went through it |
| `GET` | `/v2/sequencer/sequences/{id}` | [Get a sequence](/api-reference/endpoint/get-sequencer-sequence) | Returns one sequence by id: its settings, step and engagement counters, and `can_manage` |
| `PATCH` | `/v2/sequencer/sequences/{id}` | [Update a sequence](/api-reference/endpoint/update-sequencer-sequence) | Changes a sequence's settings |
| `GET` | `/v2/sequencer/sequences/{id}/analytics` | [Get sequence analytics](/api-reference/endpoint/get-sequencer-sequence-analytics) | Returns one sequence's enrollment counts by state (`states`), engagement counters (`engagement`) and shape… |
| `GET` | `/v2/sequencer/sequences/{id}/analytics/people` | [List the people behind an engagement metric](/api-reference/endpoint/list-sequencer-engagement-people) | Lists the people behind one engagement counter, one row per person, most recent activity first, 25 per page… |
| `POST` | `/v2/sequencer/sequences/{id}/contacts` | [Add contacts to a sequence](/api-reference/endpoint/add-contacts-to-sequencer-sequence) | Enrolls up to 500 people in one synchronous call |
| `POST` | `/v2/sequencer/sequences/{id}/disable` | [Disable a sequence](/api-reference/endpoint/disable-sequencer-sequence) | Turns the sequence off |
| `POST` | `/v2/sequencer/sequences/{id}/duplicate` | [Duplicate a sequence](/api-reference/endpoint/duplicate-sequencer-sequence) | Copies a sequence and its steps into a new, disabled sequence authored by `user_id` |
| `POST` | `/v2/sequencer/sequences/{id}/enable` | [Enable a sequence](/api-reference/endpoint/enable-sequencer-sequence) | Turns the sequence on and starts everyone waiting in it |
| `GET` | `/v2/sequencer/sequences/{id}/enrollment-attempts` | [List enrollment refusals](/api-reference/endpoint/list-sequencer-enrollment-attempts) | Lists the people who were not added to this sequence and why, most recent attempt first, 25 per page unless you… |

### Sequencer Steps

| Method | Path | Operation | Description |
| - | - | - | - |
| `GET` | `/v2/sequencer/sequences/{sequence_id}/steps` | [List steps](/api-reference/endpoint/list-sequencer-steps) | Returns every step of the sequence in cadence order, as a plain JSON array; this list is not paginated |
| `POST` | `/v2/sequencer/sequences/{sequence_id}/steps` | [Add a step](/api-reference/endpoint/create-sequencer-step) | Adds a step at the end of the cadence; its `order` is the current number of steps plus one |
| `DELETE` | `/v2/sequencer/sequences/{sequence_id}/steps/{step_id}` | [Delete a step](/api-reference/endpoint/delete-sequencer-step) | Deletes one step |
| `GET` | `/v2/sequencer/sequences/{sequence_id}/steps/{step_id}` | [Get a step](/api-reference/endpoint/get-sequencer-step) | Returns one step |
| `PATCH` | `/v2/sequencer/sequences/{sequence_id}/steps/{step_id}` | [Update a step](/api-reference/endpoint/update-sequencer-step) | Changes a step in place |
| `PUT` | `/v2/sequencer/sequences/{sequence_id}/steps/reorder` | [Reorder steps](/api-reference/endpoint/reorder-sequencer-steps) | Sets the order of the cadence |

### Sequencer Templates

| Method | Path | Operation | Description |
| - | - | - | - |
| `GET` | `/v2/sequencer/templates` | [List email templates](/api-reference/endpoint/list-sequencer-templates) | Returns the team's email templates, newest first, 10 per page unless you set `limit` |
| `POST` | `/v2/sequencer/templates` | [Create an email template](/api-reference/endpoint/create-sequencer-template) | Creates a reusable email: a `subject` and an HTML `body_html`, both with merge fields |
| `DELETE` | `/v2/sequencer/templates/{id}` | [Delete an email template](/api-reference/endpoint/delete-sequencer-template) | Permanently deletes a template |
| `GET` | `/v2/sequencer/templates/{id}` | [Get an email template](/api-reference/endpoint/get-sequencer-template) | Returns one template with its subject, body and engagement counters |
| `PATCH` | `/v2/sequencer/templates/{id}` | [Update an email template](/api-reference/endpoint/update-sequencer-template) | Changes a template |
| `POST` | `/v2/sequencer/templates/{id}/preview` | [Preview a rendered template](/api-reference/endpoint/preview-sequencer-template) | Renders the template's subject and body with merge fields filled, without sending or changing anything |

### Sequencer Enrollments

| Method | Path | Operation | Description |
| - | - | - | - |
| `GET` | `/v2/sequencer/enrollments` | [List enrollments](/api-reference/endpoint/list-sequencer-enrollments) | Lists the team's enrollments, one row per contact per sequence, newest first: where each contact is in the… |
| `GET` | `/v2/sequencer/enrollments/{id}` | [Get an enrollment](/api-reference/endpoint/get-sequencer-enrollment) | Returns one enrollment: its state, the step it is on and when that step is due, its owner, any approval hold or… |
| `POST` | `/v2/sequencer/enrollments/{id}/approve` | [Approve a held enrollment](/api-reference/endpoint/approve-sequencer-enrollment) | Approves an enrollment a rule of engagement is holding for approval |
| `GET` | `/v2/sequencer/enrollments/{id}/events` | [List enrollment events](/api-reference/endpoint/list-sequencer-enrollment-events) | Returns one enrollment's timeline, newest first: the enrollment, its tasks, sends, opens, clicks, replies, rule… |
| `POST` | `/v2/sequencer/enrollments/{id}/finish` | [Un-enroll a contact](/api-reference/endpoint/finish-sequencer-enrollment) | Removes a contact from a sequence by finishing their enrollment |
| `POST` | `/v2/sequencer/enrollments/{id}/pause` | [Pause an enrollment](/api-reference/endpoint/pause-sequencer-enrollment) | Pauses one enrollment |
| `POST` | `/v2/sequencer/enrollments/{id}/reassign` | [Reassign an enrollment](/api-reference/endpoint/reassign-sequencer-enrollment) | Hands one enrollment to another team member |
| `POST` | `/v2/sequencer/enrollments/{id}/reject` | [Reject a held enrollment](/api-reference/endpoint/reject-sequencer-enrollment) | Rejects an enrollment a rule of engagement is holding for approval |
| `POST` | `/v2/sequencer/enrollments/{id}/resume` | [Resume an enrollment](/api-reference/endpoint/resume-sequencer-enrollment) | Resumes a paused enrollment |
| `POST` | `/v2/sequencer/enrollments/{id}/retry` | [Retry a failed enrollment](/api-reference/endpoint/retry-sequencer-enrollment) | Restarts an enrollment the engine gave up on |
| `POST` | `/v2/sequencer/enrollments/bulk/account` | [Finish or pause everyone at an account](/api-reference/endpoint/sequencer-account-action) | Finishes or pauses the enrollments of everyone at one company — the "we just booked a meeting there, stop… |
| `POST` | `/v2/sequencer/enrollments/bulk/approve` | [Approve held enrollments in bulk](/api-reference/endpoint/bulk-approve-sequencer-enrollments) | Approves up to 500 enrollments a rule of engagement is holding for approval: the bulk form of \[Approve a held… |
| `POST` | `/v2/sequencer/enrollments/bulk/finish` | [Un-enroll contacts in bulk](/api-reference/endpoint/bulk-finish-sequencer-enrollments) | Finishes up to 500 enrollments in one call: the bulk form of \[Un-enroll a… |
| `POST` | `/v2/sequencer/enrollments/bulk/move` | [Move enrollments to another sequence](/api-reference/endpoint/move-sequencer-enrollments) | Moves up to 500 contacts from their current sequence into `sequence` |
| `POST` | `/v2/sequencer/enrollments/bulk/reassign` | [Reassign enrollments in bulk](/api-reference/endpoint/bulk-reassign-sequencer-enrollments) | Hands up to 500 enrollments to another team member: the bulk form of \[Reassign an… |
| `POST` | `/v2/sequencer/enrollments/bulk/reject` | [Reject held enrollments in bulk](/api-reference/endpoint/bulk-reject-sequencer-enrollments) | Rejects up to 500 enrollments a rule of engagement is holding for approval: the bulk form of \[Reject a held… |

### Sequencer Enrolment Runs

| Method | Path | Operation | Description |
| - | - | - | - |
| `GET` | `/v2/sequencer/enrollment-runs` | [List enrollment runs](/api-reference/endpoint/list-sequencer-enrolment-runs) | Returns the most recent enrollment runs for one sequence, newest first, including runs started in the… |
| `POST` | `/v2/sequencer/enrollment-runs` | [Start an enrollment run](/api-reference/endpoint/start-sequencer-enrolment-run) | Enrolls up to 5,000 people in one sequence in the background |
| `GET` | `/v2/sequencer/enrollment-runs/{run_id}` | [Get an enrollment run](/api-reference/endpoint/get-sequencer-enrolment-run) | Returns a run's progress and outcome |
| `POST` | `/v2/sequencer/enrollment-runs/{run_id}/cancel` | [Cancel an enrollment run](/api-reference/endpoint/cancel-sequencer-enrolment-run) | Stops a run adding anyone else |
| `POST` | `/v2/sequencer/enrollment-runs/preview` | [Preview an enrollment run](/api-reference/endpoint/preview-sequencer-enrolment) | Shows what [Start an enrollment run](/api-reference/endpoint/start-sequencer-enrolment-run) would do with the… |

### Sequencer Tasks

| Method | Path | Operation | Description |
| - | - | - | - |
| `GET` | `/v2/sequencer/tasks` | [List tasks](/api-reference/endpoint/list-sequencer-tasks) | Returns a page of the team's Sequencer tasks: the calls, emails and to-dos that sequence steps and reactions… |
| `POST` | `/v2/sequencer/tasks` | [Create a one-off task](/api-reference/endpoint/create-sequencer-task) | Creates a one-off task for one contact, outside any sequence |
| `DELETE` | `/v2/sequencer/tasks/{id}` | [Cancel a one-off task](/api-reference/endpoint/delete-sequencer-task) | Cancels an open one-off task: it moves to `cancelled` rather than being deleted, so queue counts and the… |
| `GET` | `/v2/sequencer/tasks/{id}` | [Get a task](/api-reference/endpoint/get-sequencer-task) | Returns one task, with `contact`, `sequence` and `sequence_step` expanded |
| `PATCH` | `/v2/sequencer/tasks/{id}` | [Update a one-off task](/api-reference/endpoint/update-sequencer-task) | Changes the due date, priority, subject or note of an open one-off task |
| `POST` | `/v2/sequencer/tasks/{id}/complete` | [Complete a task](/api-reference/endpoint/complete-sequencer-task) | Resolves an open task and advances its enrollment; for a `manual_email` task this sends a real email |
| `GET` | `/v2/sequencer/tasks/{id}/events` | [List task events](/api-reference/endpoint/list-sequencer-task-events) | Returns the timeline rows recorded against one task, newest first: a plain array of at most 200 events, with no… |
| `POST` | `/v2/sequencer/tasks/{id}/reassign` | [Reassign a task](/api-reference/endpoint/reassign-sequencer-task) | Hands one open task (`pending` or `held`) to another team member |
| `POST` | `/v2/sequencer/tasks/{id}/skip` | [Skip a task](/api-reference/endpoint/skip-sequencer-task) | Skips an open task, which still moves a sequence task's enrollment to the next step, as completing would |
| `POST` | `/v2/sequencer/tasks/{id}/snooze` | [Snooze a task](/api-reference/endpoint/snooze-sequencer-task) | Moves an open task's due date, and its auto-skip deadline by the same amount, so snoozing never makes it expire… |
| `GET` | `/v2/sequencer/tasks/account-coverage` | [Get buying-committee coverage](/api-reference/endpoint/get-sequencer-account-coverage) | Reports, for each account you name, which buying-committee seats the team's contacts at that account fill |
| `POST` | `/v2/sequencer/tasks/bulk` | [Create one-off tasks in bulk](/api-reference/endpoint/bulk-create-sequencer-tasks) | Creates one one-off task per contact, for up to 500 contacts, all with the same action, due date, priority,… |
| `POST` | `/v2/sequencer/tasks/bulk/reassign` | [Reassign tasks in bulk](/api-reference/endpoint/bulk-reassign-sequencer-tasks) | Hands up to 500 open tasks to another team member, one at a time, without changing who owns each enrollment |
| `POST` | `/v2/sequencer/tasks/bulk/skip` | [Skip tasks in bulk](/api-reference/endpoint/bulk-skip-sequencer-tasks) | Skips up to 500 tasks, one at a time, with the same rules as `POST /v2/sequencer/tasks/{id}/skip` |
| `POST` | `/v2/sequencer/tasks/bulk/snooze` | [Snooze tasks in bulk](/api-reference/endpoint/bulk-snooze-sequencer-tasks) | Moves up to 500 tasks to the same `due_at`, one at a time, with the rules of `POST /v2/sequencer/tasks/{id}/snooze` |
| `POST` | `/v2/sequencer/tasks/materialize-call-list` | [Fill a rep’s dial list from their call tasks](/api-reference/endpoint/materialize-sequencer-call-list) | Rebuilds a rep's Sequencer dial list from their open call tasks: it places each `pending` call task that has no… |
| `GET` | `/v2/sequencer/tasks/summary` | [Get a task-queue summary](/api-reference/endpoint/get-sequencer-task-summary) | Counts the team's `pending` tasks by due bucket, without fetching any rows |

### Sequencer Suppression

| Method | Path | Operation | Description |
| - | - | - | - |
| `GET` | `/v2/sequencer/suppression` | [List suppression entries](/api-reference/endpoint/list-sequencer-suppression) | Returns a page of the team's do-not-contact list, newest first |
| `POST` | `/v2/sequencer/suppression` | [Add a suppression entry](/api-reference/endpoint/create-sequencer-suppression) | Adds one email address, domain or phone number to the team's do-not-contact list |
| `DELETE` | `/v2/sequencer/suppression/{id}` | [Remove a suppression entry](/api-reference/endpoint/delete-sequencer-suppression) | Deletes one entry, so that address, domain or number no longer blocks enrollment or email sends |
| `POST` | `/v2/sequencer/suppression/import` | [Import suppression entries](/api-reference/endpoint/import-sequencer-suppression) | Adds up to 1,000 entries to the do-not-contact list in one request; values already on the list are left unchanged |

### Sequencer Policies

| Method | Path | Operation | Description |
| - | - | - | - |
| `GET` | `/v2/sequencer/policies` | [List rules-of-engagement policies](/api-reference/endpoint/list-sequencer-policies) | Returns every rules-of-engagement policy on the team as a plain array, not paginated: the default first, then… |
| `POST` | `/v2/sequencer/policies` | [Create a rules-of-engagement policy](/api-reference/endpoint/create-sequencer-policy) | Creates a rules-of-engagement policy, checked against the catalog; nothing uses it until a sequence names it |
| `DELETE` | `/v2/sequencer/policies/{id}` | [Delete a rules-of-engagement policy](/api-reference/endpoint/delete-sequencer-policy) | Deletes a policy that no sequence uses |
| `GET` | `/v2/sequencer/policies/{id}` | [Get a rules-of-engagement policy](/api-reference/endpoint/get-sequencer-policy) | Returns one policy with its scenario `rules`, its reactions (`outcome_rules`) and whether it is the team default |
| `PATCH` | `/v2/sequencer/policies/{id}` | [Update a rules-of-engagement policy](/api-reference/endpoint/update-sequencer-policy) | Changes a policy; `rules` and `outcome_rules` each replace the whole list when sent |
| `POST` | `/v2/sequencer/policies/{id}/default` | [Make a policy the team default](/api-reference/endpoint/set-default-sequencer-policy) | Makes this policy the team default: the one every sequence that names no policy of its own runs under |
| `GET` | `/v2/sequencer/policies/catalog` | [Get the rules-of-engagement catalog](/api-reference/endpoint/get-sequencer-policy-catalog) | Returns the vocabulary rules of engagement are built from: scopes, conditions, scenario actions, outcomes and… |
| `POST` | `/v2/sequencer/policies/preview` | [Preview a draft rule set](/api-reference/endpoint/preview-sequencer-policy) | Measures what an unsaved set of scenarios would have done to the prospects behind the team's 200 most recent… |

### Sequencer Settings

| Method | Path | Operation | Description |
| - | - | - | - |
| `GET` | `/v2/sequencer/email-accounts` | [List sending mailboxes](/api-reference/endpoint/list-sequencer-mailboxes) | Returns the team's sending mailboxes with connection health, warmup state, today's usage and who each belongs… |
| `GET` | `/v2/sequencer/email-accounts/{id}` | [Get a sending mailbox](/api-reference/endpoint/get-sequencer-mailbox) | Returns one sending mailbox: its connection health, warmup status and today's usage against its daily cap |
| `GET` | `/v2/sequencer/settings` | [Get sequencer settings](/api-reference/endpoint/get-sequencer-settings) | Returns the team's Sequencer settings: the shared mailbox pool, which mailboxes belong to which rep, the… |

## Resources for agents and crawlers

* [`/llms.txt`](/llms.txt) — a compact index of every page on this site.
* [`/llms-full.txt`](/llms-full.txt) — the full documentation as a single plain-text file.
* [`/api-reference/openapi.json`](/api-reference/openapi.json) — the complete OpenAPI 3.0.1
  description.
* [`/sitemap.xml`](/sitemap.xml) — every canonical URL.
* [`/.well-known/agent-skills/index.json`](/.well-known/agent-skills/index.json) — an agent skill
  for working with Salesfinity through the API or the MCP server.
* Any page also serves Markdown. Append `.md` to a page URL, or send
  `Accept: text/markdown`, to get the source instead of the rendered page.

```bash theme={"system"}
curl -H 'Accept: text/markdown' https://docs.salesfinity.ai/api-reference/introduction
curl https://docs.salesfinity.ai/api-reference/introduction.md
```

## Getting help

Email [hello@salesfinity.co](mailto:hello@salesfinity.co) or browse the
[help center](https://support.salesfinity.ai). When reporting an API problem, include the
`request_id` from the error body (or the `X-Request-Id` response header), the request path, the
timestamp, and the `error` and `statusCode` — the request ID lets Salesfinity find the exact
request in its logs.

## Next steps

<CardGroup cols={2}>
  <Card title="Open the developer portal" icon="code" href="/developers">
    Keys, a copy-paste quickstart, testing on live data and client patterns.
  </Card>

  <Card title="Run a sequence over the API" icon="list-check" href="/sequencer/api-quickstart">
    Create a cadence, enroll people and work the tasks it makes.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.