Skip to main content

Recordings API

These endpoints govern the compliance and sharing lifecycle of a finalized recording — together with the registry’s listing, media, and transcript operations they cover three concerns:
  • Registry — list a tenant’s finalized recordings, fetch the media (raw audio / video bytes or a signed playback URL), and read the transcript segments that power playback seeking and search.
  • 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.
All endpoints are tenant-scoped: you only ever address recordings in your own account. {id} is the recording id, any 1–128 character string — Orbit currently mints them as rec_ followed by 32 hex characters, and legacy-look ids such as rec_abc123 are accepted as well. An unknown id returns 404 NOT_FOUND; a malformed id or body returns 400 VALIDATION_ERROR.

Using the SDKs

The recordings route has no first-class helper yet — none of the SDKs wraps /recordings — so each language reaches it through the same generic escape hatch, which keeps auth, retries, and the response envelope identical to the typed resources. The samples below run the same call as the curl further down the page.
  • Node.js (@devotel-orbit/node) — orbit.request<T>(method, path)
  • Python (orbit_sdk) — client.request(method, path, params={...})
Python (same call via the SDK’s escape hatch):
The Python SDK is core-scope — it wraps the 8 core resources (messaging, voice, contacts, campaigns, verify, numbers) and reaches everything else through the generic client.request() escape hatch above. See the Python SDK. Raw curl in the body of this page works identically. Full SDK index at SDK quickstart.

List recordings

Returns one page of finalized recordings rows for the calling tenant, newest first — the same rows the dashboard’s recordings list renders, with the QC verdict, transcript readiness, and the legal-hold / integrity-seal flags you navigate to. Page through with ?cursor=<id of the last row> and ?limit=<N>; each page is capped at 200 rows.
200 OK returns the page. data is an array of recordings in the shape the registry returns — use the row id to fetch the transcript, media, or the compliance surfaces below:

Fetch recording media

A record’s media bytes are served through a signed playback URL the registry returns, so a partner integration can stream or download MP3 (audio) / MP4 (video) with no separate GCP credential.
200 OK returns the playback URL plus the row’s content metadata. For the raw bytes themselves pass ?action=download — the response is the binary stream rather than the JSON envelope, so the escape-hatch variant above is the safer default; copy the CDR export pattern when you need the raw bytes in a typed helper.

Get transcript segments

Returns the persisted transcript segments for one completed recording — each entry is one utterance with a start/end offset in milliseconds, a speaker label, and the verbatim text; the player uses these offsets for seek, and the search index ingests the same shape. An in-progress call returns 202 Accepted with transcript_status: "pending" until Deepgram finishes; a failed transcription returns 409 with RECORDING_TRANSCRIPT_NOT_READY.
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.
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.
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.

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.

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).
The response data is a self-contained digest object: the recording id, the sealed chain hashes and key metadata, the issuing operator 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.
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. 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).
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. 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.

See also