Skip to main content
POST
/
recordings
/
{id}
/
upload-url
curl -X POST https://api.bota.dev/v1/recordings/rec_abc123/upload-url \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "content_type": "audio/wav",
    "file_size_bytes": 2048576
  }'
{
  "upload_url": "https://bota-uploads.s3.amazonaws.com/proj_xxx/rec_abc123/audio.wav?X-Amz-Algorithm=AWS4-HMAC-SHA256&...",
  "expires_at": "2025-01-15T12:00:00Z",
  "headers": {
    "Content-Type": "audio/wav"
  }
}
Generate a pre-signed S3 URL for uploading audio. Upload the file directly to S3 using the returned URL, then call the Complete Upload endpoint.
id
string
required
The recording’s unique identifier (e.g., rec_abc123).
content_type
string
required
MIME type of the audio file. Supported types:
  • audio/wav
  • audio/mpeg (MP3)
  • audio/mp4
  • audio/webm
  • audio/ogg
  • audio/flac
file_size_bytes
integer
Expected file size in bytes. Used for validation.
curl -X POST https://api.bota.dev/v1/recordings/rec_abc123/upload-url \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "content_type": "audio/wav",
    "file_size_bytes": 2048576
  }'
{
  "upload_url": "https://bota-uploads.s3.amazonaws.com/proj_xxx/rec_abc123/audio.wav?X-Amz-Algorithm=AWS4-HMAC-SHA256&...",
  "expires_at": "2025-01-15T12:00:00Z",
  "headers": {
    "Content-Type": "audio/wav"
  }
}

Uploading the File

After obtaining the pre-signed URL, upload the audio file directly to S3:
cURL
curl -X PUT "https://bota-uploads.s3.amazonaws.com/..." \
  -H "Content-Type: audio/wav" \
  --data-binary @recording.wav
Node.js
const fs = require('fs');

const audioBuffer = fs.readFileSync('recording.wav');

await fetch(upload_url, {
  method: 'PUT',
  headers: {
    'Content-Type': 'audio/wav',
  },
  body: audioBuffer,
});
Python
with open('recording.wav', 'rb') as f:
    audio_data = f.read()

requests.put(
    upload_url,
    headers={'Content-Type': 'audio/wav'},
    data=audio_data,
)
The upload URL expires after 1 hour. If expired, request a new URL. After uploading, call the Complete Upload endpoint to finalize.