Skip to main content

Official Python SDK for the Tuplets transcription API — submit jobs, poll results, direct uploads, diarization, PII redaction, and analytics.

Project description

Tuplets Python SDK

Official Python client for the Tuplets API — transcribe audio, run speaker diarization, apply PII redaction, and request structured analytics from Python 3.10+.

Installation

pip install tuplets-ai

Requires Python 3.10+. The only runtime dependency is httpx.

Quick start

Transcribe a local file, wait for completion, and print the transcript:

import os

from tuplets_ai import JobCreateParams, TupletsClient

client = TupletsClient(api_key=os.environ["TUPLETS_API_KEY"])

job = client.jobs.create_from_file(
    "interview.mp3",
    params=JobCreateParams(language="en"),
)

final_job = client.jobs.wait(job.id)

if final_job.status == "completed":
    transcript = client.jobs.download_result(job.id)
    print(transcript["text"])
elif final_job.status == "failed":
    print(final_job.error_message)

Authentication

Create an API key in the Tuplets dashboard (prefix tb_) and pass it when constructing the client:

client = TupletsClient(api_key="tb_your_api_key")

Every authenticated request sends Authorization: Bearer tb_....

Client configuration

import httpx

from tuplets_ai import TupletsClient

# Custom base URL (defaults to https://api.tuplets.ai)
client = TupletsClient(
    api_key="tb_your_api_key",
    base_url="https://api.tuplets.ai",
    timeout=120.0,
)

# Reuse your own httpx client (connection pooling, proxies, retries, etc.)
http = httpx.Client(base_url="https://api.tuplets.ai", timeout=120.0)
client = TupletsClient(api_key="tb_your_api_key", http_client=http)

with client:
    ...
# or explicitly:
client.close()

Use AsyncTupletsClient the same way with httpx.AsyncClient and async with.

Submitting transcription jobs

All job submission methods return a JobAccepted object with id, status_url, cancel_url, and cancel_token.

From a local file

job = client.jobs.create_from_file(
    "call.wav",
    params=JobCreateParams(language="en", transcription_model="premium"),
)

From bytes (in memory)

from pathlib import Path

audio = Path("call.wav").read_bytes()

job = client.jobs.create_from_bytes(
    filename="call.wav",
    data=audio,
    params=JobCreateParams(language="auto"),
)

From a remote URL

Tuplets fetches the audio from a publicly reachable URL:

job = client.jobs.create_from_url(
    "https://storage.example.com/recordings/call.mp3",
    params=JobCreateParams(language="en"),
)

From a direct upload

For large files, upload to object storage first, then reference the upload when creating the job (see Direct uploads).

job = client.jobs.create_from_uploaded_audio(
    object_key=upload.object_key,
    upload_token=upload.upload_token,
    params=JobCreateParams(language="en"),
)

Job parameters

Pass options via JobCreateParams:

Parameter Type Default Description
language str "auto" BCP-47 language code or "auto" for detection
transcription_model "standard" | "premium" "standard" Accuracy/latency tier
diarization bool False Speaker attribution; when enabled, jobs fail if diarization cannot be produced
pii_processing bool False Detect and redact personally identifiable information
analytics dict None Structured post-transcription analytics (see below)
params = JobCreateParams(
    language="en",
    transcription_model="premium",
    diarization=True,
    pii_processing=True,
)

Polling, waiting, and results

Poll manually

status = client.jobs.get(job.id)

print(status.status)                 # queued | running | completed | failed
print(status.progress_percent)       # 0–100 while running
print(status.estimated_seconds_remaining)
print(status.result)                 # inline preview when completed
print(status.error_message)          # set when status == "failed"

Wait until finished

wait() polls until the job reaches completed or failed:

final_job = client.jobs.wait(
    job.id,
    poll_interval=2.0,   # seconds between polls (default: 2)
    timeout=600.0,       # optional; raises WaitTimeoutError
)

Download the full transcript

transcript = client.jobs.download_result(job.id)
print(transcript["text"])
for segment in transcript.get("segments", []):
    print(segment["start"], segment["end"], segment["text"])

When diarization=True, segments include speaker labels. Completed jobs may also include an analytics object if analytics were requested.

Downloaded JSON includes feature_execution.transcription_model_requested and feature_execution.transcription_model_applied so archived result files record whether standard or premium transcription ran.

List and cancel jobs

recent = client.jobs.list(status="completed", limit=20)
for item in recent.items:
    print(item.id, item.status, item.created_at)

client.jobs.cancel(job.id)

# Cancel without storing the job id (uses token from JobAccepted)
client.jobs.cancel_with_token(job.cancel_token)

Direct uploads

Upload large audio files to signed storage, then create a job from the upload reference:

from pathlib import Path

from tuplets_ai import JobCreateParams, TupletsClient

