VoiceML / Recording
Capture call audio to your own storage or your own recorder.
VoiceML offers two independent recording paths. <Record>, recorded <Dial> / <Conference>, and the Recordings REST API upload WAV files to your Amazon S3 bucket. <Start><Siprec> and the Siprec REST API fork live media in parallel to your Session Recording Server over standard SIPREC (RFC 7866). Use either, both, or neither — each is configured separately on your account.
Free trial Compatibility matrix
Two recording paths, fully independent
| Method | What it does | Where audio goes |
|---|---|---|
| Amazon S3 recordings | Captures call audio as WAV files via <Record>, recorded <Dial> / <Conference>, or the Recordings REST API. |
Your own S3 bucket |
| SIPREC recording | Forks live call media in parallel to your Session Recording Server (SRS) via <Start><Siprec> or the Siprec REST API. |
Your SIPREC-compatible recorder |
Both methods are bring your own. VoiceTel does not store recordings on shared platform storage. Until you configure a destination, calls are not recorded and nothing is kept on our side.
Amazon S3 recordings
Store call recordings in your own AWS account. VoiceML uploads each recording to your S3 bucket using credentials you provide. You pay AWS directly — there is no VoiceTel markup on storage.
Enable S3 recording
Configure your destination from the Account page in the VoiceML portal (section Amazon recordings):
- Open Account and scroll to Amazon recordings.
- Enter your bucket details and IAM credentials (see table below).
- Save. New recordings upload to your bucket on the next recorded call.
| Field | Example | Notes |
|---|---|---|
| Bucket name | acme-voiceml-recordings |
S3 bucket in your AWS account |
| Region | us-east-1 |
Must match the bucket's region |
| Object key prefix | prod/recordings |
Optional path prefix |
| Access key ID | AKIA… |
IAM user with bucket access |
| Secret access key | (write-only) | Leave blank to keep the saved secret |
| KMS key ID | arn:aws:kms:us-east-1:123…:key/… |
Optional — per-object encryption |
The secret access key is write-only in the portal: leave it blank to keep the existing value, or paste a new value to replace it.
Object key layout
Each recording is stored as:
<prefix>/<AccountSid>/<RecordingSid>.wav
For example, with prefix prod/recordings:
prod/recordings/AC<your-account-sid>/RE<recording-sid>.wav
AWS setup checklist
Before saving your portal settings:
- Create an S3 bucket in your AWS account (private — block public access).
- Create an IAM user scoped to that bucket only.
- Attach a minimum policy allowing upload, download, and delete on objects in the bucket:
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "VoiceMLRecordings",
"Effect": "Allow",
"Action": ["s3:PutObject", "s3:GetObject", "s3:DeleteObject"],
"Resource": "arn:aws:s3:::your-bucket-name/*"
}]
}
- Generate an access key for that IAM user and enter it in the portal.
Optional: enable bucket encryption (SSE-S3 or SSE-KMS) and a lifecycle policy to expire old recordings after your retention period.
When S3 recording applies
S3 recording is used by:
- The
<Record>verb <Dial record="record-from-answer">(and other non-do-not-recordvalues)<Conference record="record-from-start">(and similar)POST /Calls/{CallSid}/Recordingson the REST API
If your S3 destination is not configured, these verbs skip recording and the call continues normally — no audio is captured and no copy is kept on VoiceTel infrastructure.
Using <Record>
The <Record> verb captures audio from the live call into a WAV file and uploads it to your S3 bucket.
Quick start
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Record action="/handle-recording" method="POST"
maxLength="120" playBeep="true" />
</Response>
When recording finishes, VoiceML posts to your action URL with Twilio-compatible form fields:
| Field | Meaning |
|---|---|
RecordingSid | Unique recording identifier (RE…) |
RecordingUrl | URL to fetch the WAV via the VoiceML Recordings API |
RecordingDuration | Length in seconds |
Digits | DTMF key that ended the recording, hangup, or empty |
Common attributes
| Attribute | Default | Purpose |
|---|---|---|
maxLength | 3600 | Maximum recording length in seconds |
timeout | 5 | Seconds of silence before recording ends |
finishOnKey | # | DTMF key that stops recording |
playBeep | true | Play a beep before recording starts |
trim | trim-silence | Strip leading/trailing silence |
recordingStatusCallback | (none) | Webhook for lifecycle events (in-progress, completed, absent) |
transcribe | false | Run speech-to-text after recording (requires STT configured — see the speech recognition guide) |
transcribeCallback | (none) | URL POSTed with the transcript when transcribe="true" |
Voicemail-style flow
When action is omitted, VoiceML re-fetches the current document after the recording finishes:
<Response>
<Say>Please leave a message after the tone.</Say>
<Record maxLength="120" transcribe="true"
transcribeCallback="/voicemail-transcript" />
<Say>We did not receive a recording. Goodbye.</Say>
</Response>
Recording bridged and conference calls
<Dial>
Record the bridged portion of an outbound call:
<Response>
<Dial record="record-from-answer"
recordingStatusCallback="https://app.example/recording-status">
<Number>+18005551234</Number>
</Dial>
</Response>
record value |
Behavior |
|---|---|
do-not-record | No recording (default) |
record-from-answer | Start when the called party answers |
record-from-ringing | Start when ringing begins |
record-from-answer-dual | Dual-channel recording from answer |
Use recordingTrack="inbound", outbound, or both to select which leg is captured.
<Conference>
Record a conference room:
<Response>
<Dial>
<Conference record="record-from-start"
recordingStatusCallback="https://app.example/conf-recording">
Support Queue
</Conference>
</Dial>
</Response>
S3 must be configured on your account for <Dial> and <Conference> recording to produce files.
Fetch and manage recordings
Download a recording
After a recording completes, fetch the WAV from the URL in RecordingUrl (or via the REST API):
GET /2010-04-01/Accounts/{AccountSid}/Recordings/{RecordingSid}.wav
Authenticate with your account SID and API key. The response redirects to a short-lived download URL for the object in your S3 bucket.
REST API
| Method | Path | Purpose |
|---|---|---|
GET | /Recordings | List recordings for your account |
GET | /Recordings/{Sid} | Fetch recording metadata |
GET | /Recordings/{Sid}.wav | Download the WAV |
DELETE | /Recordings/{Sid} | Delete the recording (S3 object and metadata) |
POST | /Calls/{CallSid}/Recordings | Start recording on a live call |
POST | /Calls/{CallSid}/Recordings/{Sid} | Pause or resume (where supported) |
Recording metadata includes status, duration, date_created, and the public uri for the resource.
SIPREC recording
SIPREC (RFC 7866) sends a parallel copy of the call's media to your own Session Recording Server while the call continues normally. Use SIPREC when you already operate an enterprise recorder (compliance archive, quality monitoring, WORM storage, etc.) and want VoiceML to act as the Session Recording Client (SRC).
SIPREC is independent of Amazon S3 recording:
- S3 captures WAV files through VoiceML verbs.
- SIPREC streams live media to your SRS in real time.
- You can run both on the same call if your compliance design requires it.
There is no platform-default SRS. A call that references an unknown, disabled, or unconfigured connector records nothing via SIPREC (the call itself is unaffected).
Configure SIPREC connectors
A connector gives your SRS a name that VoiceML and the REST API can reference. Each connector points at one SRS SIP URI.
Portal setup
- Open Account in the VoiceML portal.
- In SIPREC recording, click Manage SIPREC connectors.
- Click Add a connector and fill in:
| Field | Example | Notes |
|---|---|---|
| Connector name | primary-srs | Referenced by connectorName in voice markup — unique per account, no spaces |
| Friendly name | Compliance recorder | Optional label for your team |
| SRS SIP URI | sip:srs.example.com:5070;transport=tcp | Your recorder's SIP endpoint |
| Enabled | Checked | Disabled connectors record nothing |
- Save. The connector is available on the next call.
SRS SIP URI format: use a standard SIP or SIPS URI with the host, port, and transport your recorder expects. Examples:
sip:10.0.1.50:5060
sip:recorder.example.com:5070;transport=tcp
sips:recorder.example.com:5061;transport=tls
Obtain the exact URI from your recorder vendor's documentation (see compatible Session Recording Servers below). Your SRS must be reachable from VoiceTel over the network paths your deployment uses.
Ensure your SRS firewall and security groups allow inbound SIP (and RTP) from VoiceTel's media and signaling addresses.
Using <Start><Siprec>
Start SIPREC on a live call, then continue with other voice-markup verbs:
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Start>
<Siprec connectorName="primary-srs"
name="compliance-trail"
track="both_tracks"
statusCallback="https://app.example/siprec-status"
statusCallbackMethod="POST">
<Parameter name="tenant" value="acme-prod"/>
<Parameter name="department" value="support"/>
</Siprec>
</Start>
<Dial><Number>+18005551234</Number></Dial>
<Stop><Siprec/></Stop>
</Response>
Attributes
| Attribute | Required | Purpose |
|---|---|---|
connectorName | Yes | Names the connector you registered in the portal |
name | No | Identifier for logs and callbacks |
track | No | inbound_track, outbound_track, or both_tracks (default) |
statusCallback | No | Webhook for SIPREC lifecycle events |
statusCallbackMethod | No | GET or POST (default POST) |
<Parameter name="…" value="…"/> children pass metadata through to the SIPREC session. They appear on status callbacks as Parameter.<name> form fields.
Behavior notes
- One active SIPREC session per call. A second
<Start><Siprec>replaces the first. <Stop><Siprec/>ends the fork; otherwise it ends when the call hangs up.connectorNameis required. An empty or unknown name fails without starting a recording session.
REST API
Start or stop SIPREC on a live call without voice markup:
# Start (connector must exist and be enabled)
curl -X POST "https://voiceml.voicetel.com/2010-04-01/Accounts/AC…/Calls/CA…/Siprec" \
-u "AC…:your_api_key" \
--data-urlencode "ConnectorName=primary-srs"
# Stop
curl -X POST "https://voiceml.voicetel.com/2010-04-01/Accounts/AC…/Calls/CA…/Siprec/SR…" \
-u "AC…:your_api_key" \
--data-urlencode "Status=stopped"
Compatible Session Recording Servers
VoiceML implements SIPREC as a Session Recording Client and sends recording sessions to your SRS. Any recorder that accepts standard SIPREC INVITEs can work, subject to your network and codec requirements.
The table below lists widely deployed platforms customers connect to VoiceML. For each one, configure the recorder first, obtain its SRS SIP URI, then enter that URI in your VoiceML connector.
| Platform | Typical use | Configuration resources |
|---|---|---|
| OrecX Oreka | Open-source and commercial SIPREC recorder; popular with VoIP providers | OrecX SIPREC overview · Oreka Administrator Manual |
| NICE CXone / NICE inContact | Enterprise compliance and contact-center recording | NICE CXone SIPREC integration (Avaya/SBC) |
| Verint Financial Compliance | Regulated-industry voice capture and archiving | Verint capture overview |
| VoIPmonitor | Network monitoring and SIPREC-based capture | VoIPmonitor SIPREC setup |
| Oracle Session Border Controller | Carrier/enterprise SBC deployments (SRS destination configuration) | Configuring SIPREC on Oracle SBC |
| Ribbon SBC environments | Service-provider SBC SIPREC deployments | Ribbon SBC SIPREC support |
Example connector entries
After your vendor provides the SRS endpoint, register it in the portal:
| Vendor | Connector name | Example SRS SIP URI |
|---|---|---|
| OrecX Oreka | oreka-primary | sip:10.0.1.12:5090;transport=tcp |
| VoIPmonitor | voipmonitor-prod | sip:monitor.example.com:5099 |
| NICE (via your SBC) | nice-compliance | sip:44.227.106.81:5061;transport=tls |
Replace host, port, and transport with values from your vendor's deployment guide. NICE, Verint, and similar enterprise platforms often require TLS (sips:), specific ports, and allowlisting of VoiceTel's signaling addresses — follow the vendor checklist before going live.
Metadata parameters
Many enterprise recorders expect custom SIPREC metadata (tenant ID, agent ID, call type). Pass these as <Parameter> children on <Siprec>:
<Siprec connectorName="nice-compliance">
<Parameter name="siteId" value="NYC-01"/>
<Parameter name="recordType" value="compliance"/>
</Siprec>
Consult your recorder vendor for supported parameter names.
Migrating from Twilio
VoiceML uses the same voice markup and REST shapes Twilio documents:
| Twilio feature | VoiceML equivalent |
|---|---|
<Record> + RecordingUrl |
Same attributes and callback fields; WAV stored in your S3 bucket instead of Twilio storage |
<Dial record="…"> |
Same; requires S3 configuration on your account |
<Start><Siprec connectorName="…"> |
Same verb; register connectors in the VoiceML portal instead of the Twilio Marketplace |
POST /Calls/{Sid}/Siprec |
Same REST shape |
On Twilio, recordings and SIPREC often run on Twilio-managed storage or connectors. On VoiceML, you configure your own S3 bucket and your own SRS endpoints — billing and data residency follow your AWS and recorder agreements.
Troubleshooting
Amazon S3 recordings
| Symptom | What to check |
|---|---|
| Calls never produce recordings | Confirm Amazon recordings is saved on the Account page with bucket, region, access key, and secret. Without a valid destination, recording verbs skip silently. |
| Recording metadata exists but download fails | Verify the IAM policy includes s3:GetObject and s3:PutObject. Check bucket name and region match the portal settings. |
| Upload errors after key rotation | Update the access key in the portal and save. Test on a new call. |
| Wrong S3 path | Object keys use <prefix>/<AccountSid>/<RecordingSid>.wav — adjust the prefix field if needed. |
SIPREC
| Symptom | What to check |
|---|---|
| SIPREC never starts | connectorName must match a connector registered on SIPREC connectors. The connector must be Enabled. |
| Recorder shows no sessions | Confirm the SRS SIP URI, port, and transport (tcp / tls) match the vendor guide. Check firewall rules allow VoiceTel to reach the SRS. |
| Wrong or missing metadata | Add <Parameter> children with names your recorder expects. |
| Changed connector didn't apply | Connector changes take effect on the next call (or next <Start><Siprec> on a live call). |
| Need both S3 and SIPREC | Configure both independently — S3 on the Account page, SIPREC on the connectors page. They do not conflict. |
General
| Symptom | What to check |
|---|---|
transcribe="true" but no transcript | Configure a speech-to-text provider on the Account page — see the speech recognition guide. |
| Recording callback missing fields | An empty S3 recording produces empty RecordingSid / RecordingUrl on the action callback — configure S3 first. |