> ## Documentation Index
> Fetch the complete documentation index at: https://docs.supertoneapi.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 비용과 사용량

> 크레딧 비용을 예측하고, 잔액을 확인하며, 보이스나 시간 구간별로 사용량을 모니터링하고, 이상 알림을 설정하는 방법을 안내합니다.

<Note>
  이 문서는 영어 원문을 기반으로 자동 번역되었습니다. 표현이 어색하거나 모호한 부분이 있을 수 있으니, 정확한 내용은 [영어 원문](/en/docs/production/cost-and-usage)을 함께 확인해 주세요.
</Note>

Supertone API는 [Supertone Play](https://play.supertone.ai)와 공유되는 **크레딧 기반** 과금 모델을 사용합니다. 이 페이지에서는 크레딧이 어떻게 동작하는지, 생성 전에 비용을 어떻게 예측하는지, 그리고 옵저버빌리티 스택에 통합해야 할 엔드포인트가 무엇인지 다룹니다.

## 크레딧 동작 방식

* 크레딧은 생성된 오디오의 **초 단위**로 차감됩니다.
* 크레딧은 **Supertone Play와 공유됩니다** — 동일한 잔액이 양쪽에 적용됩니다. Play에서 차감된 크레딧은 즉시 API에 반영되며, 그 반대도 마찬가지입니다.
* 프리셋 보이스와 커스텀 보이스 모두 동일한 잔액에서 차감됩니다.
* **`predict_duration`은 무료입니다.** 크레딧이 차감되지 않으므로, 비용 미리보기와 사전 점검에 활용하세요.

요금제는 [Play 구독 페이지](https://play.supertone.ai/subscription)에서 확인할 수 있습니다. 더 높은 한도와 전용 처리 용량이 필요하다면 [엔터프라이즈 플랜](https://docs.google.com/forms/d/1YexQpjpK0ZEou12blTytkZLqvrV-Uv95GbhxoOQ54R8/edit)을 참고해 주세요.

## 통합해야 할 엔드포인트

| 엔드포인트                                  | 용도                                                                  |
| -------------------------------------- | ------------------------------------------------------------------- |
| `POST /v1/predict-duration/{voice_id}` | 생성 전에 오디오 길이(및 그에 따른 크레딧 비용)를 예측합니다.                                |
| `GET /v1/credits`                      | 현재 크레딧 잔액 — 낮을 때 알림을 보내세요.                                          |
| `GET /v1/voice-usage`                  | 일자별 보이스/스타일/언어/모델별 생성 시간(최대 30일).                                   |
| `GET /v1/usage`                        | `voice_id`, `voice_name`, `api_key`, `model`별 분해가 가능한 구간 분석 데이터입니다. |

## Predict duration

`predict_duration`은 주어진 텍스트에 대해 오디오를 생성하지 않고 **예상 길이**를 반환합니다. 다음과 같은 용도로 사용하세요.

* 생성 전에 "약 12초 소요됩니다" 같은 추정치를 사용자에게 표시.
* 크레딧 비용 예측(이 엔드포인트는 크레딧을 차감하지 않습니다).
* 문장이 UI 슬롯이나 예산에 맞는지 판단.

<Note>
  `predict_duration`은 **자동 청크 분할을 하지 않습니다** — 동일하게 300자 제한이 적용됩니다. 더 긴 스크립트는 직접 분할한 뒤 예측된 길이를 합산하세요.
</Note>

<Tabs>
  <Tab title="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")
    ```
  </Tab>

  <Tab title="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`);
    ```
  </Tab>

  <Tab title="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 }
    ```
  </Tab>
</Tabs>

요청 본문의 형태는 [Create speech](/ko/docs/text-to-speech/create-speech)와 동일합니다 — `text`, `language`, `style`, `model`, `voice_settings` — 단, `output_format`, `include_phonemes`, `normalized_text`는 제외됩니다(이들은 예측 길이에 영향을 주지 않습니다).

**정확한 예측을 위한 팁:**

