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

# Recordings API

> Place eDiscovery legal holds, seal and verify the tamper-evident integrity chain, and mint or revoke guest share links for call and video-room recordings.

# Recordings API

These endpoints govern the compliance and sharing lifecycle of a finalized recording — separate from the post-finalize quality-control surface. They cover three concerns:

* **Legal hold** — exempt a recording from the age-based retention sweeps while litigation or an eDiscovery obligation is open.
* **Cryptographic integrity** — seal a recording into a tamper-evident, per-tenant hash chain, verify it later, and export a portable signed provenance digest an auditor can check offline.
* **Share links** — mint a time-limited, signed public link so a guest with no Orbit account can watch a completed video-room recording, and revoke every outstanding link at once.

**Base path:** `/api/v1/recordings`

**Authentication:** API key (`X-API-Key`) or session JWT.

**Scopes & roles:**

* Legal-hold and integrity reads (`GET`) require the `voice:read` scope.
* Placing/releasing a legal hold (`PUT`) and sealing integrity (`POST .../integrity/seal`) are compliance-governance actions: they require the `voice:write` scope **and** an `owner` or `admin` role, and are audit-logged.
* Share endpoints operate on video-room artefacts: `POST .../share` and `DELETE .../share` require the `video:write` scope.

| Method   | Path                                              | Purpose                                     |
| -------- | ------------------------------------------------- | ------------------------------------------- |
| `GET`    | `/api/v1/recordings/{id}/legal-hold`              | Get the current legal-hold state            |
| `PUT`    | `/api/v1/recordings/{id}/legal-hold`              | Place or release a legal hold               |
| `GET`    | `/api/v1/recordings/{id}/integrity`               | Get the integrity seal (or `sealed: false`) |
| `GET`    | `/api/v1/recordings/{id}/integrity/verify`        | Re-hash the seal and report tamper status   |
| `GET`    | `/api/v1/recordings/{id}/integrity/export-digest` | Export a signed, portable provenance digest |
| `POST`   | `/api/v1/recordings/{id}/integrity/seal`          | Compute and persist the tamper-evident seal |
| `POST`   | `/api/v1/recordings/{id}/share`                   | Mint a time-limited guest share link        |
| `DELETE` | `/api/v1/recordings/{id}/share`                   | Revoke every outstanding share link         |

All endpoints are tenant-scoped: you only ever address recordings in your own account. `{id}` is the recording id (1–128 characters). An unknown id returns `404 NOT_FOUND`; a malformed id or body returns `400 VALIDATION_ERROR`.

## Get legal-hold state

Returns the current eDiscovery legal-hold state for one recording — the `legal_hold` flag, the operator-supplied `reason`, and who/when it last changed. While a recording is held it is exempt from the age-based retention sweeps (both the storage object and the database row), so it survives litigation-preservation obligations.

```bash theme={null}
curl https://api.orbit.devotel.io/api/v1/recordings/rec_abc123/legal-hold \
  -H "X-API-Key: dv_live_sk_your_key_here"
```

```json theme={null}
{
  "data": {
    "recording_id": "rec_abc123",
    "legal_hold": true,
    "reason": "Matter #4821 — preserve pending discovery",
    "updated_by": "user_9f2a",
    "updated_at": "2026-06-18T14:02:11.000Z"
  },
  "meta": { "request_id": "req_...", "timestamp": "2026-06-18T14:09:00.000Z" }
}
```

## Place or release a legal hold

Sets the hold on or off. While held, the recording and its linked video-room session artefacts are exempt from the retention sweeps. This is a compliance-governance action — it requires an `owner` or `admin` role and is recorded in the audit log.

```bash theme={null}
curl -X PUT https://api.orbit.devotel.io/api/v1/recordings/rec_abc123/legal-hold \
  -H "X-API-Key: dv_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "hold": true,
    "reason": "Matter #4821 — preserve pending discovery"
  }'
```

| Field    | Type    | Required | Meaning                                               |
| -------- | ------- | -------- | ----------------------------------------------------- |
| `hold`   | boolean | yes      | `true` to place a hold, `false` to release it.        |
| `reason` | string  | no       | Operator-supplied justification (max 512 characters). |

The response echoes the resulting state, identical in shape to the `GET` above.

## Get the integrity seal

Returns the recording's cryptographic-integrity seal — the content hash, its link in the tenant's recording-integrity hash chain, and the KMS/BYOK key metadata. A raw key reference is never echoed; only the provider and a key fingerprint travel. `sealed` is `false` (and `seal` is `null`) when the recording has not been sealed yet.

```bash theme={null}
curl https://api.orbit.devotel.io/api/v1/recordings/rec_abc123/integrity \
  -H "X-API-Key: dv_live_sk_your_key_here"
```

```json theme={null}
{
  "data": {
    "recording_id": "rec_abc123",
    "sealed": true,
    "seal": {
      "content_sha256": "3b1f...e90a",
      "prev_hash": "0000...0000",
      "current_hash": "9c4d...77b1",
      "canonicalization_version": 1,
      "kms_provider": "gcp-kms",
      "kms_key_fingerprint": "f1:a2:...:c9",
      "encryption_algorithm": "AES-256-GCM",
      "sealed_by": "user_9f2a",
      "sealed_at": "2026-06-18T14:05:00.000Z"
    }
  },
  "meta": { "request_id": "req_...", "timestamp": "2026-06-18T14:09:00.000Z" }
}
```