client = TupletsClient(api_key="tb_your_api_key")
file_path = Path("large-audio.wav")

upload = client.uploads.create_target(
    filename=file_path.name,
    size=file_path.stat().st_size,
    content_type="audio/wav",
)

client.uploads.upload_file(upload, file_path)

job = client.jobs.create_from_uploaded_audio(
    object_key=upload.object_key,
    upload_token=upload.upload_token,
    params=JobCreateParams(language="en", transcription_model="premium"),
)

create_target returns a BrowserUploadTarget with a pre-signed upload_url, required upload_headers, and an expiry (expires_in_seconds). Upload with upload_file / upload_bytes, or PUT the bytes yourself using the signed URL.

Analytics

Request generic and custom schema-bound analytics with JobCreateParams.analytics:

job = client.jobs.create_from_file(
    "insurance-call.mp3",
    params=JobCreateParams(
        language="en",
        analytics={
            "profile": "full",
            "domain": "insurance",
            "schema": {
                "fields": [
                    {
                        "key": "call_reason",
                        "label": "Reason for call",
                        "type": "single_select",
                        "options": [
                            {"id": 1, "code": "CLAIM_STATUS", "label": "Claim status"},
                            {"id": 2, "code": "BILLING", "label": "Billing question"},
                        ],
                    }
                ]
            },
        },
    ),
)

final_job = client.jobs.wait(job.id)
if final_job.analytics:
    print(final_job.analytics["custom"]["fields"])

See tuplets.ai/docs for supported profiles, domains, and schema field types.

Async usage

The async client mirrors the sync API:

from tuplets_ai import AsyncTupletsClient, JobCreateParams

async def main() -> None:
    async with AsyncTupletsClient(api_key="tb_your_api_key") as client:
        job = await client.jobs.create_from_url(
            "https://storage.example.com/call.mp3",
            params=JobCreateParams(language="en", pii_processing=True),
        )
        final_job = await client.jobs.wait(job.id)
        if final_job.status == "completed":
            transcript = await client.jobs.download_result(job.id)
            print(transcript["text"])
        elif final_job.status == "failed":
            print(final_job.error_message)

Error handling

API failures raise typed exceptions with status_code and optional response_body:

Exception HTTP status
ValidationError 400
AuthenticationError 401
PaymentRequiredError 402
PermissionDeniedError 403
NotFoundError 404
ConflictError 409
GoneError 410
RateLimitError 429
APIStatusError other 4xx/5xx
WaitTimeoutError polling timeout (not an HTTP error)
from tuplets_ai import AuthenticationError, RateLimitError, TupletsClient

client = TupletsClient(api_key="tb_your_api_key")

try:
    client.jobs.get("job_unknown")
except AuthenticationError as exc:
    print(exc.status_code, exc.message)
except RateLimitError:
    ...

API surface

Resource Methods
client.jobs create_from_file, create_from_bytes, create_from_url, create_from_uploaded_audio, get, list, wait, cancel, cancel_with_token, download_result
client.uploads create_target, upload_file, upload_bytes
client.solutions create_inquiry (public enterprise inquiries; no API key required)

Exported types

JobCreateParams, JobAccepted, JobStatus, JobList, BrowserUploadTarget, UploadedAudioReference, SolutionsInquiryRequest, SolutionsInquirySubmission, and the exception classes above are exported from the top-level tuplets_ai package.

Support

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tuplets_ai-0.3.2.tar.gz (10.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tuplets_ai-0.3.2-py3-none-any.whl (13.5 kB view details)

Uploaded Python 3

File details

Details for the file tuplets_ai-0.3.2.tar.gz.

File metadata

  • Download URL: tuplets_ai-0.3.2.tar.gz
  • Upload date:
  • Size: 10.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for tuplets_ai-0.3.2.tar.gz
Algorithm Hash digest
SHA256 6a01efb18d910010bb0946b674a4b00d26a0d19007ee30f9fd6e7947ae29a321
MD5 73d3d5721e2d3082dae4c9642213ca38
BLAKE2b-256 7d05d8eefec8417ecc9db36d51adf1b8193413e062c78dcdc4b8441f52c23bce

See more details on using hashes here.

File details

Details for the file tuplets_ai-0.3.2-py3-none-any.whl.

File metadata

  • Download URL: tuplets_ai-0.3.2-py3-none-any.whl
  • Upload date:
  • Size: 13.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for tuplets_ai-0.3.2-py3-none-any.whl
Algorithm Hash digest
SHA256 0448c1a8944ccc672c56e5cbbed7611339953040d6fffd030e23d9c5ec2a8640
MD5 bd255d8a772a6a86432fc18299608a1d
BLAKE2b-256 315aca3c92657a5d2dec5fb878b4334555093b813802af7d79fd8c9d02d9d176

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page