Skip to content

Using the AssemblyAI SDK

Change apiKey and baseUrl and your existing AssemblyAI code runs on Sandchest. Here is exactly which endpoints and options are supported, and which are rejected.

Open .md

Sandchest speaks the AssemblyAI prerecorded API at /v2/*. If you already have AssemblyAI code, keep the official SDK and change two settings. This page shows the swap in TypeScript and Python, then lists precisely what works, what is refused, and where the behaviour differs.

The swap#

TypeScript#

transcribe.ts
import { AssemblyAI } from "assemblyai";

const client = new AssemblyAI({
  apiKey: process.env.SANDCHEST_API_KEY as string,
  baseUrl: "https://stt-api.sandchest.com",
});

const transcript = await client.transcripts.transcribe({
  audio: audioBuffer,
  disfluencies: true,
});

console.log(transcript.speech_model_used);
console.log(transcript.words);

Python#

transcribe.py
import os
import assemblyai as aai

aai.settings.api_key = os.environ["SANDCHEST_API_KEY"]
aai.settings.base_url = "https://stt-api.sandchest.com"

transcript = aai.Transcriber().transcribe("meeting.mp3")

print(transcript.text)
for word in transcript.words:
    print(word.start, word.end, word.text)

That is the whole migration. Uploads, transcript creation, polling, listing, deletion, word search, sentences, paragraphs, SRT and VTT all go through unchanged.

Supported endpoints#

MethodPathNotes
POST/v2/uploadRaw bytes in the body
POST/v2/transcriptIdempotency-Key accepted
GET/v2/transcript/:idReturns the current state immediately
GET/v2/transcriptlimit, status, created_on, before_id, after_id
DELETE/v2/transcript/:idErases words, text and source URLs
GET/v2/transcript/:id/sentencesCompleted transcripts only
GET/v2/transcript/:id/paragraphsCompleted transcripts only
GET/v2/transcript/:id/word-searchwords= required
GET/v2/transcript/:id/srtchars_per_caption supported
GET/v2/transcript/:id/vttchars_per_caption supported

Those ten paths are the complete surface. Streaming/real-time transcription, LeMUR, and the AssemblyAI audio-intelligence endpoints are not implemented. Full details in the API reference.

Supported options#

audio_url, speech_model, speech_models, language_code, language_detection, language_confidence_threshold, language_detection_options, punctuate, format_text, disfluencies, custom_spelling, multichannel, audio_start_from, audio_end_at, webhook_url, webhook_auth_header_name and webhook_auth_header_value.

Every field is documented in Transcript options.

Options that are rejected#

Sandchest never acknowledges a request whose options it silently dropped. If it cannot do the thing you asked for, it says so with HTTP 400 and this exact body shape:

You sentResponse
speaker_labels: true or any speakers_expected{"error":"Speaker identification is not supported."}
a non-empty word_boost, or any boost_param{"error":"Custom word boosting is not supported."}
any option Sandchest does not implement{"error":"The request contains an unsupported option or an invalid option value."}

That last row is the one to plan for. The AssemblyAI audio-intelligence options — summarization, auto_chapters, auto_highlights, entity_detection, content_safety, iab_categories, sentiment_analysis, redact_pii, dual_channel, language_codes and friends — are not in Sandchest's schema, so a request carrying them is refused rather than quietly stripped. Remove them before you switch a workload over.

The language options have their own rules:

You sentResponse
no language_code and language_detection: false{"error":"Either `language_detection` must be set to True, or one of `language_code` or `language_codes` must must be specified."}
a language_code and language_detection: true{"error":"`language_detection` is not available when `language_code` is specified."}
language_confidence_threshold without detection{"error":"language_confidence_threshold requires language_detection."}

Omit both and you get automatic detection, which is what most callers want. See Languages.

Differences to expect#

GET returns immediately. AssemblyAI's GET /v2/transcript/:id and Sandchest's both return the current state without waiting. The SDK's transcribe() and waitUntilReady() own the polling loop, at their configured interval. Nothing to change — just do not write code that assumes the request blocks until completion.

speech_model_used tells the truth. You can keep sending AssemblyAI model names in speech_models or speech_model for compatibility; they are accepted and echoed back in the response's speech_models. speech_model_used reports the model that genuinely produced the transcript, for example nvidia/parakeet-tdt-0.6b-v2.

disfluencies defaults to false. New transcripts drop English filled pauses ("um", "uh") unless you ask for them. Send disfluencies: true for verbatim output.

Deletion is a tombstone. DELETE erases words, text, source URLs, custom vocabulary and private error detail, then returns an object with status: "completed", text: "Deleted by user." and audio_url: "http://deleted_by_user". Usage and billing history survive.

Unknown transcript ids are a 400, not a 404. The compatibility endpoints match AssemblyAI here: {"error":"Transcript lookup error, transcript id not found"} with HTTP 400. The native endpoint at /api/v1/transcripts/:id returns a plain 404 instead.

Non-English coverage is narrower than the code list. The API accepts the full AssemblyAI language-code list, but the deployed model decodes a smaller set. A code outside it fails at inference time with a clear message on the transcript's error field. Languages has the exact list.

Verify#

Run your existing AssemblyAI code against Sandchest and check the model identifier — if it names a Parakeet model, you are on Sandchest and not on AssemblyAI.

shell
curl -sS "https://stt-api.sandchest.com/v2/transcript/$ID" \
  -H "Authorization: $SANDCHEST_API_KEY" \
  | jq '{status, speech_model_used, speech_models}'
expected output
{
  "status": "completed",
  "speech_model_used": "nvidia/parakeet-tdt-0.6b-v2",
  "speech_models": ["universal-2"]
}

Next#

Transcript options — every request field and every field on the object that comes back.