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

# Export conversations and recordings

> Archive every conversation's transcript and call recording, one day at a time.

This guide copies conversations, transcripts, and call recordings into your own storage. A daily job archives yesterday's conversations. A one-time backfill copies older ones.

Search returns summaries only. To get the transcript, you read each conversation with [`GET /conversations/{conversation_id}`](/api/conversations#get-a-conversation). To get the audio, you call [`GET /conversations/{conversation_id}/recording`](/api/conversations#download-a-call-recording).

## Choose the window

Search has no custom date window. It takes one of these `range` values:

* `today` and `yesterday` cover whole days in your team's timezone. Use `yesterday` for a daily archive.
* `7d`, `14d`, `30d`, `90d`, and `365d` start at midnight on the date that many days ago, in your team's timezone, and run until now. `mtd` and `ytd` start at midnight on the first day of this month or year.
* With no `range`, search covers all time.

`range` selects conversations by when they started. Search sorts them by latest activity, so a conversation that gets a new text moves to the top while you page. Store conversations by `id` and skip any you already have, so a moved row is not saved twice. A short window, such as one day, keeps that movement small.

Search leaves out spam, unanswered calls, and conversations that have not finished.

## Archive yesterday every day

Run this job once a day, after midnight in your team's timezone. Read the timezone from `team.timezone` in [`GET /account`](/api/account).

```javascript theme={null}
import { writeFile } from 'node:fs/promises';

const BASE = 'https://answeringagent.com/api/v1';

async function api(path) {
  const res = await fetch(`${BASE}${path}`, {
    headers: { 'X-API-KEY': process.env.ANSWERING_AGENT_API_KEY },
  });
  if (res.status === 429) {
    await new Promise((r) => setTimeout(r, Number(res.headers.get('Retry-After') ?? 60) * 1000));
    return api(path);
  }
  return res;
}

async function archive(range) {
  const saved = new Set();
  for (let page = 1; page; ) {
    const body = await (await api(`/conversations?range=${range}&limit=50&page=${page}`)).json();
    for (const { id, has_recording } of body.conversations) {
      if (saved.has(id)) continue;
      saved.add(id);

      const conversation = await (await api(`/conversations/${id}`)).json();
      await writeFile(`conversation-${id}.json`, JSON.stringify(conversation, null, 2));

      if (has_recording) {
        const audio = await api(`/conversations/${id}/recording`);
        if (audio.ok) await writeFile(`conversation-${id}-recording`, Buffer.from(await audio.arrayBuffer()));
      }
    }
    page = body.next_page;
  }
  return saved.size;
}

await archive('yesterday');
```

The job requests audio only when `has_recording` is `true`. For some calls the recording provider stores the audio and can delete it, so a request can still return `404`. The job skips it. The recording's `Content-Type` header says whether it is MP3 (`audio/mpeg`) or Ogg (`audio/ogg`). Use it to pick a file extension.

Compare the count the job saved with `total_matching` from the first page. If the job saved fewer, run it again. Conversations it already saved are skipped.

## Backfill older conversations

For conversations before your daily job started, run `archive` once with a longer range, such as `365d`, or with no `range` for all time. Skip IDs your storage already has.

Each conversation takes one request, and each recorded call takes one more. The API allows 120 requests per minute for each person, so 10,000 calls with recordings take about three hours. The `api` helper waits and retries when it gets `429`.

## What the archive contains

Each `conversation-{id}.json` file has the summary, the customer's questions, the `task` the conversation created, and:

* `transcript` for a phone call, with each turn's speaker, text, and seconds into the call.
* `written` for texts, website chats, and emails, with each message's sender, channel, text, and time.

A very long call or thread can come back with `truncated` set to `true`. The API does not return the turns it left out. See [Get a conversation](/api/conversations#get-a-conversation) for every field.


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