Whisper API

High-performance audio transcription powered by OpenAI Whisper. Upload files or provide URLs for fast, accurate speech-to-text with subtitle generation, word timestamps, and batch processing.

BASE URL https://whisper.ipsecure.ca
GET /health

Returns server health status, current queue statistics, and upstream GX10 Whisper engine availability. Use this for monitoring and readiness checks.

Response

{
  "status": "ok",
  "uptime": 84321,
  "queue": {
    "pending": 2,
    "processing": 1,
    "completed": 1047,
    "failed": 3
  },
  "gx10": {
    "status": "online",
    "responseTime": 42
  }
}
# Health check
curl https://whisper.ipsecure.ca/health
const res = await fetch("https://whisper.ipsecure.ca/health");
const data = await res.json();
console.log(data);
import requests

res = requests.get("https://whisper.ipsecure.ca/health")
print(res.json())

POST /transcribe

Transcribe a single audio file. Upload a file via multipart/form-data or provide a remote URL. Supports synchronous mode (wait for result) and asynchronous mode (fire and forget with optional webhook callback).

By default, the request waits for the transcription to complete (wait=true). For large files, set wait=false to receive a job ID and poll or use a callback URL.
.wav .mp3 .m4a .ogg .flac .webm .mp4 max 500 MB

Request Parameters

ParameterTypeRequiredDefaultDescription
filefileconditionalAudio file upload (multipart/form-data). Required if url is not provided.
urlstringconditionalRemote URL of the audio file. Required if file is not provided.
languagestringnoautoISO 639-1 language code (e.g. en, fr, es). Auto-detected if omitted.
taskstringnotranscribetranscribe or translate (translates to English).
word_timestampsbooleannofalseInclude per-word timestamps in the response.
vad_filterbooleannofalseEnable voice activity detection to filter silence and reduce hallucinations.
formatstringnojsonResponse format: json, text, srt, or vtt.
waitbooleannotrueIf true, waits for completion. If false, returns immediately with a job ID.
callbackUrlstringnoWebhook URL to receive the result when transcription completes.

Response — Synchronous (wait=true, format=json)

{
  "success": true,
  "jobId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "text": "Hello, this is a transcription of the audio file.",
  "language": "en",
  "language_probability": 0.98,
  "duration": 12.45,
  "processing_time": 3.21,
  "word_count": 10,
  "segments": [
    {
      "start": 0.0,
      "end": 4.8,
      "text": "Hello, this is a transcription"
    }
  ],
  "words": [
    { "word": "Hello", "start": 0.0, "end": 0.42 }
  ]
}

Response — Asynchronous (wait=false)

{
  "success": true,
  "jobId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "status": "queued",
  "statusUrl": "https://whisper.ipsecure.ca/transcribe/status/a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "estimatedWait": 15
}
# Single file transcription (synchronous)
curl -X POST https://whisper.ipsecure.ca/transcribe \
  -F "file=@recording.wav" \
  -F "language=en" \
  -F "format=json"
const fs = require("fs");

const form = new FormData();
form.append("file", new Blob([fs.readFileSync("recording.wav")]), "recording.wav");
form.append("language", "en");
form.append("format", "json");

const res = await fetch("https://whisper.ipsecure.ca/transcribe", {
  method: "POST",
  body: form
});
const data = await res.json();
console.log(data.text);
import requests

res = requests.post(
    "https://whisper.ipsecure.ca/transcribe",
    files={"file": open("recording.wav", "rb")},
    data={"language": "en", "format": "json"}
)
print(res.json()["text"])
# Single file from URL
curl -X POST https://whisper.ipsecure.ca/transcribe \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/call.wav",
    "language": "en",
    "vad_filter": true
  }'
const res = await fetch("https://whisper.ipsecure.ca/transcribe", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    url: "https://example.com/call.wav",
    language: "en",
    vad_filter: true
  })
});
const data = await res.json();
console.log(data);
import requests

res = requests.post(
    "https://whisper.ipsecure.ca/transcribe",
    json={
        "url": "https://example.com/call.wav",
        "language": "en",
        "vad_filter": True
    }
)
print(res.json())
# Async transcription (fire and forget)
curl -X POST https://whisper.ipsecure.ca/transcribe \
  -F "file=@longfile.mp3" \
  -F "wait=false" \
  -F "callbackUrl=https://yourserver.com/webhook"
const fs = require("fs");

