S3 recording and transcript storage
This is the canonical S3 file and JSON reference for Super Admins and platform operators. Use it to configure storage access, verify retention, and integrate with recording outputs. Recording and transcript storage covers the controls available to Members and Team Admins in TelWeb.
Configuration and ownership
App recording artefacts are selected in Flow Designer → Flow Settings → App settings. Its destination is configured under Settings → Team → Call recording using the recording S3 bucket, AWS region, and optional recording IAM role ARN. Members and Team Admins can select app artefacts; saving the Team settings form requires a Team Admin. The bucket setting is shared by the team's apps; it is not a platform-wide destination in the Platform Settings tab.
The current Voice recording path uses the app and team configuration. RECORDING_ENABLED and
RECORDING_BUCKET are not controls for this path. Platform operators must provide an existing
bucket and working AWS access for Voice uploads, Ops processing and cleanup, and TelWeb playback,
deletion, and lifecycle configuration. Provision the bucket and IAM role before handing the values
to the team; Team settings does not create either resource.
The current role checks differ between the Team settings form and recording-field updates: the form also submits administrative settings and therefore requires ADMIN+, while an update containing only the recording fields is accepted for MEMBER+. The form's admin requirement is not an admin-only access restriction on the recording fields themselves.
TelWeb does not expose controls for object names, JSON structure, per-turn output formats, or a custom recording retention period. Apps can choose which of the supported artefacts to retain, including transcripts without audio; an empty selection turns recording off. Manage the bucket policy and lifecycle with AWS access; see Retention and destination changes.
Conversation prefix
New recordings use this S3 key prefix:
The exact object-key or JSON example is preserved in the recording-contract edition for this historical release. Follow the returned object and audio references; do not infer an integration-specific identifier or optional suffix.
| Component | Meaning |
|---|---|
{teamId} | Team that owns the recording. |
{appId} | App that handled the call. |
{ISO-timestamp} | UTC call-start time formatted as YYYY-MM-DDTHH-mm-ss (no milliseconds or Z). |
{conversationId} | Delphi conversation ID. |
For example, a call starting at 2026-09-10T10:15:30.123Z can use
the integration-specific example prefix in the assigned recording reference.
Conversation IDs are sanitized for the key; use the recorded prefix rather than rebuilding it.
Older recordings can use a recording ID or call ID in the final prefix component. Delphi still checks those legacy locations when retrieving recordings.
Objects stored for a call
A fully processed call can contain the following supported outputs. Objects are created only when the app selected that artefact and the call contains the corresponding recording stage or turn data. RFC4733 / SIP INFO keypad events are reconstructed into the full call transcript and full-call MP3s when selected; STT/TTS turn artefacts remain speech-only.
The exact object-key or JSON example is preserved in the recording-contract edition for this historical release. Follow the returned object and audio references; do not infer an integration-specific identifier or optional suffix.
| Object | When present | Contents |
|---|---|---|
call-transcript.json | Recording metadata is uploaded. | Call identifiers and context, recording status, source-stage codec metadata, the complete recording-side transcript snapshot, node history, actions, and final context. |
transcript-stt-input.json | Turn artefacts are generated. | Caller turns in chronological order, including transcript text, timing, provider/model metadata, and references to matching objects under stt-input/. |
transcript-tts-output.json | Turn artefacts are generated. | Bot turns in chronological order, including synthesized text, timing, provider/model metadata, and references to matching objects under tts-output/. |
recording-processed.mp3 | Caller audio after preprocessing exists. | Call-level mix using caller audio after audio preprocessing. With bot audio, the caller is the left channel and the bot is the right channel. |
recording-raw.mp3 | Caller audio before preprocessing exists, or only bot audio does. | Call-level mix using caller audio before audio preprocessing. With bot audio, the caller is the left channel and the bot is the right channel. |
stt-input/NNNN_client.raw | An unprotected caller turn contains audio. | One headerless caller-audio excerpt per STT turn. |
tts-output/NNNN_bot.raw | An unprotected bot turn contains audio. | One headerless bot-audio excerpt per TTS turn. |
The normal Voice processing job requests per-turn raw output. Ops also supports per-turn MP3
when a processing job requests it; in that case, files such as stt-input/0001_client.mp3 are
referenced by the JSON item's audio.mp3 and s3Audio.mp3. This is not a TelWeb format selector.
The call and turn JSON files are independently selectable. A turn document can have an empty
items array. Do not require all three JSON files for every recording. If an integration needs
per-turn audio references, select the corresponding STT/TTS transcript artefact as well as its audio.
The caller and bot sequence numbers are independent, zero-padded, and start at 0001. Use the
audio or s3Audio references in the matching transcript JSON as the source of truth instead of
constructing object keys from the sequence number.
The three commonly confused audio objects
pre-audioproc.raw
This is the temporary caller-to-AI source track captured before audio preprocessing such as
denoising. It is headerless audio, not a WAV file. Its codec, sample rate, bit depth, channel count,
and byte count are recorded under the pre-audioproc stage in call-transcript.json.
outbound.raw
This is the temporary AI-to-caller source track: the bot audio Delphi sent towards the caller. It is
also headerless audio. Its decoding parameters are recorded under the outbound stage in
call-transcript.json.
recording-raw.mp3
This is the supported, playable MP3 generated from the pre-audio-processing caller track and the bot track. When both tracks exist it is stereo:
- left channel: caller audio before preprocessing;
- right channel: bot audio sent to the caller.
If only one side exists, Delphi produces a mono MP3. “Raw” in this filename describes which caller track was selected; the object itself is an encoded MP3, not raw headerless audio.
Temporary processing objects
When audio artefacts are selected, Voice uploads the following source objects at call completion so the Ops Tasker can generate the selected MP3 recordings and per-turn artefacts. A full-call transcript-only selection does not upload these audio sources:
| Object | Contents |
|---|---|
pre-audioproc.raw | Caller audio before audio preprocessing. |
post-audioproc.raw | Caller audio after audio preprocessing. |
outbound.raw | Bot audio sent towards the caller. |
These objects are processing inputs, not supported final outputs. A separate retryable cleanup job
deletes them after recording processing succeeds. They can remain visible while the recording has
status PROCESSING, after a failed or incomplete processing/cleanup job, or in recordings created
by a release that did not yet clean up source objects.
.raw objectsUse the MP3 recordings and the audio references in the transcript JSON files. Temporary source objects can disappear after processing or a later cleanup retry.
Raw audio format
All .raw objects are headerless audio byte streams. They do not contain a RIFF/WAV header, so the
filename alone is not enough to decode them.
- Call-level source parameters are in the matching
recording.stagesentry incall-transcript.json. - Turn-level parameters are in the item's
mediaFormatfield intranscript-stt-input.jsonortranscript-tts-output.json. - Examples include
raw/lpcm16_16for signed 16-bit little-endian PCM at 16 kHz,raw/alaw_8for A-law at 8 kHz, andraw/mulaw_8for μ-law at 8 kHz.
WAV is not a persisted recording-output format.
Transcript JSON roles
The three current JSON documents serve different purposes:
| Document | Scope | Use it for |
|---|---|---|
call-transcript.json | Call | Call context, complete transcript snapshot, recording status, and the metadata required to interpret source audio. |
transcript-stt-input.json | Turn | Caller/STT turns and their per-turn audio references. |
transcript-tts-output.json | Turn | Bot/TTS turns and their per-turn audio references. |
All three use UTF-8 JSON, ISO 8601 UTC timestamps, and a top-level schemaVersion. Consumers should
ignore unknown fields so compatible metadata can be added later.
transcript-full.json is a legacy object. It duplicated the combined caller and bot turn data now
split between transcript-stt-input.json and transcript-tts-output.json; new recordings do not
produce it. It can still be present in recordings created by older releases.
call-transcript.json
When Full call transcript is selected, TelPhi writes this call-level document before any
asynchronous audio processing finishes. Its
recording.recordingStatus can therefore be PROCESSING, and recording.recordingFile can still
be null at upload time. For a full-call transcript-only selection, no audio processing is needed;
the conversation can be AVAILABLE with recordingFile: null and no audio player. This JSON is
a capture-time snapshot, not a live view of the later conversation status.
The exact object-key or JSON example is preserved in the recording-contract edition for this historical release. Follow the returned object and audio references; do not infer an integration-specific identifier or optional suffix.
The transcript, nodeHistory, actionsLog, finalContext, and systemContext values are
conversation snapshots. The recording.stages array describes the available source tracks and
their captured turn segments. A stage is pre-audioproc, post-audioproc, or outbound.
STT and TTS turn documents
transcript-stt-input.json contains only caller (client) turns.
transcript-tts-output.json contains only bot turns. They share this envelope and item format:
The exact object-key or JSON example is preserved in the recording-contract edition for this historical release. Follow the returned object and audio references; do not infer an integration-specific identifier or optional suffix.
Turn item fields
| Field | Meaning |
|---|---|
turnId | Provider or pipeline turn identifier. |
side | Display label: Client or Bot. |
speaker | Stable value: client or bot. |
timestamp | Absolute turn start time, when available. |
startMs | Turn start relative to recorder initialisation. |
endMs | Turn end relative to recorder initialisation, or null. |
durationMs | Captured or derived turn duration, or null. |
text | STT result or the text supplied to TTS; null when unavailable or protected. |
audio | Relative turn-audio paths keyed by raw and, when generated, mp3. |
s3Audio | Full S3 object keys for the same audio. |
mediaFormat | Raw encoding and rate, such as raw/lpcm16_16. |
provider | STT or TTS provider identifier, or null. |
model | Provider model or deployment identifier, or null. |
stage | Source stage used for the segment. |
nodeId | Matching flow node, or null. |
storageRedacted | true when storage was suppressed for this turn. |
redactionReason | The stored reason for a redacted turn. |
Items remain in chronological order. Optional source metadata uses null; audio keys are omitted
when that output was not generated.
DTMF reconstruction
Delphi prefers RFC4733 telephone-event and accepts SIP INFO as a fallback. Those transports do
not put an audible tone in the recorded PCM, so keypad presses are silent unless reconstructed.
When the matching artefact is selected:
call-transcript.jsoninserts sidecar-onlyDTMF 5lines and a top-leveldtmfEventsarray.recording-processed.mp3andrecording-raw.mp3overlay ITU-T Q.23 tones on the caller channel.
STT/TTS transcript JSON and per-turn stt-input/ / tts-output/ files stay speech-only.
Retention and destination changes
Saving a non-empty recording bucket in Team settings attempts to install or replace the S3 rule
delphi-recordings-ttl, expiring objects under recordings/ after 180 days. Other lifecycle
rules are preserved. This applies to audio, transcript JSON, and any remaining temporary sources
under that prefix. TelWeb has no custom retention-period field.
The lifecycle update can fail while the team settings save still succeeds, for example when AWS
permissions are missing. Verify the rule in S3 and check TelWeb/TelAPI logs for
Could not set S3 lifecycle on recording bucket. Do not treat 180-day expiry as guaranteed by the
saved settings. If you manage a different expiry period in AWS, account for later Team settings
saves that include the bucket: they can replace Delphi's rule with the 180-day default.
Clearing the app's recording-artefact selection does not remove existing objects. Changing the team's bucket, region, or role does not migrate recordings; playback and deletion use the team's current storage settings. Plan migration and access before switching destinations. TelWeb's recording deletion removes the objects found under the call's current and legacy prefixes, including transcript JSON, then clears the recording status. It does not delete the conversation row or diagnostic logs.