Voice call recordings to your own bucket (BYO storage)
By default, a call recording lands on Orbit-managed object storage. Regulated tenants often need more than that default: the recording must land in a bucket the tenant owns so the audio archive sits in their own cloud account — which is also where their own knowledge-ingest and quality pipelines read it back from. Therecording_storage organization setting gives you that control for voice recordings. It is the standing, organization-level analogue of the per-request recording_storage field on video rooms: you set it once, and every call recording on the account is routed to the declared destination. There is no request-body field on call start or recording start — call recordings are asynchronous, so the destination comes from your organization’s stored configuration.
1. What goes into the BYO bucket
Voice recording BYO storage currently moves one artifact class:- Call recordings — the finalized audio file for each recorded call. The object lands under
recordings/<tenant>/<callId>.mp3inside the destination bucket (or under your configuredprefixinstead ofrecordings). The recording metadata — thegs://path, duration, and transcript — is still recorded against the call in Orbit, so the call log and QA surfaces keep working exactly as before.
- Transcripts and QA artifacts — transcription, quality-evaluation, and sentiment outputs live in your workspace data, not as objects in the bucket. The recording’s transcript is stored with the call record (and reachable through the recordings API), not written as a second object.
- The object-path record — Orbit records the
gs://<bucket>/<object>path of every recording so read-back and audit surfaces can point at it. That descriptor never carries credentials. - Video room recordings — a separate, per-request control. See the video room BYO storage guide; do not infer its per-request behaviour onto calls.
2. Bucket and IAM setup
The supported BYO destination for call recordings is a Google Cloud Storage bucket you own. Create a dedicated bucket for call recordings — do not reuse a general-purpose bucket. Orbit’s recording service authenticates to your bucket with its workload identity (the cross-project grant case): there is no service-account JSON key to register and no persisted secret. What Orbit needs from you is a grant, not a credential. Grant the role on the bucket only, to Orbit’s recording service account:roles/storage.objectCreator— lets the recording upload write new objects into the bucket.- Nothing else. Do not grant
roles/storage.admin(too broad), do not grant at the project level, and do not add list/delete permissions you have no use for — least privilege is the whole point of BYO.
roles/storage.objectViewer on the same bucket. Keep the two grants separate so each identity carries only the scope it needs.
An S3 destination is accepted on the setting for parity with the video-room surface, but the synchronous call-recording path cannot honour it today — an S3-configured organization falls back to Orbit-managed storage for call recordings while the configuration is preserved. Use GCS for BYO call recordings.
3. Register the bucket
Recording storage is an organization setting. Set it through the settings API (PUT /api/v1/organization/settings) — the same endpoint-backplane that the dashboard’s organization settings use:
provider—"gcs"for a customer bucket,"orbit"for Orbit-managed storage.bucket— a valid bucket name: lowercase alphanumerics plus.,_, and-; 3–255 chars; must start and end alphanumeric.prefix— optional object-key prefix. Restricted to[A-Za-z0-9._/-]; traversal segments (..) are stripped. When omitted, objects land underrecordings/.region— meaningful only forprovider: "orbit"(a data-residency audit pin; see Pin a region, below).
recording_storage back to null (or { "provider": "orbit" }).
Verify with a write-and-read probe
After registering, confirm the route end to end:- Place a short test call with recording enabled and let it finalize.
- In your bucket, confirm a new object appeared under
recordings/<tenant>/<callId>.mp3(or under your prefix). The object key is also visible in the call’s recording metadata — compare it against the object that landed. - Fetch the call’s recording in the dashboard or via the recordings API — the metadata should point at the
gs://path in your bucket, and playback (see Reading a recording back, below) should succeed.
4. Where the write path lands
Object keys are deterministic so a pipeline can address them without a lookup:<tenant> is the tenant-scoped folder name portion of your organization’s storage path; <callId> is the call identifier already present in your call logs and webhooks. Transcripts and QA artifacts are not objects — they live in the workspace data (see §1).
5. Reading a recording back
There are two read-back paths and they serve different audiences:- QA and dashboard surfaces — Orbit’s recording library, call log, and QA panels read the recording through a presigned URL the platform mints for the object path on demand. Nothing changes for those surfaces when you go BYO: they still resolve the stored
gs://path to a time-limited playable URL the same way they do for Orbit-managed storage. - Your own systems — because the bucket is yours, your own tooling can also read objects directly with your own credentials (for example, a
gsutil/storageclient or a signed URL minted by your own service account). Use this for bulk export or an ingest pipeline; the platform’s presigned URL is for the QA surfaces and single-recording playback.
6. The SIPREC uploader side
The SIPREC recording-ingest pipeline (the service that receives SIPREC-recorder pushes) supports the same BYO convention: when your organization has a customer GCS destination configured, SIPREC uploads land in your bucket under the samerecordings/<tenant>/<callId> object-key shape, and the stored gs:// path points into your account. If you ingest via SIPREC (call recording from your own SBC/recorder rather than Orbit’s outbound call recording), the registration is the same one — there is no second setting to manage.
This guide otherwise scopes itself to CCaaS (Orbit call) recordings; the mechanics above are the ones you run for that path.
7. Lifecycle: retention and deletion hooks are yours
Orbit records the object path but does not enforce retention on customer bucket objects. Retention of the audio is the bucket’s own lifecycle policy:- Set a GCS lifecycle rule on the bucket — for example, delete objects 90 days (or your policy’s window) after creation — and that policy owns expiry, not Orbit.
- Deleting or expiring an object in the bucket does not retro-edit the recording metadata; the workspace keeps the
gs://path record, and read-back then fails when the object is gone (see the next section). If you need the workspace to forget the recording too, act on it through the recordings API (retention / delete there) rather than only emptying the bucket.
8. Credential rotation and misconfiguration: the read-back error modes
Because there is no persisted credential on the Orbit side, “credential rotation” reduces to the IAM grant — if you rotate the underlying service account on your side, the Orbit-side grant still names Orbit’s recording service account and remains valid. The failure modes that actually surface are destination-side:- Upload rejected — the recording upload was denied (grant revoked, wrong bucket name, bucket deleted). The recording is preserved on Orbit-managed storage rather than lost, and the stored destination falls back; fix the grant or bucket and subsequent recordings honour BYO again.
- QA playback fails with a read-back error — the stored
gs://path resolves to an object that no longer exists (lifecycle expired it early, or it was deleted in the bucket). The metadata is intact but the object is gone; there is no platform copy to fall back to once the original upload was honoured. - Malformed destination rejected at write — an invalid bucket name or out-of-set
prefixcharacter fails the settings write (PUT /organization/settings) with a validation error before it reaches any upload path.
9. Worked example: a HIPAA tenant under a BAA imposing BYO storage
A healthcare contact-center tenant signs a BAA that requires call recordings (potential PHI) to live in cloud storage the covered entity controls.-
Provision the bucket in the tenant’s own GCP project:
acme-health-recordings, uniform bucket-level access, no public access. -
Grant Orbit’s recording service account
roles/storage.objectCreatoron that one bucket — write-only on the bucket, nothing at project scope. -
Register the destination:
-
Run the write-and-read probe with a test call, confirm the object lands under
recordings/<tenant>/<callId>.mp3in the tenant’s bucket, and confirm QA playback still works through the dashboard. - Set the bucket lifecycle to the tenant’s HIPAA retention schedule (for example, delete after the BAA’s agreed retention window).
Where to go next
- Video room recording to your own bucket — the per-request, video surface of the same control.
- Operate the post-call recordings pipeline — QC, legal hold, integrity seals, captions, and clips on finalized recordings.
- HIPAA compliance controls — the BAA-gated posture this destination fits.
- Customer-Managed Keys (BYOK) — the complementary key-management control for regulated tenants.