const form = new FormData();
form.append("file", new Blob([fs.readFileSync("longfile.mp3")]), "longfile.mp3");
form.append("wait", "false");
form.append("callbackUrl", "https://yourserver.com/webhook");

const res = await fetch("https://whisper.ipsecure.ca/transcribe", {
  method: "POST",
  body: form
});
const { jobId, statusUrl } = await res.json();
console.log("Job queued:", jobId);
import requests

res = requests.post(
    "https://whisper.ipsecure.ca/transcribe",
    files={"file": open("longfile.mp3", "rb")},
    data={
        "wait": "false",
        "callbackUrl": "https://yourserver.com/webhook"
    }
)
job = res.json()
print(f"Job queued: {job['jobId']}")

GET /transcribe/status/:jobId

Check the status of a transcription job. Returns the current state, queue position (if pending), and the result when complete.

Path Parameters

ParameterTypeRequiredDescription
jobIdstringyesThe unique job identifier returned from a transcribe request.

Response

{
  "success": true,
  "jobId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "status": "completed",
  "queuePosition": 0,
  "result": {
    "text": "Transcribed text here...",
    "language": "en",
    "duration": 12.45,
    "segments": [...]
  }
}
# Check job status
curl https://whisper.ipsecure.ca/transcribe/status/YOUR_JOB_ID
const jobId = "YOUR_JOB_ID";
const res = await fetch(`https://whisper.ipsecure.ca/transcribe/status/${jobId}`);
const data = await res.json();
console.log(data.status, data.result);
import requests

job_id = "YOUR_JOB_ID"
res = requests.get(f"https://whisper.ipsecure.ca/transcribe/status/{job_id}")
data = res.json()
print(data["status"], data.get("result"))

POST /transcribe/batch

Submit a batch of audio files for transcription. Upload up to 200 files via multipart/form-data or provide an array of URLs in a JSON body. All jobs are processed asynchronously.

Maximum of 200 files or URLs per batch request.

Request Parameters

ParameterTypeRequiredDefaultDescription
file[]file[]conditionalArray of audio files (multipart). Required if urls not provided.
urlsstring[]conditionalArray of remote audio URLs (JSON body). Required if file[] not provided.
languagestringnoautoLanguage code applied to all files in the batch.
vad_filterbooleannofalseEnable VAD filtering for all files.
callbackUrlstringnoWebhook URL to receive batch completion notification.

Response

{
  "success": true,
  "batchId": "batch-9f8e7d6c-5b4a-3210-fedc-ba0987654321",
  "total": 3,
  "jobIds": [
    "job-aaa111",
    "job-bbb222",
    "job-ccc333"
  ],
  "statusUrl": "https://whisper.ipsecure.ca/transcribe/batch/batch-9f8e7d6c-5b4a-3210-fedc-ba0987654321",
  "callbackUrl": "https://yourserver.com/webhook/batch-done"
}
# Batch transcription from URLs
curl -X POST https://whisper.ipsecure.ca/transcribe/batch \
  -H "Content-Type: application/json" \
  -d '{
    "urls": [
      "https://yourserver.com/recordings/call1.wav",
      "https://yourserver.com/recordings/call2.wav",
      "https://yourserver.com/recordings/call3.wav"
    ],
    "language": "en",
    "vad_filter": true,
    "callbackUrl": "https://yourserver.com/webhook/batch-done"
  }'
const res = await fetch("https://whisper.ipsecure.ca/transcribe/batch", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    urls: [
      "https://yourserver.com/recordings/call1.wav",
      "https://yourserver.com/recordings/call2.wav",
      "https://yourserver.com/recordings/call3.wav"
    ],
    language: "en",
    vad_filter: true,
    callbackUrl: "https://yourserver.com/webhook/batch-done"
  })
});
const batch = await res.json();
console.log("Batch ID:", batch.batchId);
import requests

res = requests.post(
    "https://whisper.ipsecure.ca/transcribe/batch",
    json={
        "urls": [
            "https://yourserver.com/recordings/call1.wav",
            "https://yourserver.com/recordings/call2.wav",
            "https://yourserver.com/recordings/call3.wav"
        ],
        "language": "en",
        "vad_filter": True,
        "callbackUrl": "https://yourserver.com/webhook/batch-done"
    }
)
batch = res.json()
print(f"Batch ID: {batch['batchId']}")

GET /transcribe/batch/:batchId

Check the status of a batch transcription request. Returns progress percentage, individual job statuses, and results for completed jobs.

Path Parameters

ParameterTypeRequiredDescription
batchIdstringyesThe batch identifier returned from a batch transcribe request.

