Scribe v2
curl --request POST \
--url https://api.snapgen.org/v1/audio/transcriptions \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--form 'model=<string>' \
--form 'audio_url=<string>' \
--form 'language=<string>' \
--form diarize=true \
--form num_speakers=123 \
--form tag_audio_events=true \
--form 'timestamps=<string>' \
--form subtitles=true \
--form temperature=123 \
--form 'response_format=<string>' \
--form file='@example-file'import requests
url = "https://api.snapgen.org/v1/audio/transcriptions"
files = { "file": ("example-file", open("example-file", "rb")) }
payload = {
"model": "<string>",
"audio_url": "<string>",
"language": "<string>",
"diarize": "true",
"num_speakers": "123",
"tag_audio_events": "true",
"timestamps": "<string>",
"subtitles": "true",
"temperature": "123",
"response_format": "<string>"
}
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('model', '<string>');
form.append('audio_url', '<string>');
form.append('language', '<string>');
form.append('diarize', 'true');
form.append('num_speakers', '123');
form.append('tag_audio_events', 'true');
form.append('timestamps', '<string>');
form.append('subtitles', 'true');
form.append('temperature', '123');
form.append('response_format', '<string>');
form.append('file', '{
"fileName": "example-file"
}');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
fetch('https://api.snapgen.org/v1/audio/transcriptions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.snapgen.org/v1/audio/transcriptions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"audio_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"language\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"diarize\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"num_speakers\"\r\n\r\n123\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"tag_audio_events\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"timestamps\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"subtitles\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"temperature\"\r\n\r\n123\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"response_format\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: multipart/form-data"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.snapgen.org/v1/audio/transcriptions"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"audio_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"language\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"diarize\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"num_speakers\"\r\n\r\n123\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"tag_audio_events\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"timestamps\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"subtitles\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"temperature\"\r\n\r\n123\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"response_format\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.snapgen.org/v1/audio/transcriptions")
.header("Authorization", "Bearer <token>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"audio_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"language\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"diarize\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"num_speakers\"\r\n\r\n123\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"tag_audio_events\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"timestamps\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"subtitles\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"temperature\"\r\n\r\n123\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"response_format\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.snapgen.org/v1/audio/transcriptions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"audio_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"language\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"diarize\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"num_speakers\"\r\n\r\n123\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"tag_audio_events\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"timestamps\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"subtitles\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"temperature\"\r\n\r\n123\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"response_format\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_bodyElevenLabs Speech to Text
Scribe v2
ElevenLabs Scribe v2 speech to text with word timings, speaker labels, and SRT subtitles. $0.3312 per hour of audio.
POST
/
v1
/
audio
/
transcriptions
Scribe v2
curl --request POST \
--url https://api.snapgen.org/v1/audio/transcriptions \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--form 'model=<string>' \
--form 'audio_url=<string>' \
--form 'language=<string>' \
--form diarize=true \
--form num_speakers=123 \
--form tag_audio_events=true \
--form 'timestamps=<string>' \
--form subtitles=true \
--form temperature=123 \
--form 'response_format=<string>' \
--form file='@example-file'import requests
url = "https://api.snapgen.org/v1/audio/transcriptions"
files = { "file": ("example-file", open("example-file", "rb")) }
payload = {
"model": "<string>",
"audio_url": "<string>",
"language": "<string>",
"diarize": "true",
"num_speakers": "123",
"tag_audio_events": "true",
"timestamps": "<string>",
"subtitles": "true",
"temperature": "123",
"response_format": "<string>"
}
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('model', '<string>');
form.append('audio_url', '<string>');
form.append('language', '<string>');
form.append('diarize', 'true');
form.append('num_speakers', '123');
form.append('tag_audio_events', 'true');
form.append('timestamps', '<string>');
form.append('subtitles', 'true');
form.append('temperature', '123');
form.append('response_format', '<string>');
form.append('file', '{
"fileName": "example-file"
}');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
fetch('https://api.snapgen.org/v1/audio/transcriptions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.snapgen.org/v1/audio/transcriptions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"audio_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"language\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"diarize\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"num_speakers\"\r\n\r\n123\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"tag_audio_events\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"timestamps\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"subtitles\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"temperature\"\r\n\r\n123\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"response_format\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: multipart/form-data"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.snapgen.org/v1/audio/transcriptions"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"audio_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"language\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"diarize\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"num_speakers\"\r\n\r\n123\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"tag_audio_events\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"timestamps\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"subtitles\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"temperature\"\r\n\r\n123\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"response_format\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.snapgen.org/v1/audio/transcriptions")
.header("Authorization", "Bearer <token>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"audio_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"language\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"diarize\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"num_speakers\"\r\n\r\n123\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"tag_audio_events\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"timestamps\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"subtitles\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"temperature\"\r\n\r\n123\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"response_format\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.snapgen.org/v1/audio/transcriptions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"audio_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"language\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"diarize\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"num_speakers\"\r\n\r\n123\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"tag_audio_events\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"timestamps\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"subtitles\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"temperature\"\r\n\r\n123\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"response_format\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_bodyscribe-v2 transcribes speech with ElevenLabs Scribe v2 on the OpenAI-compatible transcription endpoint. Upload a file or pass a public URL, and receive JSON with the transcript and, on request, word timings, speaker labels, tagged sounds, and SRT subtitles. One request takes up to two hours of audio.
| Property | Value |
|---|---|
| Model ID | scribe-v2 |
| Endpoint | POST /v1/audio/transcriptions (multipart file or JSON audio_url) |
| Output | JSON: text, language, language_probability, duration_seconds, optional words and srt |
| Limits | Up to 7,200 seconds (2 hours) and 50 MB per request |
| Input formats | WAV, AIFF, MP3, AAC, MP4, M4A, MOV, FLAC, Ogg, and WebM with a readable length |
| Billed on | Audio length measured by SnapGen, in whole seconds |
| Price | $0.000092 per second ($0.00552 per minute, $0.3312 per hour) |
string
required
Set to
scribe-v2.file
The audio file, in a multipart field named
file, up to 50 MB. Send file
or audio_url, not both.string
Public
http or https URL of the audio. The gateway downloads it, up to
50 MB. Send audio_url or file, not both.string
Language of the audio as an ISO 639 code of two or three lowercase letters,
such as
en. Omit it to detect the language automatically.boolean
Labels who speaks each word in
words[].speaker.integer
The most speakers in the audio, from
1 to 32. Helps speaker labeling.boolean
Tags sounds such as laughter or footsteps in the transcript.
string
none, word, or character. word and character add words with
word-level timings.boolean
true adds SubRip subtitles in srt. The gateway turns on speaker labels
and word timings at the provider, which subtitles need.number
Randomness, from
0 to 2. Higher values give more varied output.string
default:"json"
json or verbose_json. verbose_json adds words unless timestamps is
none. Both return the SnapGen JSON shape, not OpenAI’s verbose schema.Request
Upload a local file asmultipart/form-data:
curl https://api.snapgen.org/v1/audio/transcriptions \
-H "Authorization: Bearer $SNAPGEN_API_KEY" \
-F model=scribe-v2 \
-F file=@interview.mp3 \
-F diarize=true \
-F subtitles=true
audio_url:
curl https://api.snapgen.org/v1/audio/transcriptions \
-H "Authorization: Bearer $SNAPGEN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "scribe-v2",
"audio_url": "https://example.com/interview.mp3",
"diarize": true,
"subtitles": true
}'
Response
{
"text": "Welcome to the show. Thanks for having me.",
"language": "eng",
"language_probability": 0.99,
"duration_seconds": 12.34,
"srt": "1\n00:00:00,120 --> 00:00:01,480\nWelcome to the show.\n\n2\n00:00:01,900 --> 00:00:03,020\nThanks for having me.\n"
}
text from the result; the extra fields in this response
don’t follow OpenAI’s verbose schema.
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["SNAPGEN_API_KEY"],
base_url="https://api.snapgen.org/v1",
)
with open("interview.mp3", "rb") as audio:
transcript = client.audio.transcriptions.create(model="scribe-v2", file=audio)
print(transcript.text)
const fs = require("node:fs");
const OpenAI = require("openai");
async function main() {
const client = new OpenAI({
apiKey: process.env.SNAPGEN_API_KEY,
baseURL: "https://api.snapgen.org/v1",
});
const transcript = await client.audio.transcriptions.create({
model: "scribe-v2",
file: fs.createReadStream("interview.mp3"),
});
console.log(transcript.text);
}
main();
Words, speakers, and subtitles
| You want | Send | You get |
|---|---|---|
| Plain text | Nothing extra | text, language, duration_seconds |
| Word timings | timestamps: "word" | words[] with start and end in seconds |
| Who said what | diarize: true and timestamps: "word" | words[].speaker, such as speaker_0 |
| Subtitles | subtitles: true | srt, ready to save as a .srt file |
| Subtitles and word timings | subtitles: true and timestamps: "word" | srt and words[] |
| Sound tags | tag_audio_events: true | Tagged sounds in text and words[] |
Price examples
| Length | Price |
|---|---|
| 1 minute | $0.00552 |
| 10 minutes | $0.0552 |
| 1 hour | $0.3312 |
| 2 hours | $0.6624 |
subtitles or diarize don’t change the price.
Synchronous audio endpoints reject
Idempotency-Key. If a request times
out, check your Console request logs before you retry. See
Speech to text for every response
field and error.