# Recordings and transcriptions

Recordings come from calls (`record` on create, the `record_start` action, CoXML `<Record>` and `<Dial record>`),
conferences, voicemail and AI agents. Transcriptions come from `<Record transcribe>` and `record_start` with
`transcription`. Paths are relative to `https://api.contactivity.io/v1/projects/{project_id}`; see the
[overview](/guides/overview.md) for auth, errors and paging.

| Method | Path | Scope | Purpose |
|---|---|---|---|
| GET | `/recordings` | `recordings:read` | List recordings (paged) |
| GET | `/recordings/{recording_id}` | `recordings:read` | Fetch a recording |
| GET | `/recordings/{recording_id}/media` | `recordings:read` | Download the audio (302 to a signed link) |
| DELETE | `/recordings/{recording_id}` | `recordings:write` | Archive a recording (audio kept) |
| GET | `/transcriptions` | `recordings:read` | List transcriptions (paged) |
| GET | `/transcriptions/{transcription_id}` | `recordings:read` | Fetch a transcription |
| DELETE | `/transcriptions/{transcription_id}` | `recordings:write` | Archive a transcription |

## The recording object

| Field | Type | Description |
|---|---|---|
| `id` | string | `RE…` |
| `call_id`, `conference_id` | string or null | |
| `from`, `to` | string or null | The call's numbers (E.164); null without a call (conference recordings) |
| `status` | string | `in_progress`, `paused`, `stopped`, `processing`, `completed`, `absent`, `failed` |
| `source` | string | `call`, `conference`, `coxml_record`, `voicemail`, `api`, `ai_agent` |
| `channels` | integer | 1 or 2 |
| `format` | string | `wav` or `mp3` |
| `duration_secs` | integer or null | |
| `price` | null | Recordings are not charged per recording today |
| `created_at` | timestamp | |
| `media_url` | string | This recording's `/media` URL (needs the API key) |

`GET /recordings` filters: `call_id`, `conference_id`, `from`, `to` (the call's numbers, exact; `+1NXXNXXXXXX` also
matches a stored `1NXXNXXXXXX`), `source`, `created_after` (inclusive), `created_before`
(exclusive), as RFC 3339 or `YYYY-MM-DD`; plus `limit`, `starting_after`. Errors: `400 invalid_parameter`.

`GET /recordings/{id}/media?format=wav|mp3` (default: the stored format) answers `302` with `Location` set to a
signed link valid for 10 minutes. Errors: `400 invalid_parameter` (param `format`), `404 not_found`,
`404 media_not_available` (no audio yet, or not in that format), `503 storage_unavailable`.

```sh
curl -sL -o call.mp3 "https://api.contactivity.io/v1/projects/$PROJECT_ID/recordings/$RECORDING_ID/media?format=mp3" \
  -H "Authorization: Bearer $CONTACTIVITY_API_KEY"
```

`DELETE /recordings/{id}` archives the recording: `204`; `404 not_found`; `409 archived` (already archived). The
audio is kept; the recording leaves lists (`?archived=true` lists it) and `GET` by id still returns it with
`archived_at` set.

## The transcription object

| Field | Type | Description |
|---|---|---|
| `id` | string | `TR…` |
| `recording_id` | string | |
| `call_id` | string or null | |
| `status` | string | `in_progress`, `completed`, `failed` |
| `language` | string | |
| `text` | string or null | |
| `confidence` | null | Not stored today |
| `duration_secs` | integer or null | |
| `price` | money or null | Set once completed |
| `error` | string or null | Why it failed |
| `created_at` | timestamp | |

`GET /transcriptions` filters: `recording_id`, `call_id`, `created_after`, `created_before`; plus `limit`,
`starting_after`.

```sh
curl "https://api.contactivity.io/v1/projects/$PROJECT_ID/transcriptions?recording_id=$RECORDING_ID" \
  -H "Authorization: Bearer $CONTACTIVITY_API_KEY"
```

`GET` and `DELETE /transcriptions/{id}`: `404 not_found` when absent; delete archives it and returns `204`
(`409 archived` when already archived).

Recording and transcription events (`call.recording.completed`, `call.transcription.completed`,
`call.transcription.failed`) are listed in [events.md](/guides/events.md).
