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

# Customer API

> Read your team's conversations, transcripts, recordings, tasks, contacts, and reports over HTTPS, update tasks, and add task notes.

The Customer API gives your own systems the data you see in the Answering Agent dashboard. Use it to copy tasks into ClickUp or Zendesk, archive call transcripts and recordings, or feed weekly numbers into your own reporting.

<Note>
  The API reads conversations, transcripts, recordings, tasks, contacts, and reports. It can also change a task's status or assignee and add a note to a task. To receive new tasks as they happen, use [webhooks](/webhooks). To ask about the same data in Claude or ChatGPT without writing code, use the [MCP server](/mcp-server).
</Note>

## Quickstart

<Steps>
  <Step title="Create an API key">
    Sign in at [answeringagent.com](https://answeringagent.com) as a team owner or admin. Use a login that belongs to only the team you want to read. Go to **Settings → API Keys**, click **New API Token**, enter a name, and click **Create**. Copy the key. The dashboard shows it once.
  </Step>

  <Step title="Put the key in an environment variable">
    Every example in these docs reads the key from `ANSWERING_AGENT_API_KEY`. The JavaScript examples use `fetch` and need Node 18 or later.

    ```bash theme={null}
    export ANSWERING_AGENT_API_KEY="your-api-key"
    ```
  </Step>

  <Step title="Get your account">
    <CodeGroup>
      ```bash cURL theme={null}
      curl https://answeringagent.com/api/v1/account \
        -H "X-API-KEY: $ANSWERING_AGENT_API_KEY"
      ```

      ```javascript JavaScript theme={null}
      const res = await fetch('https://answeringagent.com/api/v1/account', {
        headers: { 'X-API-KEY': process.env.ANSWERING_AGENT_API_KEY },
      });
      if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
      const account = await res.json();
      ```
    </CodeGroup>

    The response names the team the key reads and the role of the person who created it:

    ```json theme={null}
    {
      "team": { "id": 410, "name": "Westside Wash Co.", "timezone": "America/Chicago", "today": "2026-10-06" },
      "you": { "id": 9021, "name": "Sam Ortiz", "role": "admin" },
      "phone_lines": [
        { "id": 2181, "name": "Westside Wash", "phone_number": "+15125550142" },
        { "id": 2182, "name": "Lamar Blvd", "phone_number": "+15125550177" }
      ],
      "members": [
        { "id": 9040, "name": "Jordan Lee", "role": "user" },
        { "id": 9034, "name": "Priya Shah", "role": "manager" },
        { "id": 9021, "name": "Sam Ortiz", "role": "admin" }
      ]
    }
    ```

    The full response has more fields. See [Account](/api/account).
  </Step>
</Steps>

If the call fails or reads the wrong team:

| You see | Cause | Fix |
| - | - | - |
| `401` with `"error": "API key is required"` | The `X-API-KEY` header is missing or empty. | Check that `ANSWERING_AGENT_API_KEY` is set in the shell that runs `curl`. |
| `401` with `"error": "Invalid credentials"` | The key is wrong or revoked, or the person who created it was deactivated. | Copy the whole key, including the number and the `\|`. Create a new key if you lost it. |
| `403` | The person who created the key is not an owner, admin, or manager on the team open in their dashboard. | Create the key from an owner or admin login, or give that person one of those roles. |
| `200`, but `team.name` is another team | The person who created the key belongs to more than one team and has the other team open in the dashboard. | Switch that login back to the right team, or create the key from a login that belongs to only one team. |

Next, follow a guide:

<CardGroup cols={2}>
  <Card title="Sync tasks to ClickUp or Zendesk" icon="refresh-cw" href="/guides/sync-tasks">
    Create tickets from webhooks and write status changes back.
  </Card>

  <Card title="Export conversations" icon="archive" href="/guides/export-conversations">
    Archive transcripts and call recordings day by day.
  </Card>
</CardGroup>

## Base URL

```
https://answeringagent.com/api/v1
```

Every endpoint on these pages sits under this URL.

## Authenticate

Send the key in the `X-API-KEY` header on every request.

<CodeGroup>
  ```bash cURL theme={null}
  curl https://answeringagent.com/api/v1/account \
    -H "X-API-KEY: $ANSWERING_AGENT_API_KEY"
  ```

  ```javascript JavaScript theme={null}
  const res = await fetch('https://answeringagent.com/api/v1/account', {
    headers: { 'X-API-KEY': process.env.ANSWERING_AGENT_API_KEY },
  });
  if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
  const account = await res.json();
  ```
</CodeGroup>

A key looks like `123|AbCdEf0123456789...`: a number, a `|`, and a secret. Send the whole string. Store it on your server, never in browser code. To revoke a key, click **Revoke** next to it in **Settings → API Keys**. Requests that use it get `401` from then on.

<Warning>
  **A key acts as the person who created it.**

  * **Team.** The key reads the team that person has open in the dashboard right now. If they belong to more than one team and switch teams, the key switches with them.
  * **Role.** That person must be an owner, admin, or manager on the team. Other roles get `403`. Only owners and admins can create keys.
  * **Visibility.** The key sees what that person sees. If their access is limited to some phone lines, so is the key's.
  * **Lifetime.** Keys do not expire. A key stops working when you revoke it or when its creator is deactivated.
  * **Permissions.** Keys have no scopes. Every key can read all the data above, update tasks, and add task notes.

  **Recommended setup.** Create a dedicated login for the integration, such as `integrations@yourcompany.com`. Add it to one team only, with the admin role, and create the key from that login. The key then keeps working when people leave or switch teams, and task changes and notes made through the API show that login in the task's activity.
</Warning>

For hosting, data retention, AI training, and compliance status, see [Security and data handling](/security).

## Names and IDs

Every endpoint, the [MCP server](/mcp-server), report filters and rows, and the webhook's `data` object use the same names. A value you read from one endpoint works as an input to another. The examples on these pages follow conversation 184532, a call from Dana Ruiz who wants to cancel her membership.

| Concept | Name | Values or shape |
| - | - | - |
| Channel | `channel` | `phone`, `text`, `web_chat`, or `email` |
| Task status | `status` | `open`, `in_progress`, `on_hold`, or `done`. Task search also takes `not_done` and `all`. |
| Person | `assignee`, `you`, `members[]`, report `team_member` | `{ "id": 9034, "name": "Priya Shah" }`. `you` and `members[]` add `role`. Inputs take the `id`: `assigned_to`, `expected_assigned_to`, and report `filters.team_member_ids`. |
| Customer | `customer` | `{ "name": "Dana Ruiz", "phone": "+15125550118", "email": "dana.ruiz@example.com" }`. Any field can be `null`. |
| Phone line | `phone_line`, `phone_lines[]` | `{ "id": 2181, "name": "Westside Wash", "phone_number": "+15125550142" }`. `name` and `phone_number` can be `null`. Report `filters.phone_line_id` takes the `id`. |
| Conversation ID | `id` | An integer, such as `184532`. |
| Task ID | `id` | `conversation-184532` or `form-submission-45`. The prefix names the source, and the number is that conversation's or form submission's ID. |
| Category | `category` | A key such as `cancellation`. Conversations, tasks, and reports use one list. A task has its conversation's category, and a form task has `form`. [`GET /reports/metrics`](/api/reports#list-the-metrics) lists every key with its label under `categories`. Older records can have a retired key that is not in that list. |
| Timestamp | Fields ending in `_at` | ISO 8601 in UTC, such as `2026-10-05T14:21:07.000Z`. |
| Date | `team.today`, report `range.from` and `range.to` | `YYYY-MM-DD`. |

The webhook's top-level fields, such as `task.channel` with `phone_call`, are older than these names and keep their original values. See [Legacy fields](/webhooks#legacy-fields).

## Rate limit

Each user can make 120 requests per minute. All keys created by the same person share that limit. Over the limit, the API returns `429` with a `Retry-After` header that gives the seconds to wait.

## Errors

Errors return a JSON body with an `error` message for people and a `code` for your code. Branch on `code`. The message text can change.

```json theme={null}
{ "error": "That conversation is not available.", "code": "not_found" }
```

An `invalid_request` error also includes `issues`, one entry for each input that failed validation.

```json theme={null}
{
  "error": "Invalid request.",
  "code": "invalid_request",
  "issues": [
    { "path": ["limit"], "message": "Too big: expected number to be <=50" }
  ]
}
```

The API ignores query parameters it does not use, so a misspelled parameter such as `chanel` has no effect. A JSON body with a key the API does not know returns `400`.

| Status | `code` | Meaning |
| - | - | - |
| `200` | None | Success. |
| `201` | None | A task note was added. |
| `400` | `invalid_request` | An input is missing or invalid. See `issues`. |
| `401` | `unauthorized` | The `X-API-KEY` header is missing, the key is wrong or revoked, or the person who created it was deactivated. |
| `403` | `forbidden` | The person who created the key is not an owner, admin, or manager on the team, or a task update or note is not allowed. |
| `404` | `not_found` | The record does not exist, the key cannot see it, or no endpoint has that path. |
| `405` | `method_not_allowed` | The endpoint does not support that HTTP method. The `Allow` header lists the methods it does support. |
| `409` | `conflict` | A task update's `expected_status` or `expected_assigned_to` no longer matches. Nothing changed. |
| `422` | `unprocessable` | The dashboard would refuse the same task update or note, for example because the assignee is not on the team. |
| `429` | `rate_limited` | Too many requests. Wait for `Retry-After` seconds. |
| `500` | `internal` | Something failed on our side. Retry, then email [support@answeringagent.com](mailto:support@answeringagent.com). |

A recording download can also return `416` with `invalid_request`, or `502` or `503` with `internal`. Any other `4xx` status has `invalid_request`, and any other `5xx` has `internal`.

## Pages and time ranges

List endpoints take `limit` (1 to 50, default 10) and `page` (default 1). Each list response includes `total_matching` and `next_page`. `next_page` is `null` on the last page.

```json theme={null}
{ "total_matching": 1342, "page": 1, "next_page": 2, "conversations": [] }
```

Tasks and contacts come newest first. Conversations come in order of latest activity, so a call with a new text reply moves to the top. Conversations and tasks also take `range`, which limits results to records created in that window. For a task, that is when its conversation started or its form was submitted. Every window uses your team's timezone.

| `range` | Window |
| - | - |
| `today` | From midnight today until now |
| `yesterday` | Yesterday from midnight to midnight |
| `7d`, `14d`, `30d`, `90d`, `365d` | From midnight on the date 7, 14, 30, 90, or 365 days ago, until now. On October 6, `30d` starts at midnight on September 6. |
| `mtd`, `ytd` | From midnight on the first day of this month or year, until now |

Leave out `range` for all time. Search has no custom date window. [Reports](/api/reports#request-body) cover the same dates, but their `7d` to `365d` start at the current time of day rather than at midnight. Reports also take a `month` or a custom `from` and `to`.

## Endpoints

| Method | Path | Returns | Playground |
| - | - | - | - |
| `GET` | [`/account`](/api/account) | Your team, phone lines, members, and connected point-of-sale systems | [Try it](/api-reference/account/get-account) |
| `GET` | [`/conversations`](/api/conversations#search-conversations) | Calls, texts, website chats, and emails | [Try it](/api-reference/conversations/search-conversations) |
| `GET` | [`/conversations/{conversation_id}`](/api/conversations#get-a-conversation) | One conversation with its transcript | [Try it](/api-reference/conversations/get-a-conversation) |
| `GET` | [`/conversations/{conversation_id}/recording`](/api/conversations#download-a-call-recording) | The call recording audio | [Try it](/api-reference/conversations/download-a-call-recording) |
| `GET` | [`/tasks`](/api/tasks#search-tasks) | Follow-up tasks | [Try it](/api-reference/tasks/search-tasks) |
| `GET` | [`/tasks/{task_id}`](/api/tasks#get-a-task) | One task with its full description | [Try it](/api-reference/tasks/get-a-task) |
| `PATCH` | [`/tasks/{task_id}`](/api/tasks#update-a-task) | Change a task's status or assignee | [Try it](/api-reference/tasks/update-a-task) |
| `POST` | [`/tasks/{task_id}/notes`](/api/tasks#add-a-note) | Add an internal note to a task | [Try it](/api-reference/tasks/add-a-note-to-a-task) |
| `GET` | [`/contacts`](/api/contacts#search-contacts) | Customers | [Try it](/api-reference/contacts/search-contacts) |
| `GET` | [`/contacts/{contact_id}`](/api/contacts#get-a-contact) | One customer and their recent conversations | [Try it](/api-reference/contacts/get-a-contact) |
| `GET` | [`/reports/metrics`](/api/reports#list-the-metrics) | Every report metric and how it is calculated | [Try it](/api-reference/reports/list-report-metrics) |
| `POST` | [`/reports`](/api/reports#run-a-report) | Report numbers, totals, and breakdowns | [Try it](/api-reference/reports/run-a-report) |

Requests from the playground go to production. With a real key, **Try it** on `PATCH /tasks/{task_id}` changes a live task, and **Try it** on `POST /tasks/{task_id}/notes` adds a note to one.

Links in responses, such as `url`, open the record in the dashboard.

## The API and the MCP server

The API and the [MCP server](/mcp-server) share the lookups for the account, conversations, tasks, contacts, and reports. They also share task updates and task notes. The same report returns the same numbers over both. They differ in what else they do:

* Only the API downloads call recordings and lists the metric catalog.
* Only the MCP server reads the AI's settings, your support requests, and the help center.
* Each has its own limit of 120 requests per minute per person.

## Partner API

Resellers that provision accounts for their own customers use a different API under the same base URL. See the [Partner API](/partner-api/overview). A regular team's key gets `401` on Partner API endpoints.


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