* **속도(speed)는 결과를 바꿉니다.** `voice_settings.speed`는 길이를 배수로 변경합니다. 미리보기와 실제 생성에서 다른 속도를 사용하면 실제 길이가 달라집니다. 두 호출에서 동일한 speed를 사용하세요.
* **모델을 일치시키세요.** `predict_duration`은 `create_speech`와 동일한 `model` 필드를 받습니다. 특정 모델로 생성할 예정이라면 동일 모델로 예측하세요.

**배치 작업**의 사전 점검이나 **사용자별 예산** 관리를 위해서는, 먼저 `predict_duration`을 호출해 길이를 합산한 뒤 진행 여부를 결정하세요.

## 일일 잔액 점검

잔액이 임계값 이하로 떨어지면 모니터링 도구에 알림을 보내는 간단한 cron 작업만 있어도, `402 Payment Required`로 인한 장애 발생 며칠 전에 미리 경고를 받을 수 있습니다.

<Tabs>
  <Tab title="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}"
            )
    ```
  </Tab>

  <Tab title="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)}`);
    }
    ```
  </Tab>

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

실시간 잔액은 콘솔 대시보드 또는 Play 구독 페이지에서도 확인할 수 있습니다.

## 주간 보이스별 리포트

어느 보이스가 비용을 가장 많이 발생시키는지 파악하거나, 폭주하는 연동을 찾아낼 때 유용합니다. 최대 조회 기간은 30일이며, 날짜 기준은 UTC+0입니다.

<Tabs>
  <Tab title="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")
    ```
  </Tab>

  <Tab title="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`);
    }
    ```
  </Tab>

  <Tab title="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"
    ```
  </Tab>
</Tabs>

## 대시보드용 구간 분석

`GET /v1/usage`는 시간 단위 또는 일 단위 구간과 다양한 분해 옵션을 지원합니다. 대시보드 패널을 채우거나, 메트릭 백엔드로 행을 전송할 때 사용하세요.

<Tabs>
  <Tab title="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,
            })
    ```
  </Tab>

  <Tab title="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,
      });
    }
    ```
  </Tab>
</Tabs>

제약 사항:

* 동일한 `breakdown_type`에 `voice_id`와 `voice_name`을 함께 지정할 수 없습니다.
* `start_time`과 `end_time`의 UTC 오프셋이 서로 다른 경우, API는 `end_time`의 오프셋을 무시합니다.
* 페이지 크기는 1\~20이며, `next_page_token`으로 페이지네이션합니다.

## 이상 알림

비용 대비 효율이 좋은 두 가지 알림은 다음과 같습니다.

1. **사용량 급증** — 오늘의 생성 분(minutes-generated)을 최근 7일 중앙값과 비교합니다. 예를 들어 중앙값의 3배를 초과하면 알림을 보냅니다.
2. **프로덕션에 새로운 보이스 등장** — `get_voice_usage` 결과에서 예상한 보이스 집합에 없는 보이스가 나타나면 플래그합니다. 프로덕션 코드에 실수로 하드코딩된 테스트 보이스를 잡아낼 수 있습니다.

## 사용자별 사용량 귀속

Supertone API는 최종 사용자 식별 정보를 직접 추적하지 않습니다 — 이는 백엔드의 책임입니다. 일반적인 패턴은 다음과 같습니다.

1. 백엔드에서 각 TTS 호출을 `user_id`, `voice_id`, 예측/실제 길이, 타임스탬프와 함께 기록합니다.
2. 내부에서 빌링 또는 어뷰즈 방지 용도로 집계합니다.
3. 주기적으로 `get_voice_usage`와 대조하여, 자체 기록이 Supertone의 집계와 일치하는지 확인합니다.

## 관련 문서

<CardGroup cols={2}>
  <Card title="Create speech" icon="comment" href="/ko/docs/text-to-speech/create-speech">
    비용을 예측한 뒤 오디오를 생성하세요.
  </Card>

  <Card title="요청 수 제한" icon="gauge" href="/ko/docs/production/rate-limits">
    티어별 분당 요청 제한을 확인하세요.
  </Card>
</CardGroup>
