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

# Call records and retention

> Read call statistics and call detail records, export them, and set how long call data is kept.

`calls` on a team or project client reads call history. `callRetention` sets how
long Polymorfa keeps call data.

| Task | Permission |
| - | - |
| Read statistics, records, and exports; read retention | `sessions:read` |
| Change retention | `sessions:manage` |

A team client covers every project unless you pass `projectId`. A project client
reads only its own project.

## Read call statistics

```typescript theme={null}
const { data: stats } = await platform.calls.stats({
  since: "2026-09-01T00:00:00Z",
  until: "2026-10-01T00:00:00Z",
  groupBy: "day",
  timezone: "Europe/Lisbon",
});

console.log(stats.totals.answerRate, stats.groups.length);
```

`groupBy` is `day` (the default), `hour`, `session`, or `outcome`. Without
`since` and `until`, the range is the last 7 days. `timezone` is an IANA zone
name and defaults to `UTC`.

Every call method accepts the same filters: `sessionId`, `direction`
(`inbound` or `outbound`), `upstream` (`linked_device` or `cloud_api`),
`outcome` (`answered`, `missed`, `declined`, `failed`, or `in_progress`), and
`since` and `until` as RFC 3339 timestamps or `Date` objects.

## List call records

```typescript theme={null}
for await (const call of await platform.calls.list({ outcome: "missed" })) {
  console.log(call.callId, call.sessionId, call.direction, call.peerRef);
}
```

Records are newest first. They never contain phone numbers. `peerRef` is a
pseudonym for the other party that stays the same across your team's calls.

Read one call's full detail, including its event history and media
measurements:

```typescript theme={null}
const detail = await platform.calls.retrieve("<call-id>");
console.log(detail.data.history.events);
```

## Export call records

`exportAll` returns every page as text, in order. CSV pages after the first
leave out the header row, so you can write the chunks to one file:

```typescript theme={null}
import { createWriteStream } from "node:fs";

const file = createWriteStream("calls.csv");
for await (const chunk of platform.calls.exportAll({ since: "2026-09-01T00:00:00Z" })) {
  file.write(chunk);
}
file.end();
```

Pass `format: "ndjson"` for one JSON record per line. `export` returns a single
page of up to 1,000 records with a `nextCursor`.

## Set call data retention

Retention is one setting for the whole team. Changing it needs a team key.

```typescript theme={null}
const { data: current } = await platform.callRetention.retrieve();
console.log(current.policy, current.retentionDays);

await platform.callRetention.update({
  policy: "custom",
  retentionDays: 45,
  expectedRevision: current.revision,
});
```

| Policy | Days kept |
| - | - |
| `short` | 7 |
| `standard` | 30 |
| `extended` (default) | 90 |
| `compliance` | 365 |
| `custom` | `retentionDays`, from 1 to 2555 |

A stale `expectedRevision` fails with `409 state_conflict`. Without it, the
update applies regardless of other changes.

<Warning>
  Deletion of call data older than the retention period starts on a date
  Polymorfa announces in the [changelog](/changelog). Until then, the setting
  records your choice and nothing is deleted. After deletion starts, a shorter
  period also removes call data already stored, and deleted data cannot be
  recovered.
</Warning>

See [Call data retention](/guides/calls/overview#call-data-retention).


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