> ## Documentation Index
> Fetch the complete documentation index at: https://supertone-b89202c8.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Cost and usage

> Forecast credit cost, check your balance, monitor usage by voice or time bucket, and set up anomaly alerts.

The Supertone API uses a **credit-based** billing model that is shared with [Supertone Play](https://play.supertone.ai). This page covers how credits work, how to forecast cost before generating, and the endpoints you should integrate into your observability stack.

## How credits work

* Credits are deducted **per second** of generated audio.
* Credits are **shared with Supertone Play** — the same balance applies to both. Credits charged in Play are immediately available to the API and vice versa.
* Both preset voices and custom voices deduct from the same balance.
* **`predict_duration` is free.** No credits are deducted — use it for cost preview and pre-flighting.

Pricing tiers are listed on the [Play subscription page](https://play.supertone.ai/subscription). For higher limits and dedicated capacity, see [enterprise plans](https://docs.google.com/forms/d/1YexQpjpK0ZEou12blTytkZLqvrV-Uv95GbhxoOQ54R8/edit).

## Endpoints you should integrate

| Endpoint | Purpose |
| - | - |
| `POST /v1/predict-duration/{voice_id}` | Forecast audio length (and therefore credit cost) before generating. |
| `GET /v1/credits` | Current credit balance — alert when it's low. |
| `GET /v1/voice-usage` | Minutes generated per voice / style / language / model, by day (max 30 days). |
| `GET /v1/usage` | Bucketed analytics with breakdowns by `voice_id`, `voice_name`, `api_key`, or `model`. |

## Predict duration

`predict_duration` returns the **expected length** of generated speech for a given text, without producing audio. Use it to:

* Show users a "this will take \~12 seconds" estimate before generation.
* Forecast credit cost (no credits are deducted by this endpoint).
* Decide whether a sentence fits a UI slot or budget.

> [!NOTE]
>
> `predict_duration` does **not** auto-chunk — the same 300-character limit applies. For longer scripts, split yourself and sum the predicted durations.

**Python**

```python theme={"dark"}
import os
from supertone import Supertone

VOICE_ID = "20160a4c5ba38967330c84"  # replace with your voice ID

with Supertone(api_key=os.environ["SUPERTONE_API_KEY"]) as client:
    response = client.text_to_speech.predict_duration(
        voice_id=VOICE_ID,
        text="This is a sentence to estimate.",
        language="en",
    )

print(f"Estimated duration: {response.duration:.2f}s")
```

**TypeScript**

```typescript theme={"dark"}
import { Supertone } from "@supertone/supertone";

const VOICE_ID = "20160a4c5ba38967330c84"; // replace with your voice ID

const client = new Supertone({ apiKey: process.env.SUPERTONE_API_KEY });

const response = await client.textToSpeech.predictDuration({
  voiceId: VOICE_ID,
  predictTTSDurationRequest: {
    text: "This is a sentence to estimate.",
    language: "en",
  },
});

console.log(`Estimated duration: ${response.duration?.toFixed(2)}s`);
```

**cURL**

```bash theme={"dark"}
VOICE_ID="20160a4c5ba38967330c84"

curl -X POST "https://supertoneapi.com/v1/predict-duration/$VOICE_ID" \
  -H "x-sup-api-key: $SUPERTONE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "This is a sentence to estimate.",
    "language": "en"
  }'
```

Response:

```json theme={"dark"}
{ "duration": 2.18 }
```

The request body is the same shape as [Create speech](/en/docs/text-to-speech/create-speech) — `text`, `language`, `style`, `model`, `voice_settings` — minus `output_format`, `include_phonemes`, and `normalized_text` (none of which affect the predicted length).

**Tips for accurate forecasts:**

* **Speed changes the result.** `voice_settings.speed` multiplies the duration. If you preview at one speed and generate at another, the actual length will differ. Use the same speed in both calls.
* **Match the model.** `predict_duration` accepts the same `model` field as `create_speech`. If your generation will use a specific model, predict against it.

For pre-flighting **batch jobs** or **per-user budgets**, call `predict_duration` first and sum the durations to decide whether to proceed.

## Daily balance check

A simple cron job that posts to your monitoring tool when the balance drops below a threshold gives you days of warning before a `402 Payment Required` outage.

**Python**

```python theme={"dark"}
import os
from supertone import Supertone

LOW_THRESHOLD_USD = 50.0

with Supertone(api_key=os.environ["SUPERTONE_API_KEY"]) as client:
    balance = client.usage.get_credit_balance()
    if balance.credit_balance < LOW_THRESHOLD_USD:
        notify_oncall(
            f"Supertone credit balance low: ${balance.credit_balance:.2f}"
        )
```

**TypeScript**

```typescript theme={"dark"}
import { Supertone } from "@supertone/supertone";

const LOW_THRESHOLD = 50;

const client = new Supertone({ apiKey: process.env.SUPERTONE_API_KEY });
const { creditBalance } = await client.usage.getCreditBalance();

if (creditBalance !== undefined && creditBalance < LOW_THRESHOLD) {
  await notifyOncall(`Supertone credit balance low: $${creditBalance.toFixed(2)}`);
}
```

**cURL**

```bash theme={"dark"}
curl https://supertoneapi.com/v1/credits \
  -H "x-sup-api-key: $SUPERTONE_API_KEY"
```

You can also view the live balance in the console dashboard or the Play subscription page.

## Weekly per-voice report

Useful when you want to know which voices drive the most cost, or to flag a runaway integration. Maximum query window is 30 days; dates are UTC+0.

**Python**

```python theme={"dark"}
from supertone import Supertone

with Supertone(api_key=API_KEY) as client:
    usage = client.usage.get_voice_usage(
        start_date="2025-05-01",
        end_date="2025-05-31",
    )

    by_voice = {}
    for row in usage.usages or []:
        by_voice[row.name] = by_voice.get(row.name, 0) + row.total_minutes_used

    for name, minutes in sorted(by_voice.items(), key=lambda x: -x[1]):
        print(f"{name:30s} {minutes:>8.2f} min")
```

**TypeScript**

```typescript theme={"dark"}
const usage = await client.usage.getVoiceUsage({
  startDate: "2025-05-01",
  endDate: "2025-05-31",
});

const byVoice = new Map<string, number>();
for (const row of usage.usages ?? []) {
  byVoice.set(row.name, (byVoice.get(row.name) ?? 0) + row.totalMinutesUsed);
}

for (const [name, minutes] of [...byVoice.entries()].sort((a, b) => b[1] - a[1])) {
  console.log(`${name.padEnd(30)} ${minutes.toFixed(2)} min`);
}
```

**cURL**

```bash theme={"dark"}
curl "https://supertoneapi.com/v1/voice-usage?start_date=2025-05-01&end_date=2025-05-31" \
  -H "x-sup-api-key: $SUPERTONE_API_KEY"
```

## Bucketed analytics for dashboards

`GET /v1/usage` supports hourly or daily buckets with multiple breakdowns. Use it to populate a dashboard panel or send rows to your metrics backend.

**Python**

```python theme={"dark"}
from supertone import Supertone

with Supertone(api_key=API_KEY) as client:
    page = client.usage.get_usage(
        start_time="2025-05-01T00:00:00+00:00",
        end_time="2025-05-31T23:59:59+00:00",
        bucket_width="day",
        breakdown_type=["api_key", "model"],
        page_size=20,
    )

    for row in page.items or []:
        emit_metric("supertone.minutes_generated", value=row.total_minutes_used, tags={
            "api_key": row.api_key,
            "model": row.model,
            "bucket_start": row.bucket_start,
        })
```

**TypeScript**

```typescript theme={"dark"}
import { Supertone } from "@supertone/supertone";

const client = new Supertone({ apiKey: API_KEY });

const page = await client.usage.getUsage({
  startTime: "2025-05-01T00:00:00+00:00",
  endTime: "2025-05-31T23:59:59+00:00",
  bucketWidth: "day",
  breakdownType: ["api_key", "model"],
  pageSize: 20,
});

for (const row of page.items ?? []) {
  emitMetric("supertone.minutes_generated", row.totalMinutesUsed, {
    api_key: row.apiKey,
    model: row.model,
    bucket_start: row.bucketStart,
  });
}
```

Restrictions:

* You can't combine `voice_id` and `voice_name` in the same `breakdown_type`.
* If `start_time` and `end_time` have different UTC offsets, the API ignores `end_time`'s offset.
* Page size is 1–20; paginate via `next_page_token`.

## Anomaly alerts

Two cheap, useful alerts:

1. **Spend spike** — compare today's minutes-generated to the rolling 7-day median. Alert if today is more than (say) 3× the median.
2. **New voice in production** — if a voice not in your expected set appears in `get_voice_usage`, flag it. This catches accidental hard-coded test voices in production code.

## Per-user attribution

The Supertone API itself doesn't track end-user identities — your backend does. The pattern is:

1. Have your backend record each TTS call with `user_id`, `voice_id`, predicted/actual duration, timestamp.
2. Roll up internally for billing or anti-abuse.
3. Cross-check periodically against `get_voice_usage` to make sure your records align with Supertone's count.

## Related

> **[Create speech](/en/docs/text-to-speech/create-speech)**
>
> Generate audio once you've forecasted the cost.

> **[Rate limits](/en/docs/production/rate-limits)**
>
> Per-minute request limits by tier.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.