Response

{
  "success": true,
  "batchId": "batch-9f8e7d6c-5b4a-3210-fedc-ba0987654321",
  "status": "processing",
  "total": 3,
  "completed": 1,
  "failed": 0,
  "progress": 33.3,
  "jobs": [
    { "jobId": "job-aaa111", "status": "completed" },
    { "jobId": "job-bbb222", "status": "processing" },
    { "jobId": "job-ccc333", "status": "queued" }
  ]
}
# Check batch status
curl https://whisper.ipsecure.ca/transcribe/batch/YOUR_BATCH_ID
const batchId = "YOUR_BATCH_ID";
const res = await fetch(`https://whisper.ipsecure.ca/transcribe/batch/${batchId}`);
const data = await res.json();
console.log(`Progress: ${data.progress}%`);
import requests

batch_id = "YOUR_BATCH_ID"
res = requests.get(f"https://whisper.ipsecure.ca/transcribe/batch/{batch_id}")
data = res.json()
print(f"Progress: {data['progress']}%")

GET /transcribe/result/:jobId

Retrieve the transcription result for a completed job. Supports multiple output formats including plain text, SRT subtitles, WebVTT, and full JSON with segments and word timestamps.

Path Parameters

ParameterTypeRequiredDescription
jobIdstringyesThe unique job identifier.

Query Parameters

ParameterTypeRequiredDefaultDescription
formatstringnojsonOutput format: json, text, srt, or vtt.
# Get result as plain text
curl "https://whisper.ipsecure.ca/transcribe/result/YOUR_JOB_ID?format=text"
const jobId = "YOUR_JOB_ID";
const res = await fetch(`https://whisper.ipsecure.ca/transcribe/result/${jobId}?format=text`);
const text = await res.text();
console.log(text);
import requests

job_id = "YOUR_JOB_ID"
res = requests.get(f"https://whisper.ipsecure.ca/transcribe/result/{job_id}", params={"format": "text"})
print(res.text)
# Get result as SRT subtitles
curl "https://whisper.ipsecure.ca/transcribe/result/YOUR_JOB_ID?format=srt"
const jobId = "YOUR_JOB_ID";
const res = await fetch(`https://whisper.ipsecure.ca/transcribe/result/${jobId}?format=srt`);
const srt = await res.text();
console.log(srt);
import requests

job_id = "YOUR_JOB_ID"
res = requests.get(f"https://whisper.ipsecure.ca/transcribe/result/{job_id}", params={"format": "srt"})
print(res.text)

DELETE /transcribe/job/:jobId

Cancel a pending or in-progress transcription job, or delete a completed job and its results. Returns the final status of the job.

Path Parameters

ParameterTypeRequiredDescription
jobIdstringyesThe unique job identifier to cancel or delete.

Response

{
  "success": true,
  "jobId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "status": "cancelled"
}
# Cancel or delete a job
curl -X DELETE https://whisper.ipsecure.ca/transcribe/job/YOUR_JOB_ID
const jobId = "YOUR_JOB_ID";
const res = await fetch(`https://whisper.ipsecure.ca/transcribe/job/${jobId}`, {
  method: "DELETE"
});
const data = await res.json();
console.log(data.status);
import requests

job_id = "YOUR_JOB_ID"
res = requests.delete(f"https://whisper.ipsecure.ca/transcribe/job/{job_id}")
print(res.json())

Webhook Callbacks

When you provide a callbackUrl, the API sends a POST request with a JSON body to your endpoint when transcription completes. Ensure your endpoint returns a 2xx status code.

Single Transcription Callback

{
  "event": "transcription.complete",
  "jobId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "success": true,
  "result": {
    "text": "Transcribed text here...",
    "language": "en",
    "language_probability": 0.98,
    "duration": 12.45,
    "processing_time": 3.21,
    "word_count": 10,
    "segments": [...]
  }
}

Batch Completion Callback

{
  "event": "batch.complete",
  "batchId": "batch-9f8e7d6c-5b4a-3210-fedc-ba0987654321",
  "total": 3,
  "succeeded": 3,
  "failed": 0,
  "results": [
    {
      "jobId": "job-aaa111",
      "success": true,
      "text": "First file transcription..."
    },
    {
      "jobId": "job-bbb222",
      "success": true,
      "text": "Second file transcription..."
    },
    {
      "jobId": "job-ccc333",
      "success": true,
      "text": "Third file transcription..."
    }
  ]
}