## Verify the integrity seal

Re-hashes the stored seal and reports whether the recording's bytes and key metadata are intact. `valid` is the verdict; `reason` explains a failure; `current_hash` and `expected_hash` let an integrator compare the stored versus recomputed chain link.

```bash theme={null}
curl https://api.orbit.devotel.io/api/v1/recordings/rec_abc123/integrity/verify \
  -H "X-API-Key: dv_live_sk_your_key_here"
```

```json theme={null}
{
  "data": {
    "recording_id": "rec_abc123",
    "sealed": true,
    "valid": true,
    "reason": null,
    "current_hash": "9c4d...77b1",
    "expected_hash": "9c4d...77b1"
  },
  "meta": { "request_id": "req_...", "timestamp": "2026-06-18T14:09:00.000Z" }
}
```

## Export a signed provenance digest

Returns a portable, HMAC-signed digest a customer ships alongside an exported recording so an auditor can verify provenance offline. The recording must already be sealed — calling this on an unsealed recording returns `400` (`RECORDING_INTEGRITY_NOT_SEALED`).

```bash theme={null}
curl https://api.orbit.devotel.io/api/v1/recordings/rec_abc123/integrity/export-digest \
  -H "X-API-Key: dv_live_sk_your_key_here"
```

The response `data` is a self-contained digest object: the recording id, the sealed chain hashes and key metadata, the issuing jurisdiction and timestamp, and an HMAC signature an auditor recomputes to confirm the digest was issued by your tenant and has not been altered.

## Seal a recording

Computes and persists the tamper-evident seal, chaining it into the tenant's recording-integrity hash chain and stamping the tenant's BYOK/KMS posture. This is a compliance-governance action — it requires an `owner` or `admin` role and is written into the public audit-log hash chain.

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/recordings/rec_abc123/integrity/seal \
  -H "X-API-Key: dv_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "content_sha256": "3b1fce0a3b1fce0a3b1fce0a3b1fce0a3b1fce0a3b1fce0a3b1fce0a3b1fce90a"
  }'
```

| Field                  | Type   | Required | Meaning                                                                                                    |
| ---------------------- | ------ | -------- | ---------------------------------------------------------------------------------------------------------- |
| `content_sha256`       | string | no       | 64-char hex SHA-256 of the recorded media bytes. Defaults to the egress-stamped `metadata.content_sha256`. |
| `encryption_algorithm` | string | no       | Symmetric algorithm the bytes are encrypted under at rest (max 64 characters).                             |

If no content hash is supplied and the egress pipeline has not stamped one yet, the call returns `400` (`RECORDING_INTEGRITY_MISSING_CONTENT_HASH`). On success the response carries `sealed: true` and the resulting seal, in the same shape as the `GET .../integrity` response.

## Mint a share link

Mints a time-limited, signed public link for a **completed video-room recording** so a guest with no Orbit account can watch it. The requested lifetime is clamped server-side to between 5 minutes and 30 days; omit `expires_in_seconds` for the 7-day default. Only completed video-room recordings are shareable — anything else returns `400` (`RECORDING_SHARE_NOT_SHAREABLE`).

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/recordings/rec_abc123/share \
  -H "X-API-Key: dv_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "expires_in_seconds": 604800
  }'
```

| Field                | Type    | Required | Meaning                                                                                                     |
| -------------------- | ------- | -------- | ----------------------------------------------------------------------------------------------------------- |
| `expires_in_seconds` | integer | no       | Requested link lifetime in seconds. Clamped to the \[5 minutes, 30 days] range; omitted defaults to 7 days. |

```json theme={null}
{
  "data": {
    "recording_id": "rec_abc123",
    "share_url": "https://api.orbit.devotel.io/api/v1/public/recordings/eyJ...",
    "token": "eyJ...",
    "expires_at": "2026-06-25T14:09:00.000Z",
    "revocable": true
  },
  "meta": { "request_id": "req_...", "timestamp": "2026-06-18T14:09:00.000Z" }
}
```

The grant lives entirely inside the signed `token` — the only persisted state is a per-recording revocation nonce. A guest opens `share_url` to stream the recording without authenticating.

## Revoke share links

Revokes **every** outstanding link for the recording by rotating its share nonce. Previously-shared URLs stop resolving immediately; you can mint fresh links afterwards. The call is audit-logged.

```bash theme={null}
curl -X DELETE https://api.orbit.devotel.io/api/v1/recordings/rec_abc123/share \
  -H "X-API-Key: dv_live_sk_your_key_here"
```

```json theme={null}
{
  "data": { "recording_id": "rec_abc123", "revoked": true },
  "meta": { "request_id": "req_...", "timestamp": "2026-06-18T14:10:00.000Z" }
}
```

## See also

* [Voice API](/api-reference/voice) — calls that produce recordings
* [Video API](/api-reference/video) — video-room sessions whose recordings are shareable
* [Error codes](/reference/error-codes)
