> ## 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.

# Developer Portal

> API keys, quickstarts, testing guidance, SDK-free client patterns, and machine-readable resources for building on Salesfinity.

Everything you need to go from zero to a working Salesfinity integration: getting a key, making
your first authenticated call, testing without disturbing live dialing, handling errors and
retries, and the machine-readable files your tools can consume directly.

<CardGroup cols={2}>
  <Card title="Generate an API key" icon="key" href="https://preview.salesfinity.co/dashboard/settings">
    Dashboard → Settings → Connections & API
  </Card>

  <Card title="OpenAPI description" icon="file-code" href="/api-reference/openapi.json">
    OpenAPI 3.0.1, 35 operations, typed responses
  </Card>

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

  <Card title="MCP server" icon="bolt" href="/mcp/overview">
    Hosted MCP endpoint for AI assistants
  </Card>
</CardGroup>

## 1. Get an API key

1. Open the Salesfinity dashboard and go to **Settings → Connections & API**.
2. Generate a new API key.
3. Copy it immediately and store it in your secret manager. Treat it like a password.

A key is scoped to a **single team**. Every request made with it sees only that team's contact
lists, call logs, and analytics. There is no account-wide or cross-team key, so an integration
serving several teams needs one key per team.

<Note>
  Keys are long-lived and do not expire on a schedule. Rotate them from the same settings screen
  when someone with access leaves, or if a key is ever committed to source control.
</Note>

## 2. Make your first call

Every endpoint authenticates with the `x-api-key` request header. The cheapest way to verify a
key is to read the team it belongs to.

<CodeGroup>
  ```bash cURL theme={null}
  curl https://client-api.salesfinity.co/v1/team \
    --header 'x-api-key: YOUR_API_KEY'
  ```

  ```js Node.js theme={null}
  const res = await fetch("https://client-api.salesfinity.co/v1/team", {
    headers: { "x-api-key": process.env.SALESFINITY_API_KEY },
  });

  if (!res.ok) {
    // Errors are always JSON, never an HTML page.
    const { message, error, statusCode } = await res.json();
    throw new Error(`Salesfinity ${statusCode} ${error}: ${message}`);
  }

  const team = await res.json();
  ```

  ```python Python theme={null}
  import os, requests

  res = requests.get(
      "https://client-api.salesfinity.co/v1/team",
      headers={"x-api-key": os.environ["SALESFINITY_API_KEY"]},
      timeout=30,
  )

  if not res.ok:
      body = res.json()
      raise RuntimeError(
          f"Salesfinity {body['statusCode']} {body['error']}: {body['message']}"
      )

  team = res.json()
  ```
</CodeGroup>

If the key is missing or invalid you get HTTP 403 and a JSON body, not an HTML error page:

```json theme={null}
{ "message": "Forbidden resource", "error": "Forbidden", "statusCode": 403 }
```

## 3. Build the client

There is no official Salesfinity SDK. The API is small, uniform, and fully described by an
OpenAPI document, so the two supported paths are a thin hand-written client or a generated one.

### Generate a client from the OpenAPI description

The description at [`/api-reference/openapi.json`](/api-reference/openapi.json) is also served at
[`/openapi.json`](/openapi.json). Every operation has a unique `operationId`, which becomes the
method name in most generators.

```bash theme={null}
# TypeScript, using openapi-typescript
npx openapi-typescript https://docs.salesfinity.ai/openapi.json -o salesfinity.d.ts

# Any language, using openapi-generator
openapi-generator-cli generate \
  -i https://docs.salesfinity.ai/openapi.json \
  -g python \
  -o ./salesfinity-client
```

### Conventions worth encoding once

| Concern      | Convention                                                                                                               |
| ------------ | ------------------------------------------------------------------------------------------------------------------------ |
| Base URL     | `https://client-api.salesfinity.co`                                                                                      |
| Auth         | `x-api-key` header on every request                                                                                      |
| Auth failure | **403**, never 401 — a "refresh on 401" branch will never fire                                                           |
| Pagination   | `page` (1-based) and `limit`; the `limit` default varies by endpoint (10, 50, or 100), capped at 100 where a cap applies |
| Sorting      | `sort=field` ascending, `sort=-field` descending                                                                         |
| Filtering    | Bracketed parameters such as `filters[start_date]`, `filters[user_ids]`                                                  |
| Errors       | Always JSON, always `{ message, error, statusCode }`                                                                     |
| IDs          | 24-character hexadecimal strings                                                                                         |

