Overview

Poll the status of an asynchronous text-to-speech (TTS) job. Use the runId and model values returned by POST /api/tts when the initial response is 202 with status: "pending".

Query parameters

  • runId (string, required): Job identifier from the submit response
  • model (string, required): The model that was used for the job (e.g., Elevenlabs-Turbo-V2.5)
  • cost (number, optional): Cost from the ticket; helps with automatic refunds
  • paymentSource (string, optional): Currency/source from the ticket (e.g., USD)
  • isApiRequest (boolean, optional): Pass true when polling from API clients
Including cost, paymentSource, and isApiRequest from the original ticket helps the platform perform automatic refunds if the upstream provider rejects content after you were charged.

Usage

import time
import requests

BASE = "https://nano-gpt.com/api"

def get_tts_status(run_id: str, model: str, api_key: str, *, cost=None, payment_source=None, is_api_request=True) -> dict:
    params = {"runId": run_id, "model": model}
    if isinstance(cost, (int, float)):
        params["cost"] = str(cost)
    if payment_source:
        params["paymentSource"] = str(payment_source)
    if isinstance(is_api_request, bool):
        params["isApiRequest"] = str(is_api_request)

    resp = requests.get(
        f"{BASE}/tts/status",
        headers={"x-api-key": api_key},
        params=params,
        timeout=30,
    )
    resp.raise_for_status()
    return resp.json()


def wait_for_tts(run_id: str, model: str, api_key: str, *, cost=None, payment_source=None, is_api_request=True, max_attempts: int = 60, delay_s: int = 3) -> str:
    for attempt in range(max_attempts):
        data = get_tts_status(run_id, model, api_key, cost=cost, payment_source=payment_source, is_api_request=is_api_request)
        status = data.get("status")

        if status == "completed" and data.get("audioUrl"):
            return data["audioUrl"]
        if status == "error":
            raise RuntimeError(data.get("error", "TTS generation failed"))

        time.sleep(delay_s)

    raise TimeoutError("Polling timeout")

Response examples

Pending

{
  "status": "pending",
  "runId": "98b0d593-fe8d-49b8-89c9-233022232297",
  "queuePosition": 3
}

Completed

{
  "status": "completed",
  "audioUrl": "https://.../file.mp3",
  "contentType": "audio/mpeg",
  "model": "Elevenlabs-Turbo-V2.5"
}

Error (generic)

{
  "status": "error",
  "error": "TTS generation failed. Please try again."
}

Error (content policy)

{
  "status": "error",
  "code": "CONTENT_POLICY_VIOLATION",
  "error": "Content rejected by provider. Please modify your prompt and try again."
}

Notes

  • For Elevenlabs‑family async models (e.g., Elevenlabs-Turbo-V2.5, Elevenlabs-V3) you will always poll this endpoint until it returns completed.
  • When the job completes, the response includes an audioUrl you can download or play in the browser.
  • If available, include cost, paymentSource, and isApiRequest from the original ticket while polling to improve refund handling.