### Retries

Retry on **429** and **5xx** with exponential backoff and jitter. Do not retry **400**, **402**,
**403**, or **404** — none of them succeed on a second identical attempt. `POST` endpoints are not
idempotent, so cap retries and confirm state with a `GET` before retrying a create.

Salesfinity does not currently publish a fixed request quota. Build the 429 path anyway and keep
concurrency modest.

## 4. Test safely

There is no separate sandbox host. `https://client-api.salesfinity.co` is the only public API
host, and it operates on live data, so build your test plan around that:

* **Start read-only.** `GET /v1/team`, `GET /v1/dispositions`, `GET /v1/custom-fields`, and the
  analytics endpoints have no side effects and are safe to hammer during development.
* **Use a dedicated test team.** Generate a key for a team that is not actively dialing, so
  writes cannot disturb a live queue.
* **Use a throwaway contact list.** [Create a List](/api-reference/endpoint/create-list) gives you
  an isolated target for add, remove, and merge calls that you can
  [delete](/api-reference/endpoint/delete-contact-list) afterwards.
* **Know which writes reach the dialer.**
  [Add a Contact to a List](/api-reference/endpoint/add-contact) puts the contact into the dialing
  queue immediately, and
  [Reimport Contacts](/api-reference/endpoint/reimport-contacts) pushes a whole list into it.
  Everything else is safe to exercise against a test list.
* **Point the enrichment `callback_url` somewhere disposable** while developing, so test results
  are not POSTed at a production handler.

<Warning>
  Enrichment endpoints spend real credits. `POST /v1/api/enrichment/email` consumes a credit per
  lookup, and returns **402 Payment Required** when the team's balance reaches zero. Check
  [Get Enrichment Credits](/api-reference/endpoint/get-enrichment-credits) before a bulk run.
</Warning>

## 5. Pick an integration surface

<CardGroup cols={3}>
  <Card title="REST API" icon="code" href="/api-reference/introduction">
    35 operations for full programmatic control. Best for backend integrations and data sync.
  </Card>

  <Card title="MCP server" icon="bolt" href="/mcp/overview">
    Hosted at `https://mcp.salesfinity.ai/mcp`. Best for AI assistants and internal tooling.
  </Card>

  <Card title="Use cases" icon="lightbulb" href="/mcp/use-cases/overview">
    Worked examples for managers, reps, and shared workflows.
  </Card>
</CardGroup>

## Machine-readable resources

| Resource            | URL                                                                                             | Format             |
| ------------------- | ----------------------------------------------------------------------------------------------- | ------------------ |
| OpenAPI description | [`/openapi.json`](/openapi.json) · [`/api-reference/openapi.json`](/api-reference/openapi.json) | OpenAPI 3.0.1 JSON |
| Documentation index | [`/llms.txt`](/llms.txt)                                                                        | Plain text         |
| Full documentation  | [`/llms-full.txt`](/llms-full.txt)                                                              | Plain text         |
| Sitemap             | [`/sitemap.xml`](/sitemap.xml)                                                                  | XML                |
| Agent card          | [`/.well-known/agent-card.json`](/.well-known/agent-card.json)                                  | JSON               |
| MCP server card     | [`/.well-known/mcp/server-card.json`](/.well-known/mcp/server-card.json)                        | JSON               |
| Agent skills index  | [`/.well-known/agent-skills/index.json`](/.well-known/agent-skills/index.json)                  | JSON               |

Every documentation page is also available as Markdown — append `.md` to the URL, or send an
`Accept: text/markdown` request header:

```bash theme={null}
curl -H 'Accept: text/markdown' https://docs.salesfinity.ai/developers
curl https://docs.salesfinity.ai/developers.md
```

## Support

* **Email** — [hello@salesfinity.co](mailto:hello@salesfinity.co)
* **Help center** — [support.salesfinity.ai](https://support.salesfinity.ai)

Include the request path, the timestamp, and the `error` and `statusCode` from the response body
when reporting an API problem. Never include your API key.
