# 한국어 AI 내레이션 TTS



16가지 전문 내레이션 목소리와 타임라인이 맞는 ASS 자막을 함께 생성합니다.



인증: Authorization: Bearer $APICK_API_KEY

본문 있는 REST 요청: multipart/form-data. GET 본문 및 MCP JSON-RPC 규격은 해당 명세를 따릅니다.

인증키는 서버에 보관하세요. 모든 예제는 정적 자료입니다.



## POST /rest/tts/jobs 응답 필드

- `data` (object): 아래 하위 항목을 확인하세요.

- `data.job_id` (string): 접수 응답에서 받은 작업 ID. 같은 계정의 작업에만 접근할 수 있습니다.

- `data.status` (string): 접수 완료. 허용값: waiting

- `data.voice_id` (string): 선택한 목소리 ID.

- `data.character_count` (integer): 공백·문장부호를 포함한 합성 글자 수.

- `api` (object): 호출 메타데이터.

- `api.success` (boolean): API 공통 처리 여부. HTTP 상태·업무 결과와 함께 확인합니다.

- `api.cost` (number): 이번 호출에서 차감한 포인트. 무료 조회·재전송은 0.

- `api.pl_id` (integer): 과금 기록 ID. 과금 기록이 있을 때만 포함합니다.

## 작업 접수: POST /rest/tts/jobs



### 입력

- `voice_id` (string, 필수): 지원 voice_id 허용값: v2_ann_m_30s_01, v2_ann_m_30s_02, v2_ann_m_30s_04, v2_ann_m_30s_05, v2_ann_f_30s_01, v2_ann_f_30s_02, v2_ann_f_30s_03, v2_ann_f_30s_04, v2_ann_f_30s_05, v2_m_teen_01, v2_m_young_01, v2_m_mid_01, v2_m_senior_01, v2_f_teen_01, v2_f_young_01, v2_f_senior_01

- `text` (string, 조건부): 합성할 한국어 본문. text와 utterances 중 하나만 사용합니다. 전체 1~800자(공백·줄바꿈 포함).

- `utterances` (array, 선택): 발화 객체 배열(1~100개). 전체 text 합계 최대 800자. text와 동시 사용 불가

- `utterances[0][text]` (string, 조건부): 발화 본문. text와 utterances 중 하나만 사용합니다. 최대 100개 발화, 전체 본문 합계 800자입니다.

- `utterances[0][paragraph_id]` (string, 선택): 발화가 속한 문단 식별자입니다.

- `utterances[0][pause_after]` (string, 선택): 발화 뒤 쉼. none=없음, micro=짧은 쉼, normal=보통, strong=긴 쉼, paragraph=문단 경계. 생략하면 문맥에 맞춰 자동 지정합니다. 허용값: none, micro, normal, strong, paragraph

- `utterances[0][pause_before_ms]` (integer, 선택): 발화 앞 쉼의 길이. 밀리초 단위 정수 0~10000.



### 응답 명세

```json

{
  "type": "object",
  "description": "공개 JSON 응답.",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "job_id": {
          "type": "string",
          "description": "접수 응답에서 받은 작업 ID. 같은 계정의 작업에만 접근할 수 있습니다."
        },
        "status": {
          "type": "string",
          "description": "접수 완료.",
          "enum": [
            "waiting"
          ]
        },
        "voice_id": {
          "type": "string",
          "description": "선택한 목소리 ID."
        },
        "character_count": {
          "type": "integer",
          "description": "공백·문장부호를 포함한 합성 글자 수."
        }
      }
    },
    "api": {
      "type": "object",
      "description": "호출 메타데이터.",
      "properties": {
        "success": {
          "type": "boolean",
          "description": "API 공통 처리 여부. HTTP 상태·업무 결과와 함께 확인합니다."
        },
        "cost": {
          "type": "number",
          "description": "이번 호출에서 차감한 포인트. 무료 조회·재전송은 0."
        },
        "pl_id": {
          "type": "integer",
          "description": "과금 기록 ID. 과금 기록이 있을 때만 포함합니다."
        }
      }
    }
  }
}

```

### 정적 응답 예시

```json

{
  "data": {
    "job_id": "7f7e43f578cd459db04696416435c789",
    "status": "waiting",
    "voice_id": "v2_ann_m_30s_01",
    "character_count": 27
  },
  "api": {
    "success": true,
    "cost": 10,
    "pl_id": 12345
  }
}

```

### curl

```curl

curl --fail-with-body --request POST 'https://apick.app/rest/tts/jobs' \
  --header "Authorization: Bearer $APICK_API_KEY" \
  --form-string 'voice_id=v2_ann_m_30s_01' \
  --form-string 'text=오늘 들려드릴 이야기는 한 사람의 선택에서 시작됩니다.'

```

### Node.js (서버 ESM)

```javascript

const form = new FormData();
form.append("voice_id", "v2_ann_m_30s_01");
form.append("text", "오늘 들려드릴 이야기는 한 사람의 선택에서 시작됩니다.");
const response = await fetch("https://apick.app/rest/tts/jobs", {
  method: "POST",
  headers: { Authorization: "Bearer " + process.env.APICK_API_KEY },
  body: form,
  signal: AbortSignal.timeout(120_000),
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
const result = await response.json();
console.log(result);

```

### python

```python

import os
import requests
parts = [
    ("voice_id", (None, "v2_ann_m_30s_01")),
    ("text", (None, "오늘 들려드릴 이야기는 한 사람의 선택에서 시작됩니다.")),
]
response = requests.request("POST", "https://apick.app/rest/tts/jobs",
    headers={"Authorization": "Bearer " + os.environ["APICK_API_KEY"]},
    files=parts,
    timeout=(10, 120))
response.raise_for_status()
result = response.json()
print(result)

```

### php

```php

<?php
$headers = ["Authorization: Bearer " . getenv("APICK_API_KEY")];
$form = [
    'voice_id' => 'v2_ann_m_30s_01',
    'text' => '오늘 들려드릴 이야기는 한 사람의 선택에서 시작됩니다.',
];
$curl = curl_init('https://apick.app/rest/tts/jobs');
curl_setopt_array($curl, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_POSTFIELDS => $form,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_TIMEOUT => 120,
]);
$body = curl_exec($curl);
if ($body === false) { throw new RuntimeException(curl_error($curl)); }
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
if ($status >= 400) { throw new RuntimeException($body); }
$result = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
print_r($result);

```

## GET /rest/tts/jobs/:job_id 응답 필드

- `data` (object): 아래 하위 항목을 확인하세요.

- `data.job_id` (string): 접수 응답에서 받은 작업 ID. 같은 계정의 작업에만 접근할 수 있습니다.

- `data.status` (string): 작업 진행 상태. 완료 여부와 다운로드 가능 여부를 함께 확인합니다. 허용값: waiting, processing, completed, cancelled, failed

- `data.result_available` (boolean): 최종 MP3를 내려받을 수 있는지 여부.

- `data.subtitles_available` (boolean): 자막을 내려받을 수 있는지 여부.

- `data.resume_revision` (integer): 재시도 회차. 0은 최초 생성이며 재시도할 때 증가합니다.

- `data.quality` (object): 품질 상세. 아직 검사 전이면 null이거나 생략됩니다. null 허용.

- `data.quality.schema_version` (string): 품질 결과 규격 버전.

- `data.quality.attempt` (integer): 현재 검사 시도 회차.

- `data.quality.phase` (string): 현재 처리 단계.

- `data.quality.accepted_utterances` (integer): 통과 발화 수.

- `data.quality.failed_utterances` (integer): 실패 발화 수.

- `data.quality.total_utterances` (integer): 전체 발화 수.

- `data.quality.expires_at` (string): 후보 결과 보관 만료 일시. null 허용.

- `data.quality.queue_elapsed_sec` (number): 대기 시간(초).

- `data.quality.generation_elapsed_sec` (number): 생성 시간(초).

- `data.quality.utterances` (array): 발화별 검사 결과.

- `data.quality.utterances[].id` (string): 발화 식별자.

- `data.quality.utterances[].utterance_id` (string): 발화 식별자. 예: u001.

- `data.quality.utterances[].candidate_id` (string): 음성 후보 식별자.

- `data.quality.utterances[].status` (string): 항목 처리 또는 검사 상태.

- `data.quality.utterances[].attempt` (integer): 생성 시도 회차.

- `data.quality.utterances[].voice_id` (string): 요청한 공개 목소리 ID.

- `data.quality.utterances[].created_at` (string): 항목 생성 일시.

- `data.quality.utterances[].elapsed_sec` (number): 처리 경과 시간(초).

- `data.quality.utterances[].reasons` (array): 검사·실패 사유 목록. 사유가 없으면 빈 배열입니다.

- `data.quality.utterances[].speech_rate` (object): 발화 속도 검사. 검사 단계에 따라 일부 필드는 생략됩니다.

- `data.quality.utterances[].speech_rate.characters` (integer): 발화 글자 수.

- `data.quality.utterances[].speech_rate.chars` (integer): 발화 글자 수.

- `data.quality.utterances[].speech_rate.duration_sec` (number): 측정 음성 길이(초).

- `data.quality.utterances[].speech_rate.duration_ms` (number): 측정 음성 길이(밀리초).

- `data.quality.utterances[].speech_rate.cps` (number): 초당 발화 글자 수.

- `data.quality.utterances[].speech_rate.expected_sec` (number): 예상 발화 길이(초).

- `data.quality.utterances[].speech_rate.expected_duration_ms` (number): 예상 발화 길이(밀리초).

- `data.quality.utterances[].speech_rate.duration_ratio` (number): 실제 길이/예상 길이 비율. 계산할 수 없으면 null. null 허용.

- `data.quality.utterances[].speech_rate.min_cps` (number): 최소 허용 초당 글자 수.

- `data.quality.utterances[].speech_rate.minimum_characters` (integer): 검사에 필요한 최소 글자 수.

- `data.quality.utterances[].speech_rate.status` (string): 속도 검사 결과.

- `data.quality.utterances[].audio_sha256` (string): 후보 음원 SHA-256. 동일 음원 확인에 사용합니다.

- `data.quality.utterances[].audio_duration_ms` (number): 음원 길이(밀리초).

- `data.quality.utterances[].audio_available` (boolean): 후보 음원 다운로드 가능 여부.

- `data.quality.utterances[].transcript` (string): 음원에서 인식한 텍스트.

- `data.quality.utterances[].cer` (number): 문자 오류율. 낮을수록 원문과 가깝습니다.

- `data.quality.utterances[].coverage` (number): 원문에 대한 음성의 포함률.

- `data.quality.utterances[].repeat` (object): 검출 결과. 분석할 수 없는 항목은 생략되거나 null입니다.

- `data.quality.utterances[].repeat.detected` (boolean): 해당 현상이 검출됐는지 여부.

- `data.quality.utterances[].repeat.suspected` (boolean): 추가 확인이 필요한지 여부.

- `data.quality.utterances[].repeat.correlation` (number): 비교 구간의 상관도.

- `data.quality.utterances[].repeat.best_lag_sec` (number): 가장 잘 일치한 시간 차(초).

- `data.quality.utterances[].repeat.window_start_sec` (number): 검사 구간 시작(초).

- `data.quality.utterances[].repeat.window_end_sec` (number): 검사 구간 끝(초).

- `data.quality.utterances[].repeat.matched_characters` (integer): 일치한 글자 수.

- `data.quality.utterances[].repeat.matched_chars` (integer): 일치한 글자 수.

- `data.quality.utterances[].reference_intrusion` (object): 검출 결과. 분석할 수 없는 항목은 생략되거나 null입니다.

- `data.quality.utterances[].reference_intrusion.detected` (boolean): 해당 현상이 검출됐는지 여부.

- `data.quality.utterances[].reference_intrusion.suspected` (boolean): 추가 확인이 필요한지 여부.

- `data.quality.utterances[].reference_intrusion.correlation` (number): 비교 구간의 상관도.

- `data.quality.utterances[].reference_intrusion.best_lag_sec` (number): 가장 잘 일치한 시간 차(초).

- `data.quality.utterances[].reference_intrusion.window_start_sec` (number): 검사 구간 시작(초).

- `data.quality.utterances[].reference_intrusion.window_end_sec` (number): 검사 구간 끝(초).

- `data.quality.utterances[].reference_intrusion.matched_characters` (integer): 일치한 글자 수.

- `data.quality.utterances[].reference_intrusion.matched_chars` (integer): 일치한 글자 수.

- `data.quality.utterances[].text_qa_status` (string): 텍스트 검사 상태.

- `data.quality.utterances[].active_start_ms` (number): 유효 음성 구간 시작(밀리초).

- `data.quality.utterances[].active_end_ms` (number): 유효 음성 구간 끝(밀리초).

- `data.quality.utterances[].tail_guard_attached` (boolean): 끝부분 확인용 보호 구간 부착 여부.

- `data.quality.utterances[].tail_verified` (boolean): 끝부분 검증 완료 여부.

- `data.quality.utterances[].tail_verified_at_ms` (number): 끝부분을 검증한 시각(밀리초). 검증 전에는 null. null 허용.

- `data.quality.utterances[].tail_body_end_at_ms` (number): 본문 끝 위치(밀리초). null 허용.

- `data.quality.utterances[].tail_guard_attached_chunk_ids` (array): 보호 구간이 붙은 음성 구간 ID 목록.

- `data.quality.utterances[].generation_budget_exhausted` (boolean): 해당 발화의 자동 생성 시도 한도 소진 여부.

- `data.quality.utterances[].retry_requires_new_regeneration_key` (boolean): 새 재생성 키가 필요한 상태인지 여부.

- `data.quality.utterances[].candidate_revision` (integer): 재시도 회차. 0은 최초 생성이며 재시도할 때 증가합니다.

- `data.quality.candidates` (array): 음원 후보별 검사 결과.

- `data.quality.candidates[].id` (string): 발화 식별자.

- `data.quality.candidates[].utterance_id` (string): 발화 식별자. 예: u001.

- `data.quality.candidates[].candidate_id` (string): 음성 후보 식별자.

- `data.quality.candidates[].status` (string): 항목 처리 또는 검사 상태.

- `data.quality.candidates[].attempt` (integer): 생성 시도 회차.

- `data.quality.candidates[].voice_id` (string): 요청한 공개 목소리 ID.

- `data.quality.candidates[].created_at` (string): 항목 생성 일시.

- `data.quality.candidates[].elapsed_sec` (number): 처리 경과 시간(초).

- `data.quality.candidates[].reasons` (array): 검사·실패 사유 목록. 사유가 없으면 빈 배열입니다.

- `data.quality.candidates[].speech_rate` (object): 발화 속도 검사. 검사 단계에 따라 일부 필드는 생략됩니다.

- `data.quality.candidates[].speech_rate.characters` (integer): 발화 글자 수.

- `data.quality.candidates[].speech_rate.chars` (integer): 발화 글자 수.

- `data.quality.candidates[].speech_rate.duration_sec` (number): 측정 음성 길이(초).

- `data.quality.candidates[].speech_rate.duration_ms` (number): 측정 음성 길이(밀리초).

- `data.quality.candidates[].speech_rate.cps` (number): 초당 발화 글자 수.

- `data.quality.candidates[].speech_rate.expected_sec` (number): 예상 발화 길이(초).

- `data.quality.candidates[].speech_rate.expected_duration_ms` (number): 예상 발화 길이(밀리초).

- `data.quality.candidates[].speech_rate.duration_ratio` (number): 실제 길이/예상 길이 비율. 계산할 수 없으면 null. null 허용.

- `data.quality.candidates[].speech_rate.min_cps` (number): 최소 허용 초당 글자 수.

- `data.quality.candidates[].speech_rate.minimum_characters` (integer): 검사에 필요한 최소 글자 수.

- `data.quality.candidates[].speech_rate.status` (string): 속도 검사 결과.

- `data.quality.candidates[].audio_sha256` (string): 후보 음원 SHA-256. 동일 음원 확인에 사용합니다.

- `data.quality.candidates[].audio_duration_ms` (number): 음원 길이(밀리초).

- `data.quality.candidates[].audio_available` (boolean): 후보 음원 다운로드 가능 여부.

- `data.quality.candidates[].transcript` (string): 음원에서 인식한 텍스트.

- `data.quality.candidates[].cer` (number): 문자 오류율. 낮을수록 원문과 가깝습니다.

- `data.quality.candidates[].coverage` (number): 원문에 대한 음성의 포함률.

- `data.quality.candidates[].repeat` (object): 검출 결과. 분석할 수 없는 항목은 생략되거나 null입니다.

- `data.quality.candidates[].repeat.detected` (boolean): 해당 현상이 검출됐는지 여부.

- `data.quality.candidates[].repeat.suspected` (boolean): 추가 확인이 필요한지 여부.

- `data.quality.candidates[].repeat.correlation` (number): 비교 구간의 상관도.

- `data.quality.candidates[].repeat.best_lag_sec` (number): 가장 잘 일치한 시간 차(초).

- `data.quality.candidates[].repeat.window_start_sec` (number): 검사 구간 시작(초).

- `data.quality.candidates[].repeat.window_end_sec` (number): 검사 구간 끝(초).

- `data.quality.candidates[].repeat.matched_characters` (integer): 일치한 글자 수.

- `data.quality.candidates[].repeat.matched_chars` (integer): 일치한 글자 수.

- `data.quality.candidates[].reference_intrusion` (object): 검출 결과. 분석할 수 없는 항목은 생략되거나 null입니다.

- `data.quality.candidates[].reference_intrusion.detected` (boolean): 해당 현상이 검출됐는지 여부.

- `data.quality.candidates[].reference_intrusion.suspected` (boolean): 추가 확인이 필요한지 여부.

- `data.quality.candidates[].reference_intrusion.correlation` (number): 비교 구간의 상관도.

- `data.quality.candidates[].reference_intrusion.best_lag_sec` (number): 가장 잘 일치한 시간 차(초).

- `data.quality.candidates[].reference_intrusion.window_start_sec` (number): 검사 구간 시작(초).

- `data.quality.candidates[].reference_intrusion.window_end_sec` (number): 검사 구간 끝(초).

- `data.quality.candidates[].reference_intrusion.matched_characters` (integer): 일치한 글자 수.

- `data.quality.candidates[].reference_intrusion.matched_chars` (integer): 일치한 글자 수.

- `data.quality.candidates[].text_qa_status` (string): 텍스트 검사 상태.

- `data.quality.candidates[].active_start_ms` (number): 유효 음성 구간 시작(밀리초).

- `data.quality.candidates[].active_end_ms` (number): 유효 음성 구간 끝(밀리초).

- `data.quality.candidates[].tail_guard_attached` (boolean): 끝부분 확인용 보호 구간 부착 여부.

- `data.quality.candidates[].tail_verified` (boolean): 끝부분 검증 완료 여부.

- `data.quality.candidates[].tail_verified_at_ms` (number): 끝부분을 검증한 시각(밀리초). 검증 전에는 null. null 허용.

- `data.quality.candidates[].tail_body_end_at_ms` (number): 본문 끝 위치(밀리초). null 허용.

- `data.quality.candidates[].tail_guard_attached_chunk_ids` (array): 보호 구간이 붙은 음성 구간 ID 목록.

- `data.quality.candidates[].generation_budget_exhausted` (boolean): 해당 발화의 자동 생성 시도 한도 소진 여부.

- `data.quality.candidates[].retry_requires_new_regeneration_key` (boolean): 새 재생성 키가 필요한 상태인지 여부.

- `data.quality.candidates[].candidate_revision` (integer): 재시도 회차. 0은 최초 생성이며 재시도할 때 증가합니다.

- `data.quality.final_quality` (object): 최종 결과 검사. 최종 검사 전에는 생략됩니다.

- `data.quality.final_quality.schema_version` (string): 품질 결과 규격 버전.

- `data.quality.final_quality.attempt` (integer): 현재 검사 시도 회차.

- `data.quality.final_quality.phase` (string): 현재 처리 단계.

- `data.quality.final_quality.accepted_utterances` (integer): 통과 발화 수.

- `data.quality.final_quality.failed_utterances` (integer): 실패 발화 수.

- `data.quality.final_quality.total_utterances` (integer): 전체 발화 수.

- `data.quality.final_quality.expires_at` (string): 후보 결과 보관 만료 일시. null 허용.

- `data.quality.final_quality.queue_elapsed_sec` (number): 대기 시간(초).

- `data.quality.final_quality.generation_elapsed_sec` (number): 생성 시간(초).

- `data.quality.final_quality.utterances` (array): 발화별 검사 결과.

- `data.quality.final_quality.utterances[].id` (string): 발화 식별자.

- `data.quality.final_quality.utterances[].utterance_id` (string): 발화 식별자. 예: u001.

- `data.quality.final_quality.utterances[].candidate_id` (string): 음성 후보 식별자.

- `data.quality.final_quality.utterances[].status` (string): 항목 처리 또는 검사 상태.

- `data.quality.final_quality.utterances[].attempt` (integer): 생성 시도 회차.

- `data.quality.final_quality.utterances[].voice_id` (string): 요청한 공개 목소리 ID.

- `data.quality.final_quality.utterances[].created_at` (string): 항목 생성 일시.

- `data.quality.final_quality.utterances[].elapsed_sec` (number): 처리 경과 시간(초).

- `data.quality.final_quality.utterances[].reasons` (array): 검사·실패 사유 목록. 사유가 없으면 빈 배열입니다.

- `data.quality.final_quality.utterances[].speech_rate` (object): 발화 속도 검사. 검사 단계에 따라 일부 필드는 생략됩니다.

- `data.quality.final_quality.utterances[].speech_rate.characters` (integer): 발화 글자 수.

- `data.quality.final_quality.utterances[].speech_rate.chars` (integer): 발화 글자 수.

- `data.quality.final_quality.utterances[].speech_rate.duration_sec` (number): 측정 음성 길이(초).

- `data.quality.final_quality.utterances[].speech_rate.duration_ms` (number): 측정 음성 길이(밀리초).

- `data.quality.final_quality.utterances[].speech_rate.cps` (number): 초당 발화 글자 수.

- `data.quality.final_quality.utterances[].speech_rate.expected_sec` (number): 예상 발화 길이(초).

- `data.quality.final_quality.utterances[].speech_rate.expected_duration_ms` (number): 예상 발화 길이(밀리초).

- `data.quality.final_quality.utterances[].speech_rate.duration_ratio` (number): 실제 길이/예상 길이 비율. 계산할 수 없으면 null. null 허용.

- `data.quality.final_quality.utterances[].speech_rate.min_cps` (number): 최소 허용 초당 글자 수.

- `data.quality.final_quality.utterances[].speech_rate.minimum_characters` (integer): 검사에 필요한 최소 글자 수.

- `data.quality.final_quality.utterances[].speech_rate.status` (string): 속도 검사 결과.

- `data.quality.final_quality.utterances[].audio_sha256` (string): 후보 음원 SHA-256. 동일 음원 확인에 사용합니다.

- `data.quality.final_quality.utterances[].audio_duration_ms` (number): 음원 길이(밀리초).

- `data.quality.final_quality.utterances[].audio_available` (boolean): 후보 음원 다운로드 가능 여부.

- `data.quality.final_quality.utterances[].transcript` (string): 음원에서 인식한 텍스트.

- `data.quality.final_quality.utterances[].cer` (number): 문자 오류율. 낮을수록 원문과 가깝습니다.

- `data.quality.final_quality.utterances[].coverage` (number): 원문에 대한 음성의 포함률.

- `data.quality.final_quality.utterances[].repeat` (object): 검출 결과. 분석할 수 없는 항목은 생략되거나 null입니다.

- `data.quality.final_quality.utterances[].repeat.detected` (boolean): 해당 현상이 검출됐는지 여부.

- `data.quality.final_quality.utterances[].repeat.suspected` (boolean): 추가 확인이 필요한지 여부.

- `data.quality.final_quality.utterances[].repeat.correlation` (number): 비교 구간의 상관도.

- `data.quality.final_quality.utterances[].repeat.best_lag_sec` (number): 가장 잘 일치한 시간 차(초).

- `data.quality.final_quality.utterances[].repeat.window_start_sec` (number): 검사 구간 시작(초).

- `data.quality.final_quality.utterances[].repeat.window_end_sec` (number): 검사 구간 끝(초).

- `data.quality.final_quality.utterances[].repeat.matched_characters` (integer): 일치한 글자 수.

- `data.quality.final_quality.utterances[].repeat.matched_chars` (integer): 일치한 글자 수.

- `data.quality.final_quality.utterances[].reference_intrusion` (object): 검출 결과. 분석할 수 없는 항목은 생략되거나 null입니다.

- `data.quality.final_quality.utterances[].reference_intrusion.detected` (boolean): 해당 현상이 검출됐는지 여부.

- `data.quality.final_quality.utterances[].reference_intrusion.suspected` (boolean): 추가 확인이 필요한지 여부.

- `data.quality.final_quality.utterances[].reference_intrusion.correlation` (number): 비교 구간의 상관도.

- `data.quality.final_quality.utterances[].reference_intrusion.best_lag_sec` (number): 가장 잘 일치한 시간 차(초).

- `data.quality.final_quality.utterances[].reference_intrusion.window_start_sec` (number): 검사 구간 시작(초).

- `data.quality.final_quality.utterances[].reference_intrusion.window_end_sec` (number): 검사 구간 끝(초).

- `data.quality.final_quality.utterances[].reference_intrusion.matched_characters` (integer): 일치한 글자 수.

- `data.quality.final_quality.utterances[].reference_intrusion.matched_chars` (integer): 일치한 글자 수.

- `data.quality.final_quality.utterances[].text_qa_status` (string): 텍스트 검사 상태.

- `data.quality.final_quality.utterances[].active_start_ms` (number): 유효 음성 구간 시작(밀리초).

- `data.quality.final_quality.utterances[].active_end_ms` (number): 유효 음성 구간 끝(밀리초).

- `data.quality.final_quality.utterances[].tail_guard_attached` (boolean): 끝부분 확인용 보호 구간 부착 여부.

- `data.quality.final_quality.utterances[].tail_verified` (boolean): 끝부분 검증 완료 여부.

- `data.quality.final_quality.utterances[].tail_verified_at_ms` (number): 끝부분을 검증한 시각(밀리초). 검증 전에는 null. null 허용.

- `data.quality.final_quality.utterances[].tail_body_end_at_ms` (number): 본문 끝 위치(밀리초). null 허용.

- `data.quality.final_quality.utterances[].tail_guard_attached_chunk_ids` (array): 보호 구간이 붙은 음성 구간 ID 목록.

- `data.quality.final_quality.utterances[].generation_budget_exhausted` (boolean): 해당 발화의 자동 생성 시도 한도 소진 여부.

- `data.quality.final_quality.utterances[].retry_requires_new_regeneration_key` (boolean): 새 재생성 키가 필요한 상태인지 여부.

- `data.quality.final_quality.utterances[].candidate_revision` (integer): 재시도 회차. 0은 최초 생성이며 재시도할 때 증가합니다.

- `data.quality.final_quality.candidates` (array): 음원 후보별 검사 결과.

- `data.quality.final_quality.candidates[].id` (string): 발화 식별자.

- `data.quality.final_quality.candidates[].utterance_id` (string): 발화 식별자. 예: u001.

- `data.quality.final_quality.candidates[].candidate_id` (string): 음성 후보 식별자.

- `data.quality.final_quality.candidates[].status` (string): 항목 처리 또는 검사 상태.

- `data.quality.final_quality.candidates[].attempt` (integer): 생성 시도 회차.

- `data.quality.final_quality.candidates[].voice_id` (string): 요청한 공개 목소리 ID.

- `data.quality.final_quality.candidates[].created_at` (string): 항목 생성 일시.

- `data.quality.final_quality.candidates[].elapsed_sec` (number): 처리 경과 시간(초).

- `data.quality.final_quality.candidates[].reasons` (array): 검사·실패 사유 목록. 사유가 없으면 빈 배열입니다.

- `data.quality.final_quality.candidates[].speech_rate` (object): 발화 속도 검사. 검사 단계에 따라 일부 필드는 생략됩니다.

- `data.quality.final_quality.candidates[].speech_rate.characters` (integer): 발화 글자 수.

- `data.quality.final_quality.candidates[].speech_rate.chars` (integer): 발화 글자 수.

- `data.quality.final_quality.candidates[].speech_rate.duration_sec` (number): 측정 음성 길이(초).

- `data.quality.final_quality.candidates[].speech_rate.duration_ms` (number): 측정 음성 길이(밀리초).

- `data.quality.final_quality.candidates[].speech_rate.cps` (number): 초당 발화 글자 수.

- `data.quality.final_quality.candidates[].speech_rate.expected_sec` (number): 예상 발화 길이(초).

- `data.quality.final_quality.candidates[].speech_rate.expected_duration_ms` (number): 예상 발화 길이(밀리초).

- `data.quality.final_quality.candidates[].speech_rate.duration_ratio` (number): 실제 길이/예상 길이 비율. 계산할 수 없으면 null. null 허용.

- `data.quality.final_quality.candidates[].speech_rate.min_cps` (number): 최소 허용 초당 글자 수.

- `data.quality.final_quality.candidates[].speech_rate.minimum_characters` (integer): 검사에 필요한 최소 글자 수.

- `data.quality.final_quality.candidates[].speech_rate.status` (string): 속도 검사 결과.

- `data.quality.final_quality.candidates[].audio_sha256` (string): 후보 음원 SHA-256. 동일 음원 확인에 사용합니다.

- `data.quality.final_quality.candidates[].audio_duration_ms` (number): 음원 길이(밀리초).

- `data.quality.final_quality.candidates[].audio_available` (boolean): 후보 음원 다운로드 가능 여부.

- `data.quality.final_quality.candidates[].transcript` (string): 음원에서 인식한 텍스트.

- `data.quality.final_quality.candidates[].cer` (number): 문자 오류율. 낮을수록 원문과 가깝습니다.

- `data.quality.final_quality.candidates[].coverage` (number): 원문에 대한 음성의 포함률.

- `data.quality.final_quality.candidates[].repeat` (object): 검출 결과. 분석할 수 없는 항목은 생략되거나 null입니다.

- `data.quality.final_quality.candidates[].repeat.detected` (boolean): 해당 현상이 검출됐는지 여부.

- `data.quality.final_quality.candidates[].repeat.suspected` (boolean): 추가 확인이 필요한지 여부.

- `data.quality.final_quality.candidates[].repeat.correlation` (number): 비교 구간의 상관도.

- `data.quality.final_quality.candidates[].repeat.best_lag_sec` (number): 가장 잘 일치한 시간 차(초).

- `data.quality.final_quality.candidates[].repeat.window_start_sec` (number): 검사 구간 시작(초).

- `data.quality.final_quality.candidates[].repeat.window_end_sec` (number): 검사 구간 끝(초).

- `data.quality.final_quality.candidates[].repeat.matched_characters` (integer): 일치한 글자 수.

- `data.quality.final_quality.candidates[].repeat.matched_chars` (integer): 일치한 글자 수.

- `data.quality.final_quality.candidates[].reference_intrusion` (object): 검출 결과. 분석할 수 없는 항목은 생략되거나 null입니다.

- `data.quality.final_quality.candidates[].reference_intrusion.detected` (boolean): 해당 현상이 검출됐는지 여부.

- `data.quality.final_quality.candidates[].reference_intrusion.suspected` (boolean): 추가 확인이 필요한지 여부.

- `data.quality.final_quality.candidates[].reference_intrusion.correlation` (number): 비교 구간의 상관도.

- `data.quality.final_quality.candidates[].reference_intrusion.best_lag_sec` (number): 가장 잘 일치한 시간 차(초).

- `data.quality.final_quality.candidates[].reference_intrusion.window_start_sec` (number): 검사 구간 시작(초).

- `data.quality.final_quality.candidates[].reference_intrusion.window_end_sec` (number): 검사 구간 끝(초).

- `data.quality.final_quality.candidates[].reference_intrusion.matched_characters` (integer): 일치한 글자 수.

- `data.quality.final_quality.candidates[].reference_intrusion.matched_chars` (integer): 일치한 글자 수.

- `data.quality.final_quality.candidates[].text_qa_status` (string): 텍스트 검사 상태.

- `data.quality.final_quality.candidates[].active_start_ms` (number): 유효 음성 구간 시작(밀리초).

- `data.quality.final_quality.candidates[].active_end_ms` (number): 유효 음성 구간 끝(밀리초).

- `data.quality.final_quality.candidates[].tail_guard_attached` (boolean): 끝부분 확인용 보호 구간 부착 여부.

- `data.quality.final_quality.candidates[].tail_verified` (boolean): 끝부분 검증 완료 여부.

- `data.quality.final_quality.candidates[].tail_verified_at_ms` (number): 끝부분을 검증한 시각(밀리초). 검증 전에는 null. null 허용.

- `data.quality.final_quality.candidates[].tail_body_end_at_ms` (number): 본문 끝 위치(밀리초). null 허용.

- `data.quality.final_quality.candidates[].tail_guard_attached_chunk_ids` (array): 보호 구간이 붙은 음성 구간 ID 목록.

- `data.quality.final_quality.candidates[].generation_budget_exhausted` (boolean): 해당 발화의 자동 생성 시도 한도 소진 여부.

- `data.quality.final_quality.candidates[].retry_requires_new_regeneration_key` (boolean): 새 재생성 키가 필요한 상태인지 여부.

- `data.quality.final_quality.candidates[].candidate_revision` (integer): 재시도 회차. 0은 최초 생성이며 재시도할 때 증가합니다.

- `data.quality.final_quality.status` (string): 최종 검사 상태.

- `data.quality.final_quality.audio_sha256` (string): 최종 음원 SHA-256.

- `data.error` (object): 실패 상태일 때 포함합니다.

- `data.error.code` (string): 실패한 작업의 공개 오류코드.

- `data.error.message` (string): 오류 설명.

- `api` (object): 호출 메타데이터.

- `api.success` (boolean): API 공통 처리 여부. HTTP 상태·업무 결과와 함께 확인합니다.

- `api.cost` (number): 이번 호출에서 차감한 포인트. 무료 조회·재전송은 0.

- `api.pl_id` (integer): 과금 기록 ID. 과금 기록이 있을 때만 포함합니다.

## 상태·목록 조회: GET /rest/tts/jobs/:job_id



### 입력



### 응답 명세

```json

{
  "type": "object",
  "description": "공개 JSON 응답.",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "job_id": {
          "type": "string",
          "description": "접수 응답에서 받은 작업 ID. 같은 계정의 작업에만 접근할 수 있습니다."
        },
        "status": {
          "type": "string",
          "description": "작업 진행 상태. 완료 여부와 다운로드 가능 여부를 함께 확인합니다.",
          "enum": [
            "waiting",
            "processing",
            "completed",
            "cancelled",
            "failed"
          ]
        },
        "result_available": {
          "type": "boolean",
          "description": "최종 MP3를 내려받을 수 있는지 여부."
        },
        "subtitles_available": {
          "type": "boolean",
          "description": "자막을 내려받을 수 있는지 여부."
        },
        "resume_revision": {
          "type": "integer",
          "description": "재시도 회차. 0은 최초 생성이며 재시도할 때 증가합니다.",
          "minimum": 0
        },
        "quality": {
          "type": "object",
          "description": "품질 상세. 아직 검사 전이면 null이거나 생략됩니다.",
          "properties": {
            "schema_version": {
              "type": "string",
              "description": "품질 결과 규격 버전."
            },
            "attempt": {
              "type": "integer",
              "description": "현재 검사 시도 회차."
            },
            "phase": {
              "type": "string",
              "description": "현재 처리 단계."
            },
            "accepted_utterances": {
              "type": "integer",
              "description": "통과 발화 수."
            },
            "failed_utterances": {
              "type": "integer",
              "description": "실패 발화 수."
            },
            "total_utterances": {
              "type": "integer",
              "description": "전체 발화 수."
            },
            "expires_at": {
              "type": "string",
              "description": "후보 결과 보관 만료 일시.",
              "nullable": true
            },
            "queue_elapsed_sec": {
              "type": "number",
              "description": "대기 시간(초)."
            },
            "generation_elapsed_sec": {
              "type": "number",
              "description": "생성 시간(초)."
            },
            "utterances": {
              "type": "array",
              "description": "발화별 검사 결과.",
              "items": {
                "type": "object",
                "description": "발화·음원 후보별 공개 검사 결과. 단계별로 제공되는 항목만 포함합니다.",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "발화 식별자."
                  },
                  "utterance_id": {
                    "type": "string",
                    "description": "발화 식별자. 예: u001."
                  },
                  "candidate_id": {
                    "type": "string",
                    "description": "음성 후보 식별자."
                  },
                  "status": {
                    "type": "string",
                    "description": "항목 처리 또는 검사 상태."
                  },
                  "attempt": {
                    "type": "integer",
                    "description": "생성 시도 회차."
                  },
                  "voice_id": {
                    "type": "string",
                    "description": "요청한 공개 목소리 ID."
                  },
                  "created_at": {
                    "type": "string",
                    "description": "항목 생성 일시."
                  },
                  "elapsed_sec": {
                    "type": "number",
                    "description": "처리 경과 시간(초)."
                  },
                  "reasons": {
                    "type": "array",
                    "description": "검사·실패 사유 목록. 사유가 없으면 빈 배열입니다.",
                    "items": {
                      "type": "string",
                      "description": "검사 결과 사유."
                    }
                  },
                  "speech_rate": {
                    "type": "object",
                    "description": "발화 속도 검사. 검사 단계에 따라 일부 필드는 생략됩니다.",
                    "properties": {
                      "characters": {
                        "type": "integer",
                        "description": "발화 글자 수."
                      },
                      "chars": {
                        "type": "integer",
                        "description": "발화 글자 수."
                      },
                      "duration_sec": {
                        "type": "number",
                        "description": "측정 음성 길이(초)."
                      },
                      "duration_ms": {
                        "type": "number",
                        "description": "측정 음성 길이(밀리초)."
                      },
                      "cps": {
                        "type": "number",
                        "description": "초당 발화 글자 수."
                      },
                      "expected_sec": {
                        "type": "number",
                        "description": "예상 발화 길이(초)."
                      },
                      "expected_duration_ms": {
                        "type": "number",
                        "description": "예상 발화 길이(밀리초)."
                      },
                      "duration_ratio": {
                        "type": "number",
                        "description": "실제 길이/예상 길이 비율. 계산할 수 없으면 null.",
                        "nullable": true
                      },
                      "min_cps": {
                        "type": "number",
                        "description": "최소 허용 초당 글자 수."
                      },
                      "minimum_characters": {
                        "type": "integer",
                        "description": "검사에 필요한 최소 글자 수."
                      },
                      "status": {
                        "type": "string",
                        "description": "속도 검사 결과."
                      }
                    }
                  },
                  "audio_sha256": {
                    "type": "string",
                    "description": "후보 음원 SHA-256. 동일 음원 확인에 사용합니다."
                  },
                  "audio_duration_ms": {
                    "type": "number",
                    "description": "음원 길이(밀리초)."
                  },
                  "audio_available": {
                    "type": "boolean",
                    "description": "후보 음원 다운로드 가능 여부."
                  },
                  "transcript": {
                    "type": "string",
                    "description": "음원에서 인식한 텍스트."
                  },
                  "cer": {
                    "type": "number",
                    "description": "문자 오류율. 낮을수록 원문과 가깝습니다."
                  },
                  "coverage": {
                    "type": "number",
                    "description": "원문에 대한 음성의 포함률."
                  },
                  "repeat": {
                    "type": "object",
                    "description": "검출 결과. 분석할 수 없는 항목은 생략되거나 null입니다.",
                    "properties": {
                      "detected": {
                        "type": "boolean",
                        "description": "해당 현상이 검출됐는지 여부."
                      },
                      "suspected": {
                        "type": "boolean",
                        "description": "추가 확인이 필요한지 여부."
                      },
                      "correlation": {
                        "type": "number",
                        "description": "비교 구간의 상관도."
                      },
                      "best_lag_sec": {
                        "type": "number",
                        "description": "가장 잘 일치한 시간 차(초)."
                      },
                      "window_start_sec": {
                        "type": "number",
                        "description": "검사 구간 시작(초)."
                      },
                      "window_end_sec": {
                        "type": "number",
                        "description": "검사 구간 끝(초)."
                      },
                      "matched_characters": {
                        "type": "integer",
                        "description": "일치한 글자 수."
                      },
                      "matched_chars": {
                        "type": "integer",
                        "description": "일치한 글자 수."
                      }
                    }
                  },
                  "reference_intrusion": {
                    "type": "object",
                    "description": "검출 결과. 분석할 수 없는 항목은 생략되거나 null입니다.",
                    "properties": {
                      "detected": {
                        "type": "boolean",
                        "description": "해당 현상이 검출됐는지 여부."
                      },
                      "suspected": {
                        "type": "boolean",
                        "description": "추가 확인이 필요한지 여부."
                      },
                      "correlation": {
                        "type": "number",
                        "description": "비교 구간의 상관도."
                      },
                      "best_lag_sec": {
                        "type": "number",
                        "description": "가장 잘 일치한 시간 차(초)."
                      },
                      "window_start_sec": {
                        "type": "number",
                        "description": "검사 구간 시작(초)."
                      },
                      "window_end_sec": {
                        "type": "number",
                        "description": "검사 구간 끝(초)."
                      },
                      "matched_characters": {
                        "type": "integer",
                        "description": "일치한 글자 수."
                      },
                      "matched_chars": {
                        "type": "integer",
                        "description": "일치한 글자 수."
                      }
                    }
                  },
                  "text_qa_status": {
                    "type": "string",
                    "description": "텍스트 검사 상태."
                  },
                  "active_start_ms": {
                    "type": "number",
                    "description": "유효 음성 구간 시작(밀리초)."
                  },
                  "active_end_ms": {
                    "type": "number",
                    "description": "유효 음성 구간 끝(밀리초)."
                  },
                  "tail_guard_attached": {
                    "type": "boolean",
                    "description": "끝부분 확인용 보호 구간 부착 여부."
                  },
                  "tail_verified": {
                    "type": "boolean",
                    "description": "끝부분 검증 완료 여부."
                  },
                  "tail_verified_at_ms": {
                    "type": "number",
                    "description": "끝부분을 검증한 시각(밀리초). 검증 전에는 null.",
                    "nullable": true
                  },
                  "tail_body_end_at_ms": {
                    "type": "number",
                    "description": "본문 끝 위치(밀리초).",
                    "nullable": true
                  },
                  "tail_guard_attached_chunk_ids": {
                    "type": "array",
                    "description": "보호 구간이 붙은 음성 구간 ID 목록.",
                    "items": {
                      "type": "string",
                      "description": "확인한 구간 ID."
                    }
                  },
                  "generation_budget_exhausted": {
                    "type": "boolean",
                    "description": "해당 발화의 자동 생성 시도 한도 소진 여부."
                  },
                  "retry_requires_new_regeneration_key": {
                    "type": "boolean",
                    "description": "새 재생성 키가 필요한 상태인지 여부."
                  },
                  "candidate_revision": {
                    "type": "integer",
                    "description": "재시도 회차. 0은 최초 생성이며 재시도할 때 증가합니다.",
                    "minimum": 0
                  }
                }
              }
            },
            "candidates": {
              "type": "array",
              "description": "음원 후보별 검사 결과.",
              "items": {
                "type": "object",
                "description": "발화·음원 후보별 공개 검사 결과. 단계별로 제공되는 항목만 포함합니다.",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "발화 식별자."
                  },
                  "utterance_id": {
                    "type": "string",
                    "description": "발화 식별자. 예: u001."
                  },
                  "candidate_id": {
                    "type": "string",
                    "description": "음성 후보 식별자."
                  },
                  "status": {
                    "type": "string",
                    "description": "항목 처리 또는 검사 상태."
                  },
                  "attempt": {
                    "type": "integer",
                    "description": "생성 시도 회차."
                  },
                  "voice_id": {
                    "type": "string",
                    "description": "요청한 공개 목소리 ID."
                  },
                  "created_at": {
                    "type": "string",
                    "description": "항목 생성 일시."
                  },
                  "elapsed_sec": {
                    "type": "number",
                    "description": "처리 경과 시간(초)."
                  },
                  "reasons": {
                    "type": "array",
                    "description": "검사·실패 사유 목록. 사유가 없으면 빈 배열입니다.",
                    "items": {
                      "type": "string",
                      "description": "검사 결과 사유."
                    }
                  },
                  "speech_rate": {
                    "type": "object",
                    "description": "발화 속도 검사. 검사 단계에 따라 일부 필드는 생략됩니다.",
                    "properties": {
                      "characters": {
                        "type": "integer",
                        "description": "발화 글자 수."
                      },
                      "chars": {
                        "type": "integer",
                        "description": "발화 글자 수."
                      },
                      "duration_sec": {
                        "type": "number",
                        "description": "측정 음성 길이(초)."
                      },
                      "duration_ms": {
                        "type": "number",
                        "description": "측정 음성 길이(밀리초)."
                      },
                      "cps": {
                        "type": "number",
                        "description": "초당 발화 글자 수."
                      },
                      "expected_sec": {
                        "type": "number",
                        "description": "예상 발화 길이(초)."
                      },
                      "expected_duration_ms": {
                        "type": "number",
                        "description": "예상 발화 길이(밀리초)."
                      },
                      "duration_ratio": {
                        "type": "number",
                        "description": "실제 길이/예상 길이 비율. 계산할 수 없으면 null.",
                        "nullable": true
                      },
                      "min_cps": {
                        "type": "number",
                        "description": "최소 허용 초당 글자 수."
                      },
                      "minimum_characters": {
                        "type": "integer",
                        "description": "검사에 필요한 최소 글자 수."
                      },
                      "status": {
                        "type": "string",
                        "description": "속도 검사 결과."
                      }
                    }
                  },
                  "audio_sha256": {
                    "type": "string",
                    "description": "후보 음원 SHA-256. 동일 음원 확인에 사용합니다."
                  },
                  "audio_duration_ms": {
                    "type": "number",
                    "description": "음원 길이(밀리초)."
                  },
                  "audio_available": {
                    "type": "boolean",
                    "description": "후보 음원 다운로드 가능 여부."
                  },
                  "transcript": {
                    "type": "string",
                    "description": "음원에서 인식한 텍스트."
                  },
                  "cer": {
                    "type": "number",
                    "description": "문자 오류율. 낮을수록 원문과 가깝습니다."
                  },
                  "coverage": {
                    "type": "number",
                    "description": "원문에 대한 음성의 포함률."
                  },
                  "repeat": {
                    "type": "object",
                    "description": "검출 결과. 분석할 수 없는 항목은 생략되거나 null입니다.",
                    "properties": {
                      "detected": {
                        "type": "boolean",
                        "description": "해당 현상이 검출됐는지 여부."
                      },
                      "suspected": {
                        "type": "boolean",
                        "description": "추가 확인이 필요한지 여부."
                      },
                      "correlation": {
                        "type": "number",
                        "description": "비교 구간의 상관도."
                      },
                      "best_lag_sec": {
                        "type": "number",
                        "description": "가장 잘 일치한 시간 차(초)."
                      },
                      "window_start_sec": {
                        "type": "number",
                        "description": "검사 구간 시작(초)."
                      },
                      "window_end_sec": {
                        "type": "number",
                        "description": "검사 구간 끝(초)."
                      },
                      "matched_characters": {
                        "type": "integer",
                        "description": "일치한 글자 수."
                      },
                      "matched_chars": {
                        "type": "integer",
                        "description": "일치한 글자 수."
                      }
                    }
                  },
                  "reference_intrusion": {
                    "type": "object",
                    "description": "검출 결과. 분석할 수 없는 항목은 생략되거나 null입니다.",
                    "properties": {
                      "detected": {
                        "type": "boolean",
                        "description": "해당 현상이 검출됐는지 여부."
                      },
                      "suspected": {
                        "type": "boolean",
                        "description": "추가 확인이 필요한지 여부."
                      },
                      "correlation": {
                        "type": "number",
                        "description": "비교 구간의 상관도."
                      },
                      "best_lag_sec": {
                        "type": "number",
                        "description": "가장 잘 일치한 시간 차(초)."
                      },
                      "window_start_sec": {
                        "type": "number",
                        "description": "검사 구간 시작(초)."
                      },
                      "window_end_sec": {
                        "type": "number",
                        "description": "검사 구간 끝(초)."
                      },
                      "matched_characters": {
                        "type": "integer",
                        "description": "일치한 글자 수."
                      },
                      "matched_chars": {
                        "type": "integer",
                        "description": "일치한 글자 수."
                      }
                    }
                  },
                  "text_qa_status": {
                    "type": "string",
                    "description": "텍스트 검사 상태."
                  },
                  "active_start_ms": {
                    "type": "number",
                    "description": "유효 음성 구간 시작(밀리초)."
                  },
                  "active_end_ms": {
                    "type": "number",
                    "description": "유효 음성 구간 끝(밀리초)."
                  },
                  "tail_guard_attached": {
                    "type": "boolean",
                    "description": "끝부분 확인용 보호 구간 부착 여부."
                  },
                  "tail_verified": {
                    "type": "boolean",
                    "description": "끝부분 검증 완료 여부."
                  },
                  "tail_verified_at_ms": {
                    "type": "number",
                    "description": "끝부분을 검증한 시각(밀리초). 검증 전에는 null.",
                    "nullable": true
                  },
                  "tail_body_end_at_ms": {
                    "type": "number",
                    "description": "본문 끝 위치(밀리초).",
                    "nullable": true
                  },
                  "tail_guard_attached_chunk_ids": {
                    "type": "array",
                    "description": "보호 구간이 붙은 음성 구간 ID 목록.",
                    "items": {
                      "type": "string",
                      "description": "확인한 구간 ID."
                    }
                  },
                  "generation_budget_exhausted": {
                    "type": "boolean",
                    "description": "해당 발화의 자동 생성 시도 한도 소진 여부."
                  },
                  "retry_requires_new_regeneration_key": {
                    "type": "boolean",
                    "description": "새 재생성 키가 필요한 상태인지 여부."
                  },
                  "candidate_revision": {
                    "type": "integer",
                    "description": "재시도 회차. 0은 최초 생성이며 재시도할 때 증가합니다.",
                    "minimum": 0
                  }
                }
              }
            },
            "final_quality": {
              "type": "object",
              "description": "최종 결과 검사. 최종 검사 전에는 생략됩니다.",
              "properties": {
                "schema_version": {
                  "type": "string",
                  "description": "품질 결과 규격 버전."
                },
                "attempt": {
                  "type": "integer",
                  "description": "현재 검사 시도 회차."
                },
                "phase": {
                  "type": "string",
                  "description": "현재 처리 단계."
                },
                "accepted_utterances": {
                  "type": "integer",
                  "description": "통과 발화 수."
                },
                "failed_utterances": {
                  "type": "integer",
                  "description": "실패 발화 수."
                },
                "total_utterances": {
                  "type": "integer",
                  "description": "전체 발화 수."
                },
                "expires_at": {
                  "type": "string",
                  "description": "후보 결과 보관 만료 일시.",
                  "nullable": true
                },
                "queue_elapsed_sec": {
                  "type": "number",
                  "description": "대기 시간(초)."
                },
                "generation_elapsed_sec": {
                  "type": "number",
                  "description": "생성 시간(초)."
                },
                "utterances": {
                  "type": "array",
                  "description": "발화별 검사 결과.",
                  "items": {
                    "type": "object",
                    "description": "발화·음원 후보별 공개 검사 결과. 단계별로 제공되는 항목만 포함합니다.",
                    "properties": {
                      "id": {
                        "type": "string",
                        "description": "발화 식별자."
                      },
                      "utterance_id": {
                        "type": "string",
                        "description": "발화 식별자. 예: u001."
                      },
                      "candidate_id": {
                        "type": "string",
                        "description": "음성 후보 식별자."
                      },
                      "status": {
                        "type": "string",
                        "description": "항목 처리 또는 검사 상태."
                      },
                      "attempt": {
                        "type": "integer",
                        "description": "생성 시도 회차."
                      },
                      "voice_id": {
                        "type": "string",
                        "description": "요청한 공개 목소리 ID."
                      },
                      "created_at": {
                        "type": "string",
                        "description": "항목 생성 일시."
                      },
                      "elapsed_sec": {
                        "type": "number",
                        "description": "처리 경과 시간(초)."
                      },
                      "reasons": {
                        "type": "array",
                        "description": "검사·실패 사유 목록. 사유가 없으면 빈 배열입니다.",
                        "items": {
                          "type": "string",
                          "description": "검사 결과 사유."
                        }
                      },
                      "speech_rate": {
                        "type": "object",
                        "description": "발화 속도 검사. 검사 단계에 따라 일부 필드는 생략됩니다.",
                        "properties": {
                          "characters": {
                            "type": "integer",
                            "description": "발화 글자 수."
                          },
                          "chars": {
                            "type": "integer",
                            "description": "발화 글자 수."
                          },
                          "duration_sec": {
                            "type": "number",
                            "description": "측정 음성 길이(초)."
                          },
                          "duration_ms": {
                            "type": "number",
                            "description": "측정 음성 길이(밀리초)."
                          },
                          "cps": {
                            "type": "number",
                            "description": "초당 발화 글자 수."
                          },
                          "expected_sec": {
                            "type": "number",
                            "description": "예상 발화 길이(초)."
                          },
                          "expected_duration_ms": {
                            "type": "number",
                            "description": "예상 발화 길이(밀리초)."
                          },
                          "duration_ratio": {
                            "type": "number",
                            "description": "실제 길이/예상 길이 비율. 계산할 수 없으면 null.",
                            "nullable": true
                          },
                          "min_cps": {
                            "type": "number",
                            "description": "최소 허용 초당 글자 수."
                          },
                          "minimum_characters": {
                            "type": "integer",
                            "description": "검사에 필요한 최소 글자 수."
                          },
                          "status": {
                            "type": "string",
                            "description": "속도 검사 결과."
                          }
                        }
                      },
                      "audio_sha256": {
                        "type": "string",
                        "description": "후보 음원 SHA-256. 동일 음원 확인에 사용합니다."
                      },
                      "audio_duration_ms": {
                        "type": "number",
                        "description": "음원 길이(밀리초)."
                      },
                      "audio_available": {
                        "type": "boolean",
                        "description": "후보 음원 다운로드 가능 여부."
                      },
                      "transcript": {
                        "type": "string",
                        "description": "음원에서 인식한 텍스트."
                      },
                      "cer": {
                        "type": "number",
                        "description": "문자 오류율. 낮을수록 원문과 가깝습니다."
                      },
                      "coverage": {
                        "type": "number",
                        "description": "원문에 대한 음성의 포함률."
                      },
                      "repeat": {
                        "type": "object",
                        "description": "검출 결과. 분석할 수 없는 항목은 생략되거나 null입니다.",
                        "properties": {
                          "detected": {
                            "type": "boolean",
                            "description": "해당 현상이 검출됐는지 여부."
                          },
                          "suspected": {
                            "type": "boolean",
                            "description": "추가 확인이 필요한지 여부."
                          },
                          "correlation": {
                            "type": "number",
                            "description": "비교 구간의 상관도."
                          },
                          "best_lag_sec": {
                            "type": "number",
                            "description": "가장 잘 일치한 시간 차(초)."
                          },
                          "window_start_sec": {
                            "type": "number",
                            "description": "검사 구간 시작(초)."
                          },
                          "window_end_sec": {
                            "type": "number",
                            "description": "검사 구간 끝(초)."
                          },
                          "matched_characters": {
                            "type": "integer",
                            "description": "일치한 글자 수."
                          },
                          "matched_chars": {
                            "type": "integer",
                            "description": "일치한 글자 수."
                          }
                        }
                      },
                      "reference_intrusion": {
                        "type": "object",
                        "description": "검출 결과. 분석할 수 없는 항목은 생략되거나 null입니다.",
                        "properties": {
                          "detected": {
                            "type": "boolean",
                            "description": "해당 현상이 검출됐는지 여부."
                          },
                          "suspected": {
                            "type": "boolean",
                            "description": "추가 확인이 필요한지 여부."
                          },
                          "correlation": {
                            "type": "number",
                            "description": "비교 구간의 상관도."
                          },
                          "best_lag_sec": {
                            "type": "number",
                            "description": "가장 잘 일치한 시간 차(초)."
                          },
                          "window_start_sec": {
                            "type": "number",
                            "description": "검사 구간 시작(초)."
                          },
                          "window_end_sec": {
                            "type": "number",
                            "description": "검사 구간 끝(초)."
                          },
                          "matched_characters": {
                            "type": "integer",
                            "description": "일치한 글자 수."
                          },
                          "matched_chars": {
                            "type": "integer",
                            "description": "일치한 글자 수."
                          }
                        }
                      },
                      "text_qa_status": {
                        "type": "string",
                        "description": "텍스트 검사 상태."
                      },
                      "active_start_ms": {
                        "type": "number",
                        "description": "유효 음성 구간 시작(밀리초)."
                      },
                      "active_end_ms": {
                        "type": "number",
                        "description": "유효 음성 구간 끝(밀리초)."
                      },
                      "tail_guard_attached": {
                        "type": "boolean",
                        "description": "끝부분 확인용 보호 구간 부착 여부."
                      },
                      "tail_verified": {
                        "type": "boolean",
                        "description": "끝부분 검증 완료 여부."
                      },
                      "tail_verified_at_ms": {
                        "type": "number",
                        "description": "끝부분을 검증한 시각(밀리초). 검증 전에는 null.",
                        "nullable": true
                      },
                      "tail_body_end_at_ms": {
                        "type": "number",
                        "description": "본문 끝 위치(밀리초).",
                        "nullable": true
                      },
                      "tail_guard_attached_chunk_ids": {
                        "type": "array",
                        "description": "보호 구간이 붙은 음성 구간 ID 목록.",
                        "items": {
                          "type": "string",
                          "description": "확인한 구간 ID."
                        }
                      },
                      "generation_budget_exhausted": {
                        "type": "boolean",
                        "description": "해당 발화의 자동 생성 시도 한도 소진 여부."
                      },
                      "retry_requires_new_regeneration_key": {
                        "type": "boolean",
                        "description": "새 재생성 키가 필요한 상태인지 여부."
                      },
                      "candidate_revision": {
                        "type": "integer",
                        "description": "재시도 회차. 0은 최초 생성이며 재시도할 때 증가합니다.",
                        "minimum": 0
                      }
                    }
                  }
                },
                "candidates": {
                  "type": "array",
                  "description": "음원 후보별 검사 결과.",
                  "items": {
                    "type": "object",
                    "description": "발화·음원 후보별 공개 검사 결과. 단계별로 제공되는 항목만 포함합니다.",
                    "properties": {
                      "id": {
                        "type": "string",
                        "description": "발화 식별자."
                      },
                      "utterance_id": {
                        "type": "string",
                        "description": "발화 식별자. 예: u001."
                      },
                      "candidate_id": {
                        "type": "string",
                        "description": "음성 후보 식별자."
                      },
                      "status": {
                        "type": "string",
                        "description": "항목 처리 또는 검사 상태."
                      },
                      "attempt": {
                        "type": "integer",
                        "description": "생성 시도 회차."
                      },
                      "voice_id": {
                        "type": "string",
                        "description": "요청한 공개 목소리 ID."
                      },
                      "created_at": {
                        "type": "string",
                        "description": "항목 생성 일시."
                      },
                      "elapsed_sec": {
                        "type": "number",
                        "description": "처리 경과 시간(초)."
                      },
                      "reasons": {
                        "type": "array",
                        "description": "검사·실패 사유 목록. 사유가 없으면 빈 배열입니다.",
                        "items": {
                          "type": "string",
                          "description": "검사 결과 사유."
                        }
                      },
                      "speech_rate": {
                        "type": "object",
                        "description": "발화 속도 검사. 검사 단계에 따라 일부 필드는 생략됩니다.",
                        "properties": {
                          "characters": {
                            "type": "integer",
                            "description": "발화 글자 수."
                          },
                          "chars": {
                            "type": "integer",
                            "description": "발화 글자 수."
                          },
                          "duration_sec": {
                            "type": "number",
                            "description": "측정 음성 길이(초)."
                          },
                          "duration_ms": {
                            "type": "number",
                            "description": "측정 음성 길이(밀리초)."
                          },
                          "cps": {
                            "type": "number",
                            "description": "초당 발화 글자 수."
                          },
                          "expected_sec": {
                            "type": "number",
                            "description": "예상 발화 길이(초)."
                          },
                          "expected_duration_ms": {
                            "type": "number",
                            "description": "예상 발화 길이(밀리초)."
                          },
                          "duration_ratio": {
                            "type": "number",
                            "description": "실제 길이/예상 길이 비율. 계산할 수 없으면 null.",
                            "nullable": true
                          },
                          "min_cps": {
                            "type": "number",
                            "description": "최소 허용 초당 글자 수."
                          },
                          "minimum_characters": {
                            "type": "integer",
                            "description": "검사에 필요한 최소 글자 수."
                          },
                          "status": {
                            "type": "string",
                            "description": "속도 검사 결과."
                          }
                        }
                      },
                      "audio_sha256": {
                        "type": "string",
                        "description": "후보 음원 SHA-256. 동일 음원 확인에 사용합니다."
                      },
                      "audio_duration_ms": {
                        "type": "number",
                        "description": "음원 길이(밀리초)."
                      },
                      "audio_available": {
                        "type": "boolean",
                        "description": "후보 음원 다운로드 가능 여부."
                      },
                      "transcript": {
                        "type": "string",
                        "description": "음원에서 인식한 텍스트."
                      },
                      "cer": {
                        "type": "number",
                        "description": "문자 오류율. 낮을수록 원문과 가깝습니다."
                      },
                      "coverage": {
                        "type": "number",
                        "description": "원문에 대한 음성의 포함률."
                      },
                      "repeat": {
                        "type": "object",
                        "description": "검출 결과. 분석할 수 없는 항목은 생략되거나 null입니다.",
                        "properties": {
                          "detected": {
                            "type": "boolean",
                            "description": "해당 현상이 검출됐는지 여부."
                          },
                          "suspected": {
                            "type": "boolean",
                            "description": "추가 확인이 필요한지 여부."
                          },
                          "correlation": {
                            "type": "number",
                            "description": "비교 구간의 상관도."
                          },
                          "best_lag_sec": {
                            "type": "number",
                            "description": "가장 잘 일치한 시간 차(초)."
                          },
                          "window_start_sec": {
                            "type": "number",
                            "description": "검사 구간 시작(초)."
                          },
                          "window_end_sec": {
                            "type": "number",
                            "description": "검사 구간 끝(초)."
                          },
                          "matched_characters": {
                            "type": "integer",
                            "description": "일치한 글자 수."
                          },
                          "matched_chars": {
                            "type": "integer",
                            "description": "일치한 글자 수."
                          }
                        }
                      },
                      "reference_intrusion": {
                        "type": "object",
                        "description": "검출 결과. 분석할 수 없는 항목은 생략되거나 null입니다.",
                        "properties": {
                          "detected": {
                            "type": "boolean",
                            "description": "해당 현상이 검출됐는지 여부."
                          },
                          "suspected": {
                            "type": "boolean",
                            "description": "추가 확인이 필요한지 여부."
                          },
                          "correlation": {
                            "type": "number",
                            "description": "비교 구간의 상관도."
                          },
                          "best_lag_sec": {
                            "type": "number",
                            "description": "가장 잘 일치한 시간 차(초)."
                          },
                          "window_start_sec": {
                            "type": "number",
                            "description": "검사 구간 시작(초)."
                          },
                          "window_end_sec": {
                            "type": "number",
                            "description": "검사 구간 끝(초)."
                          },
                          "matched_characters": {
                            "type": "integer",
                            "description": "일치한 글자 수."
                          },
                          "matched_chars": {
                            "type": "integer",
                            "description": "일치한 글자 수."
                          }
                        }
                      },
                      "text_qa_status": {
                        "type": "string",
                        "description": "텍스트 검사 상태."
                      },
                      "active_start_ms": {
                        "type": "number",
                        "description": "유효 음성 구간 시작(밀리초)."
                      },
                      "active_end_ms": {
                        "type": "number",
                        "description": "유효 음성 구간 끝(밀리초)."
                      },
                      "tail_guard_attached": {
                        "type": "boolean",
                        "description": "끝부분 확인용 보호 구간 부착 여부."
                      },
                      "tail_verified": {
                        "type": "boolean",
                        "description": "끝부분 검증 완료 여부."
                      },
                      "tail_verified_at_ms": {
                        "type": "number",
                        "description": "끝부분을 검증한 시각(밀리초). 검증 전에는 null.",
                        "nullable": true
                      },
                      "tail_body_end_at_ms": {
                        "type": "number",
                        "description": "본문 끝 위치(밀리초).",
                        "nullable": true
                      },
                      "tail_guard_attached_chunk_ids": {
                        "type": "array",
                        "description": "보호 구간이 붙은 음성 구간 ID 목록.",
                        "items": {
                          "type": "string",
                          "description": "확인한 구간 ID."
                        }
                      },
                      "generation_budget_exhausted": {
                        "type": "boolean",
                        "description": "해당 발화의 자동 생성 시도 한도 소진 여부."
                      },
                      "retry_requires_new_regeneration_key": {
                        "type": "boolean",
                        "description": "새 재생성 키가 필요한 상태인지 여부."
                      },
                      "candidate_revision": {
                        "type": "integer",
                        "description": "재시도 회차. 0은 최초 생성이며 재시도할 때 증가합니다.",
                        "minimum": 0
                      }
                    }
                  }
                },
                "status": {
                  "type": "string",
                  "description": "최종 검사 상태."
                },
                "audio_sha256": {
                  "type": "string",
                  "description": "최종 음원 SHA-256."
                }
              }
            }
          },
          "nullable": true
        },
        "error": {
          "type": "object",
          "description": "실패 상태일 때 포함합니다.",
          "properties": {
            "code": {
              "type": "string",
              "description": "실패한 작업의 공개 오류코드."
            },
            "message": {
              "type": "string",
              "description": "오류 설명."
            }
          }
        }
      }
    },
    "api": {
      "type": "object",
      "description": "호출 메타데이터.",
      "properties": {
        "success": {
          "type": "boolean",
          "description": "API 공통 처리 여부. HTTP 상태·업무 결과와 함께 확인합니다."
        },
        "cost": {
          "type": "number",
          "description": "이번 호출에서 차감한 포인트. 무료 조회·재전송은 0."
        },
        "pl_id": {
          "type": "integer",
          "description": "과금 기록 ID. 과금 기록이 있을 때만 포함합니다."
        }
      }
    }
  }
}

```

### 정적 응답 예시

```json

{
  "data": {
    "job_id": "7f7e43f578cd459db04696416435c789",
    "status": "completed",
    "result_available": true,
    "subtitles_available": true
  },
  "api": {
    "success": true,
    "cost": 0
  }
}

```

### 정적 응답 예시

```json

{
  "data": {
    "job_id": "7f7e43f578cd459db04696416435c789",
    "status": "cancelled"
  },
  "api": {
    "success": true,
    "cost": 0
  }
}

```

### curl

```curl

curl --fail-with-body --request GET "https://apick.app/rest/tts/jobs/${APICK_JOB_ID}" \
  --header "Authorization: Bearer $APICK_API_KEY"

```

### Node.js (서버 ESM)

```javascript

const response = await fetch(`https://apick.app/rest/tts/jobs/${encodeURIComponent(process.env.APICK_JOB_ID)}`, {
  method: "GET",
  headers: { Authorization: "Bearer " + process.env.APICK_API_KEY },
  signal: AbortSignal.timeout(120_000),
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
const result = await response.json();
console.log(result);

```

### python

```python

import os
import requests
from urllib.parse import quote
response = requests.request("GET", "https://apick.app" + "/rest/tts/jobs/{job_id}".format(job_id=quote(os.environ["APICK_JOB_ID"], safe="")),
    headers={"Authorization": "Bearer " + os.environ["APICK_API_KEY"]},
    timeout=(10, 120))
response.raise_for_status()
result = response.json()
print(result)

```

### php

```php

<?php
$headers = ["Authorization: Bearer " . getenv("APICK_API_KEY")];
$curl = curl_init('https://apick.app/rest/tts/jobs/' . rawurlencode(getenv('APICK_JOB_ID')) . '');
curl_setopt_array($curl, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_TIMEOUT => 120,
]);
$body = curl_exec($curl);
if ($body === false) { throw new RuntimeException(curl_error($curl)); }
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
if ($status >= 400) { throw new RuntimeException($body); }
$result = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
print_r($result);

```

## POST /rest/tts/jobs/:job_id/cancel 응답 필드

- `data` (object): 아래 하위 항목을 확인하세요.

- `data.job_id` (string): 접수 응답에서 받은 작업 ID. 같은 계정의 작업에만 접근할 수 있습니다.

- `data.status` (string): 취소 완료 상태. 허용값: cancelled

- `api` (object): 호출 메타데이터.

- `api.success` (boolean): API 공통 처리 여부. HTTP 상태·업무 결과와 함께 확인합니다.

- `api.cost` (number): 이번 호출에서 차감한 포인트. 무료 조회·재전송은 0.

- `api.pl_id` (integer): 과금 기록 ID. 과금 기록이 있을 때만 포함합니다.

## 작업 취소: POST /rest/tts/jobs/:job_id/cancel



### 입력



### 응답 명세

```json

{
  "type": "object",
  "description": "공개 JSON 응답.",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "job_id": {
          "type": "string",
          "description": "접수 응답에서 받은 작업 ID. 같은 계정의 작업에만 접근할 수 있습니다."
        },
        "status": {
          "type": "string",
          "description": "취소 완료 상태.",
          "enum": [
            "cancelled"
          ]
        }
      }
    },
    "api": {
      "type": "object",
      "description": "호출 메타데이터.",
      "properties": {
        "success": {
          "type": "boolean",
          "description": "API 공통 처리 여부. HTTP 상태·업무 결과와 함께 확인합니다."
        },
        "cost": {
          "type": "number",
          "description": "이번 호출에서 차감한 포인트. 무료 조회·재전송은 0."
        },
        "pl_id": {
          "type": "integer",
          "description": "과금 기록 ID. 과금 기록이 있을 때만 포함합니다."
        }
      }
    }
  }
}

```

### 정적 응답 예시

```json

{
  "data": {
    "job_id": "7f7e43f578cd459db04696416435c789",
    "status": "cancelled"
  },
  "api": {
    "success": true,
    "cost": 0
  }
}

```

### curl

```curl

printf '%s\r\n' '--apick-empty--' | curl --fail-with-body --request POST "https://apick.app/rest/tts/jobs/${APICK_JOB_ID}/cancel" \
  --header "Authorization: Bearer $APICK_API_KEY" \
  --header 'Content-Type: multipart/form-data; boundary=apick-empty' \
  --data-binary @-

```

### Node.js (서버 ESM)

```javascript

const form = new FormData();
const response = await fetch(`https://apick.app/rest/tts/jobs/${encodeURIComponent(process.env.APICK_JOB_ID)}/cancel`, {
  method: "POST",
  headers: { Authorization: "Bearer " + process.env.APICK_API_KEY },
  body: form,
  signal: AbortSignal.timeout(120_000),
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
const result = await response.json();
console.log(result);

```

### python

```python

import os
import requests
from urllib.parse import quote
response = requests.request("POST", "https://apick.app" + "/rest/tts/jobs/{job_id}/cancel".format(job_id=quote(os.environ["APICK_JOB_ID"], safe="")),
    headers={"Authorization": "Bearer " + os.environ["APICK_API_KEY"], "Content-Type": "multipart/form-data; boundary=apick-empty"},
    data=b"--apick-empty--\r\n",
    timeout=(10, 120))
response.raise_for_status()
result = response.json()
print(result)

```

### php

```php

<?php
$headers = ["Authorization: Bearer " . getenv("APICK_API_KEY")];
$headers[] = "Content-Type: multipart/form-data; boundary=apick-empty";
$form = "--apick-empty--\r\n";
$curl = curl_init('https://apick.app/rest/tts/jobs/' . rawurlencode(getenv('APICK_JOB_ID')) . '/cancel');
curl_setopt_array($curl, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_POSTFIELDS => $form,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_TIMEOUT => 120,
]);
$body = curl_exec($curl);
if ($body === false) { throw new RuntimeException(curl_error($curl)); }
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
if ($status >= 400) { throw new RuntimeException($body); }
$result = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
print_r($result);

```

## GET /rest/tts/jobs/:job_id/result 응답 필드

## 결과 받기: GET /rest/tts/jobs/:job_id/result



### 입력



### 응답 명세

```json

{
  "type": "string",
  "format": "binary"
}

```

### curl

```curl

curl --fail-with-body --request GET "https://apick.app/rest/tts/jobs/${APICK_JOB_ID}/result" \
  --header "Authorization: Bearer $APICK_API_KEY" \
  --dump-header response.headers --output result.mp3
# response.headers의 Content-Type을 확인한 뒤 파일을 사용하세요.

```

### Node.js (서버 ESM)

```javascript

const response = await fetch(`https://apick.app/rest/tts/jobs/${encodeURIComponent(process.env.APICK_JOB_ID)}/result`, {
  method: "GET",
  headers: { Authorization: "Bearer " + process.env.APICK_API_KEY },
  signal: AbortSignal.timeout(120_000),
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
if ((response.headers.get("content-type") || "").includes("json")) {
  throw new Error(JSON.stringify(await response.json()));
}
const { writeFile } = await import("node:fs/promises");
await writeFile("result.mp3", new Uint8Array(await response.arrayBuffer()));

```

### python

```python

import os
import requests
from urllib.parse import quote
response = requests.request("GET", "https://apick.app" + "/rest/tts/jobs/{job_id}/result".format(job_id=quote(os.environ["APICK_JOB_ID"], safe="")),
    headers={"Authorization": "Bearer " + os.environ["APICK_API_KEY"]},
    timeout=(10, 120), stream=True)
response.raise_for_status()
if "json" in response.headers.get("Content-Type", ""):
    raise RuntimeError(response.json())
with open("result.mp3", "wb") as output:
    for chunk in response.iter_content(65536):
        output.write(chunk)

```

### php

```php

<?php
$headers = ["Authorization: Bearer " . getenv("APICK_API_KEY")];
$curl = curl_init('https://apick.app/rest/tts/jobs/' . rawurlencode(getenv('APICK_JOB_ID')) . '/result');
curl_setopt_array($curl, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_TIMEOUT => 120,
]);
$body = curl_exec($curl);
if ($body === false) { throw new RuntimeException(curl_error($curl)); }
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
$type = curl_getinfo($curl, CURLINFO_CONTENT_TYPE) ?: "";
curl_close($curl);
if ($status >= 400) { throw new RuntimeException($body); }
if (strpos($type, "json") !== false) { throw new RuntimeException($body); }
file_put_contents('result.mp3', $body);

```

## GET /rest/tts/jobs/:job_id/subtitles 응답 필드

## 결과 받기: GET /rest/tts/jobs/:job_id/subtitles



### 입력



### 응답 명세

```json

{
  "type": "string",
  "format": "binary"
}

```

### curl

```curl

curl --fail-with-body --request GET "https://apick.app/rest/tts/jobs/${APICK_JOB_ID}/subtitles" \
  --header "Authorization: Bearer $APICK_API_KEY" \
  --dump-header response.headers --output result.bin
# response.headers의 Content-Type을 확인한 뒤 파일을 사용하세요.

```

### Node.js (서버 ESM)

```javascript

const response = await fetch(`https://apick.app/rest/tts/jobs/${encodeURIComponent(process.env.APICK_JOB_ID)}/subtitles`, {
  method: "GET",
  headers: { Authorization: "Bearer " + process.env.APICK_API_KEY },
  signal: AbortSignal.timeout(120_000),
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
if ((response.headers.get("content-type") || "").includes("json")) {
  throw new Error(JSON.stringify(await response.json()));
}
const { writeFile } = await import("node:fs/promises");
await writeFile("result.bin", new Uint8Array(await response.arrayBuffer()));

```

### python

```python

import os
import requests
from urllib.parse import quote
response = requests.request("GET", "https://apick.app" + "/rest/tts/jobs/{job_id}/subtitles".format(job_id=quote(os.environ["APICK_JOB_ID"], safe="")),
    headers={"Authorization": "Bearer " + os.environ["APICK_API_KEY"]},
    timeout=(10, 120), stream=True)
response.raise_for_status()
if "json" in response.headers.get("Content-Type", ""):
    raise RuntimeError(response.json())
with open("result.bin", "wb") as output:
    for chunk in response.iter_content(65536):
        output.write(chunk)

```

### php

```php

<?php
$headers = ["Authorization: Bearer " . getenv("APICK_API_KEY")];
$curl = curl_init('https://apick.app/rest/tts/jobs/' . rawurlencode(getenv('APICK_JOB_ID')) . '/subtitles');
curl_setopt_array($curl, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_TIMEOUT => 120,
]);
$body = curl_exec($curl);
if ($body === false) { throw new RuntimeException(curl_error($curl)); }
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
$type = curl_getinfo($curl, CURLINFO_CONTENT_TYPE) ?: "";
curl_close($curl);
if ($status >= 400) { throw new RuntimeException($body); }
if (strpos($type, "json") !== false) { throw new RuntimeException($body); }
file_put_contents('result.bin', $body);

```

## GET /rest/tts/jobs/:job_id/quality 응답 필드

- `data` (object): 아래 하위 항목을 확인하세요.

- `data.job_id` (string): 접수 응답에서 받은 작업 ID. 같은 계정의 작업에만 접근할 수 있습니다.

- `data.resume_revision` (integer): 재시도 회차. 0은 최초 생성이며 재시도할 때 증가합니다.

- `data.schema_version` (string): 품질 결과 규격 버전.

- `data.attempt` (integer): 현재 검사 시도 회차.

- `data.phase` (string): 현재 처리 단계.

- `data.accepted_utterances` (integer): 통과 발화 수.

- `data.failed_utterances` (integer): 실패 발화 수.

- `data.total_utterances` (integer): 전체 발화 수.

- `data.expires_at` (string): 후보 결과 보관 만료 일시. null 허용.

- `data.queue_elapsed_sec` (number): 대기 시간(초).

- `data.generation_elapsed_sec` (number): 생성 시간(초).

- `data.utterances` (array): 발화별 검사 결과.

- `data.utterances[].id` (string): 발화 식별자.

- `data.utterances[].utterance_id` (string): 발화 식별자. 예: u001.

- `data.utterances[].candidate_id` (string): 음성 후보 식별자.

- `data.utterances[].status` (string): 항목 처리 또는 검사 상태.

- `data.utterances[].attempt` (integer): 생성 시도 회차.

- `data.utterances[].voice_id` (string): 요청한 공개 목소리 ID.

- `data.utterances[].created_at` (string): 항목 생성 일시.

- `data.utterances[].elapsed_sec` (number): 처리 경과 시간(초).

- `data.utterances[].reasons` (array): 검사·실패 사유 목록. 사유가 없으면 빈 배열입니다.

- `data.utterances[].speech_rate` (object): 발화 속도 검사. 검사 단계에 따라 일부 필드는 생략됩니다.

- `data.utterances[].speech_rate.characters` (integer): 발화 글자 수.

- `data.utterances[].speech_rate.chars` (integer): 발화 글자 수.

- `data.utterances[].speech_rate.duration_sec` (number): 측정 음성 길이(초).

- `data.utterances[].speech_rate.duration_ms` (number): 측정 음성 길이(밀리초).

- `data.utterances[].speech_rate.cps` (number): 초당 발화 글자 수.

- `data.utterances[].speech_rate.expected_sec` (number): 예상 발화 길이(초).

- `data.utterances[].speech_rate.expected_duration_ms` (number): 예상 발화 길이(밀리초).

- `data.utterances[].speech_rate.duration_ratio` (number): 실제 길이/예상 길이 비율. 계산할 수 없으면 null. null 허용.

- `data.utterances[].speech_rate.min_cps` (number): 최소 허용 초당 글자 수.

- `data.utterances[].speech_rate.minimum_characters` (integer): 검사에 필요한 최소 글자 수.

- `data.utterances[].speech_rate.status` (string): 속도 검사 결과.

- `data.utterances[].audio_sha256` (string): 후보 음원 SHA-256. 동일 음원 확인에 사용합니다.

- `data.utterances[].audio_duration_ms` (number): 음원 길이(밀리초).

- `data.utterances[].audio_available` (boolean): 후보 음원 다운로드 가능 여부.

- `data.utterances[].transcript` (string): 음원에서 인식한 텍스트.

- `data.utterances[].cer` (number): 문자 오류율. 낮을수록 원문과 가깝습니다.

- `data.utterances[].coverage` (number): 원문에 대한 음성의 포함률.

- `data.utterances[].repeat` (object): 검출 결과. 분석할 수 없는 항목은 생략되거나 null입니다.

- `data.utterances[].repeat.detected` (boolean): 해당 현상이 검출됐는지 여부.

- `data.utterances[].repeat.suspected` (boolean): 추가 확인이 필요한지 여부.

- `data.utterances[].repeat.correlation` (number): 비교 구간의 상관도.

- `data.utterances[].repeat.best_lag_sec` (number): 가장 잘 일치한 시간 차(초).

- `data.utterances[].repeat.window_start_sec` (number): 검사 구간 시작(초).

- `data.utterances[].repeat.window_end_sec` (number): 검사 구간 끝(초).

- `data.utterances[].repeat.matched_characters` (integer): 일치한 글자 수.

- `data.utterances[].repeat.matched_chars` (integer): 일치한 글자 수.

- `data.utterances[].reference_intrusion` (object): 검출 결과. 분석할 수 없는 항목은 생략되거나 null입니다.

- `data.utterances[].reference_intrusion.detected` (boolean): 해당 현상이 검출됐는지 여부.

- `data.utterances[].reference_intrusion.suspected` (boolean): 추가 확인이 필요한지 여부.

- `data.utterances[].reference_intrusion.correlation` (number): 비교 구간의 상관도.

- `data.utterances[].reference_intrusion.best_lag_sec` (number): 가장 잘 일치한 시간 차(초).

- `data.utterances[].reference_intrusion.window_start_sec` (number): 검사 구간 시작(초).

- `data.utterances[].reference_intrusion.window_end_sec` (number): 검사 구간 끝(초).

- `data.utterances[].reference_intrusion.matched_characters` (integer): 일치한 글자 수.

- `data.utterances[].reference_intrusion.matched_chars` (integer): 일치한 글자 수.

- `data.utterances[].text_qa_status` (string): 텍스트 검사 상태.

- `data.utterances[].active_start_ms` (number): 유효 음성 구간 시작(밀리초).

- `data.utterances[].active_end_ms` (number): 유효 음성 구간 끝(밀리초).

- `data.utterances[].tail_guard_attached` (boolean): 끝부분 확인용 보호 구간 부착 여부.

- `data.utterances[].tail_verified` (boolean): 끝부분 검증 완료 여부.

- `data.utterances[].tail_verified_at_ms` (number): 끝부분을 검증한 시각(밀리초). 검증 전에는 null. null 허용.

- `data.utterances[].tail_body_end_at_ms` (number): 본문 끝 위치(밀리초). null 허용.

- `data.utterances[].tail_guard_attached_chunk_ids` (array): 보호 구간이 붙은 음성 구간 ID 목록.

- `data.utterances[].generation_budget_exhausted` (boolean): 해당 발화의 자동 생성 시도 한도 소진 여부.

- `data.utterances[].retry_requires_new_regeneration_key` (boolean): 새 재생성 키가 필요한 상태인지 여부.

- `data.utterances[].candidate_revision` (integer): 재시도 회차. 0은 최초 생성이며 재시도할 때 증가합니다.

- `data.candidates` (array): 음원 후보별 검사 결과.

- `data.candidates[].id` (string): 발화 식별자.

- `data.candidates[].utterance_id` (string): 발화 식별자. 예: u001.

- `data.candidates[].candidate_id` (string): 음성 후보 식별자.

- `data.candidates[].status` (string): 항목 처리 또는 검사 상태.

- `data.candidates[].attempt` (integer): 생성 시도 회차.

- `data.candidates[].voice_id` (string): 요청한 공개 목소리 ID.

- `data.candidates[].created_at` (string): 항목 생성 일시.

- `data.candidates[].elapsed_sec` (number): 처리 경과 시간(초).

- `data.candidates[].reasons` (array): 검사·실패 사유 목록. 사유가 없으면 빈 배열입니다.

- `data.candidates[].speech_rate` (object): 발화 속도 검사. 검사 단계에 따라 일부 필드는 생략됩니다.

- `data.candidates[].speech_rate.characters` (integer): 발화 글자 수.

- `data.candidates[].speech_rate.chars` (integer): 발화 글자 수.

- `data.candidates[].speech_rate.duration_sec` (number): 측정 음성 길이(초).

- `data.candidates[].speech_rate.duration_ms` (number): 측정 음성 길이(밀리초).

- `data.candidates[].speech_rate.cps` (number): 초당 발화 글자 수.

- `data.candidates[].speech_rate.expected_sec` (number): 예상 발화 길이(초).

- `data.candidates[].speech_rate.expected_duration_ms` (number): 예상 발화 길이(밀리초).

- `data.candidates[].speech_rate.duration_ratio` (number): 실제 길이/예상 길이 비율. 계산할 수 없으면 null. null 허용.

- `data.candidates[].speech_rate.min_cps` (number): 최소 허용 초당 글자 수.

- `data.candidates[].speech_rate.minimum_characters` (integer): 검사에 필요한 최소 글자 수.

- `data.candidates[].speech_rate.status` (string): 속도 검사 결과.

- `data.candidates[].audio_sha256` (string): 후보 음원 SHA-256. 동일 음원 확인에 사용합니다.

- `data.candidates[].audio_duration_ms` (number): 음원 길이(밀리초).

- `data.candidates[].audio_available` (boolean): 후보 음원 다운로드 가능 여부.

- `data.candidates[].transcript` (string): 음원에서 인식한 텍스트.

- `data.candidates[].cer` (number): 문자 오류율. 낮을수록 원문과 가깝습니다.

- `data.candidates[].coverage` (number): 원문에 대한 음성의 포함률.

- `data.candidates[].repeat` (object): 검출 결과. 분석할 수 없는 항목은 생략되거나 null입니다.

- `data.candidates[].repeat.detected` (boolean): 해당 현상이 검출됐는지 여부.

- `data.candidates[].repeat.suspected` (boolean): 추가 확인이 필요한지 여부.

- `data.candidates[].repeat.correlation` (number): 비교 구간의 상관도.

- `data.candidates[].repeat.best_lag_sec` (number): 가장 잘 일치한 시간 차(초).

- `data.candidates[].repeat.window_start_sec` (number): 검사 구간 시작(초).

- `data.candidates[].repeat.window_end_sec` (number): 검사 구간 끝(초).

- `data.candidates[].repeat.matched_characters` (integer): 일치한 글자 수.

- `data.candidates[].repeat.matched_chars` (integer): 일치한 글자 수.

- `data.candidates[].reference_intrusion` (object): 검출 결과. 분석할 수 없는 항목은 생략되거나 null입니다.

- `data.candidates[].reference_intrusion.detected` (boolean): 해당 현상이 검출됐는지 여부.

- `data.candidates[].reference_intrusion.suspected` (boolean): 추가 확인이 필요한지 여부.

- `data.candidates[].reference_intrusion.correlation` (number): 비교 구간의 상관도.

- `data.candidates[].reference_intrusion.best_lag_sec` (number): 가장 잘 일치한 시간 차(초).

- `data.candidates[].reference_intrusion.window_start_sec` (number): 검사 구간 시작(초).

- `data.candidates[].reference_intrusion.window_end_sec` (number): 검사 구간 끝(초).

- `data.candidates[].reference_intrusion.matched_characters` (integer): 일치한 글자 수.

- `data.candidates[].reference_intrusion.matched_chars` (integer): 일치한 글자 수.

- `data.candidates[].text_qa_status` (string): 텍스트 검사 상태.

- `data.candidates[].active_start_ms` (number): 유효 음성 구간 시작(밀리초).

- `data.candidates[].active_end_ms` (number): 유효 음성 구간 끝(밀리초).

- `data.candidates[].tail_guard_attached` (boolean): 끝부분 확인용 보호 구간 부착 여부.

- `data.candidates[].tail_verified` (boolean): 끝부분 검증 완료 여부.

- `data.candidates[].tail_verified_at_ms` (number): 끝부분을 검증한 시각(밀리초). 검증 전에는 null. null 허용.

- `data.candidates[].tail_body_end_at_ms` (number): 본문 끝 위치(밀리초). null 허용.

- `data.candidates[].tail_guard_attached_chunk_ids` (array): 보호 구간이 붙은 음성 구간 ID 목록.

- `data.candidates[].generation_budget_exhausted` (boolean): 해당 발화의 자동 생성 시도 한도 소진 여부.

- `data.candidates[].retry_requires_new_regeneration_key` (boolean): 새 재생성 키가 필요한 상태인지 여부.

- `data.candidates[].candidate_revision` (integer): 재시도 회차. 0은 최초 생성이며 재시도할 때 증가합니다.

- `data.final_quality` (object): 최종 결과 검사. 최종 검사 전에는 생략됩니다.

- `data.final_quality.schema_version` (string): 품질 결과 규격 버전.

- `data.final_quality.attempt` (integer): 현재 검사 시도 회차.

- `data.final_quality.phase` (string): 현재 처리 단계.

- `data.final_quality.accepted_utterances` (integer): 통과 발화 수.

- `data.final_quality.failed_utterances` (integer): 실패 발화 수.

- `data.final_quality.total_utterances` (integer): 전체 발화 수.

- `data.final_quality.expires_at` (string): 후보 결과 보관 만료 일시. null 허용.

- `data.final_quality.queue_elapsed_sec` (number): 대기 시간(초).

- `data.final_quality.generation_elapsed_sec` (number): 생성 시간(초).

- `data.final_quality.utterances` (array): 발화별 검사 결과.

- `data.final_quality.utterances[].id` (string): 발화 식별자.

- `data.final_quality.utterances[].utterance_id` (string): 발화 식별자. 예: u001.

- `data.final_quality.utterances[].candidate_id` (string): 음성 후보 식별자.

- `data.final_quality.utterances[].status` (string): 항목 처리 또는 검사 상태.

- `data.final_quality.utterances[].attempt` (integer): 생성 시도 회차.

- `data.final_quality.utterances[].voice_id` (string): 요청한 공개 목소리 ID.

- `data.final_quality.utterances[].created_at` (string): 항목 생성 일시.

- `data.final_quality.utterances[].elapsed_sec` (number): 처리 경과 시간(초).

- `data.final_quality.utterances[].reasons` (array): 검사·실패 사유 목록. 사유가 없으면 빈 배열입니다.

- `data.final_quality.utterances[].speech_rate` (object): 발화 속도 검사. 검사 단계에 따라 일부 필드는 생략됩니다.

- `data.final_quality.utterances[].speech_rate.characters` (integer): 발화 글자 수.

- `data.final_quality.utterances[].speech_rate.chars` (integer): 발화 글자 수.

- `data.final_quality.utterances[].speech_rate.duration_sec` (number): 측정 음성 길이(초).

- `data.final_quality.utterances[].speech_rate.duration_ms` (number): 측정 음성 길이(밀리초).

- `data.final_quality.utterances[].speech_rate.cps` (number): 초당 발화 글자 수.

- `data.final_quality.utterances[].speech_rate.expected_sec` (number): 예상 발화 길이(초).

- `data.final_quality.utterances[].speech_rate.expected_duration_ms` (number): 예상 발화 길이(밀리초).

- `data.final_quality.utterances[].speech_rate.duration_ratio` (number): 실제 길이/예상 길이 비율. 계산할 수 없으면 null. null 허용.

- `data.final_quality.utterances[].speech_rate.min_cps` (number): 최소 허용 초당 글자 수.

- `data.final_quality.utterances[].speech_rate.minimum_characters` (integer): 검사에 필요한 최소 글자 수.

- `data.final_quality.utterances[].speech_rate.status` (string): 속도 검사 결과.

- `data.final_quality.utterances[].audio_sha256` (string): 후보 음원 SHA-256. 동일 음원 확인에 사용합니다.

- `data.final_quality.utterances[].audio_duration_ms` (number): 음원 길이(밀리초).

- `data.final_quality.utterances[].audio_available` (boolean): 후보 음원 다운로드 가능 여부.

- `data.final_quality.utterances[].transcript` (string): 음원에서 인식한 텍스트.

- `data.final_quality.utterances[].cer` (number): 문자 오류율. 낮을수록 원문과 가깝습니다.

- `data.final_quality.utterances[].coverage` (number): 원문에 대한 음성의 포함률.

- `data.final_quality.utterances[].repeat` (object): 검출 결과. 분석할 수 없는 항목은 생략되거나 null입니다.

- `data.final_quality.utterances[].repeat.detected` (boolean): 해당 현상이 검출됐는지 여부.

- `data.final_quality.utterances[].repeat.suspected` (boolean): 추가 확인이 필요한지 여부.

- `data.final_quality.utterances[].repeat.correlation` (number): 비교 구간의 상관도.

- `data.final_quality.utterances[].repeat.best_lag_sec` (number): 가장 잘 일치한 시간 차(초).

- `data.final_quality.utterances[].repeat.window_start_sec` (number): 검사 구간 시작(초).

- `data.final_quality.utterances[].repeat.window_end_sec` (number): 검사 구간 끝(초).

- `data.final_quality.utterances[].repeat.matched_characters` (integer): 일치한 글자 수.

- `data.final_quality.utterances[].repeat.matched_chars` (integer): 일치한 글자 수.

- `data.final_quality.utterances[].reference_intrusion` (object): 검출 결과. 분석할 수 없는 항목은 생략되거나 null입니다.

- `data.final_quality.utterances[].reference_intrusion.detected` (boolean): 해당 현상이 검출됐는지 여부.

- `data.final_quality.utterances[].reference_intrusion.suspected` (boolean): 추가 확인이 필요한지 여부.

- `data.final_quality.utterances[].reference_intrusion.correlation` (number): 비교 구간의 상관도.

- `data.final_quality.utterances[].reference_intrusion.best_lag_sec` (number): 가장 잘 일치한 시간 차(초).

- `data.final_quality.utterances[].reference_intrusion.window_start_sec` (number): 검사 구간 시작(초).

- `data.final_quality.utterances[].reference_intrusion.window_end_sec` (number): 검사 구간 끝(초).

- `data.final_quality.utterances[].reference_intrusion.matched_characters` (integer): 일치한 글자 수.

- `data.final_quality.utterances[].reference_intrusion.matched_chars` (integer): 일치한 글자 수.

- `data.final_quality.utterances[].text_qa_status` (string): 텍스트 검사 상태.

- `data.final_quality.utterances[].active_start_ms` (number): 유효 음성 구간 시작(밀리초).

- `data.final_quality.utterances[].active_end_ms` (number): 유효 음성 구간 끝(밀리초).

- `data.final_quality.utterances[].tail_guard_attached` (boolean): 끝부분 확인용 보호 구간 부착 여부.

- `data.final_quality.utterances[].tail_verified` (boolean): 끝부분 검증 완료 여부.

- `data.final_quality.utterances[].tail_verified_at_ms` (number): 끝부분을 검증한 시각(밀리초). 검증 전에는 null. null 허용.

- `data.final_quality.utterances[].tail_body_end_at_ms` (number): 본문 끝 위치(밀리초). null 허용.

- `data.final_quality.utterances[].tail_guard_attached_chunk_ids` (array): 보호 구간이 붙은 음성 구간 ID 목록.

- `data.final_quality.utterances[].generation_budget_exhausted` (boolean): 해당 발화의 자동 생성 시도 한도 소진 여부.

- `data.final_quality.utterances[].retry_requires_new_regeneration_key` (boolean): 새 재생성 키가 필요한 상태인지 여부.

- `data.final_quality.utterances[].candidate_revision` (integer): 재시도 회차. 0은 최초 생성이며 재시도할 때 증가합니다.

- `data.final_quality.candidates` (array): 음원 후보별 검사 결과.

- `data.final_quality.candidates[].id` (string): 발화 식별자.

- `data.final_quality.candidates[].utterance_id` (string): 발화 식별자. 예: u001.

- `data.final_quality.candidates[].candidate_id` (string): 음성 후보 식별자.

- `data.final_quality.candidates[].status` (string): 항목 처리 또는 검사 상태.

- `data.final_quality.candidates[].attempt` (integer): 생성 시도 회차.

- `data.final_quality.candidates[].voice_id` (string): 요청한 공개 목소리 ID.

- `data.final_quality.candidates[].created_at` (string): 항목 생성 일시.

- `data.final_quality.candidates[].elapsed_sec` (number): 처리 경과 시간(초).

- `data.final_quality.candidates[].reasons` (array): 검사·실패 사유 목록. 사유가 없으면 빈 배열입니다.

- `data.final_quality.candidates[].speech_rate` (object): 발화 속도 검사. 검사 단계에 따라 일부 필드는 생략됩니다.

- `data.final_quality.candidates[].speech_rate.characters` (integer): 발화 글자 수.

- `data.final_quality.candidates[].speech_rate.chars` (integer): 발화 글자 수.

- `data.final_quality.candidates[].speech_rate.duration_sec` (number): 측정 음성 길이(초).

- `data.final_quality.candidates[].speech_rate.duration_ms` (number): 측정 음성 길이(밀리초).

- `data.final_quality.candidates[].speech_rate.cps` (number): 초당 발화 글자 수.

- `data.final_quality.candidates[].speech_rate.expected_sec` (number): 예상 발화 길이(초).

- `data.final_quality.candidates[].speech_rate.expected_duration_ms` (number): 예상 발화 길이(밀리초).

- `data.final_quality.candidates[].speech_rate.duration_ratio` (number): 실제 길이/예상 길이 비율. 계산할 수 없으면 null. null 허용.

- `data.final_quality.candidates[].speech_rate.min_cps` (number): 최소 허용 초당 글자 수.

- `data.final_quality.candidates[].speech_rate.minimum_characters` (integer): 검사에 필요한 최소 글자 수.

- `data.final_quality.candidates[].speech_rate.status` (string): 속도 검사 결과.

- `data.final_quality.candidates[].audio_sha256` (string): 후보 음원 SHA-256. 동일 음원 확인에 사용합니다.

- `data.final_quality.candidates[].audio_duration_ms` (number): 음원 길이(밀리초).

- `data.final_quality.candidates[].audio_available` (boolean): 후보 음원 다운로드 가능 여부.

- `data.final_quality.candidates[].transcript` (string): 음원에서 인식한 텍스트.

- `data.final_quality.candidates[].cer` (number): 문자 오류율. 낮을수록 원문과 가깝습니다.

- `data.final_quality.candidates[].coverage` (number): 원문에 대한 음성의 포함률.

- `data.final_quality.candidates[].repeat` (object): 검출 결과. 분석할 수 없는 항목은 생략되거나 null입니다.

- `data.final_quality.candidates[].repeat.detected` (boolean): 해당 현상이 검출됐는지 여부.

- `data.final_quality.candidates[].repeat.suspected` (boolean): 추가 확인이 필요한지 여부.

- `data.final_quality.candidates[].repeat.correlation` (number): 비교 구간의 상관도.

- `data.final_quality.candidates[].repeat.best_lag_sec` (number): 가장 잘 일치한 시간 차(초).

- `data.final_quality.candidates[].repeat.window_start_sec` (number): 검사 구간 시작(초).

- `data.final_quality.candidates[].repeat.window_end_sec` (number): 검사 구간 끝(초).

- `data.final_quality.candidates[].repeat.matched_characters` (integer): 일치한 글자 수.

- `data.final_quality.candidates[].repeat.matched_chars` (integer): 일치한 글자 수.

- `data.final_quality.candidates[].reference_intrusion` (object): 검출 결과. 분석할 수 없는 항목은 생략되거나 null입니다.

- `data.final_quality.candidates[].reference_intrusion.detected` (boolean): 해당 현상이 검출됐는지 여부.

- `data.final_quality.candidates[].reference_intrusion.suspected` (boolean): 추가 확인이 필요한지 여부.

- `data.final_quality.candidates[].reference_intrusion.correlation` (number): 비교 구간의 상관도.

- `data.final_quality.candidates[].reference_intrusion.best_lag_sec` (number): 가장 잘 일치한 시간 차(초).

- `data.final_quality.candidates[].reference_intrusion.window_start_sec` (number): 검사 구간 시작(초).

- `data.final_quality.candidates[].reference_intrusion.window_end_sec` (number): 검사 구간 끝(초).

- `data.final_quality.candidates[].reference_intrusion.matched_characters` (integer): 일치한 글자 수.

- `data.final_quality.candidates[].reference_intrusion.matched_chars` (integer): 일치한 글자 수.

- `data.final_quality.candidates[].text_qa_status` (string): 텍스트 검사 상태.

- `data.final_quality.candidates[].active_start_ms` (number): 유효 음성 구간 시작(밀리초).

- `data.final_quality.candidates[].active_end_ms` (number): 유효 음성 구간 끝(밀리초).

- `data.final_quality.candidates[].tail_guard_attached` (boolean): 끝부분 확인용 보호 구간 부착 여부.

- `data.final_quality.candidates[].tail_verified` (boolean): 끝부분 검증 완료 여부.

- `data.final_quality.candidates[].tail_verified_at_ms` (number): 끝부분을 검증한 시각(밀리초). 검증 전에는 null. null 허용.

- `data.final_quality.candidates[].tail_body_end_at_ms` (number): 본문 끝 위치(밀리초). null 허용.

- `data.final_quality.candidates[].tail_guard_attached_chunk_ids` (array): 보호 구간이 붙은 음성 구간 ID 목록.

- `data.final_quality.candidates[].generation_budget_exhausted` (boolean): 해당 발화의 자동 생성 시도 한도 소진 여부.

- `data.final_quality.candidates[].retry_requires_new_regeneration_key` (boolean): 새 재생성 키가 필요한 상태인지 여부.

- `data.final_quality.candidates[].candidate_revision` (integer): 재시도 회차. 0은 최초 생성이며 재시도할 때 증가합니다.

- `data.final_quality.status` (string): 최종 검사 상태.

- `data.final_quality.audio_sha256` (string): 최종 음원 SHA-256.

- `api` (object): 호출 메타데이터.

- `api.success` (boolean): API 공통 처리 여부. HTTP 상태·업무 결과와 함께 확인합니다.

- `api.cost` (number): 이번 호출에서 차감한 포인트. 무료 조회·재전송은 0.

- `api.pl_id` (integer): 과금 기록 ID. 과금 기록이 있을 때만 포함합니다.

## 상태·목록 조회: GET /rest/tts/jobs/:job_id/quality



### 입력



### 응답 명세

```json

{
  "type": "object",
  "description": "공개 JSON 응답.",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "job_id": {
          "type": "string",
          "description": "접수 응답에서 받은 작업 ID. 같은 계정의 작업에만 접근할 수 있습니다."
        },
        "resume_revision": {
          "type": "integer",
          "description": "재시도 회차. 0은 최초 생성이며 재시도할 때 증가합니다.",
          "minimum": 0
        },
        "schema_version": {
          "type": "string",
          "description": "품질 결과 규격 버전."
        },
        "attempt": {
          "type": "integer",
          "description": "현재 검사 시도 회차."
        },
        "phase": {
          "type": "string",
          "description": "현재 처리 단계."
        },
        "accepted_utterances": {
          "type": "integer",
          "description": "통과 발화 수."
        },
        "failed_utterances": {
          "type": "integer",
          "description": "실패 발화 수."
        },
        "total_utterances": {
          "type": "integer",
          "description": "전체 발화 수."
        },
        "expires_at": {
          "type": "string",
          "description": "후보 결과 보관 만료 일시.",
          "nullable": true
        },
        "queue_elapsed_sec": {
          "type": "number",
          "description": "대기 시간(초)."
        },
        "generation_elapsed_sec": {
          "type": "number",
          "description": "생성 시간(초)."
        },
        "utterances": {
          "type": "array",
          "description": "발화별 검사 결과.",
          "items": {
            "type": "object",
            "description": "발화·음원 후보별 공개 검사 결과. 단계별로 제공되는 항목만 포함합니다.",
            "properties": {
              "id": {
                "type": "string",
                "description": "발화 식별자."
              },
              "utterance_id": {
                "type": "string",
                "description": "발화 식별자. 예: u001."
              },
              "candidate_id": {
                "type": "string",
                "description": "음성 후보 식별자."
              },
              "status": {
                "type": "string",
                "description": "항목 처리 또는 검사 상태."
              },
              "attempt": {
                "type": "integer",
                "description": "생성 시도 회차."
              },
              "voice_id": {
                "type": "string",
                "description": "요청한 공개 목소리 ID."
              },
              "created_at": {
                "type": "string",
                "description": "항목 생성 일시."
              },
              "elapsed_sec": {
                "type": "number",
                "description": "처리 경과 시간(초)."
              },
              "reasons": {
                "type": "array",
                "description": "검사·실패 사유 목록. 사유가 없으면 빈 배열입니다.",
                "items": {
                  "type": "string",
                  "description": "검사 결과 사유."
                }
              },
              "speech_rate": {
                "type": "object",
                "description": "발화 속도 검사. 검사 단계에 따라 일부 필드는 생략됩니다.",
                "properties": {
                  "characters": {
                    "type": "integer",
                    "description": "발화 글자 수."
                  },
                  "chars": {
                    "type": "integer",
                    "description": "발화 글자 수."
                  },
                  "duration_sec": {
                    "type": "number",
                    "description": "측정 음성 길이(초)."
                  },
                  "duration_ms": {
                    "type": "number",
                    "description": "측정 음성 길이(밀리초)."
                  },
                  "cps": {
                    "type": "number",
                    "description": "초당 발화 글자 수."
                  },
                  "expected_sec": {
                    "type": "number",
                    "description": "예상 발화 길이(초)."
                  },
                  "expected_duration_ms": {
                    "type": "number",
                    "description": "예상 발화 길이(밀리초)."
                  },
                  "duration_ratio": {
                    "type": "number",
                    "description": "실제 길이/예상 길이 비율. 계산할 수 없으면 null.",
                    "nullable": true
                  },
                  "min_cps": {
                    "type": "number",
                    "description": "최소 허용 초당 글자 수."
                  },
                  "minimum_characters": {
                    "type": "integer",
                    "description": "검사에 필요한 최소 글자 수."
                  },
                  "status": {
                    "type": "string",
                    "description": "속도 검사 결과."
                  }
                }
              },
              "audio_sha256": {
                "type": "string",
                "description": "후보 음원 SHA-256. 동일 음원 확인에 사용합니다."
              },
              "audio_duration_ms": {
                "type": "number",
                "description": "음원 길이(밀리초)."
              },
              "audio_available": {
                "type": "boolean",
                "description": "후보 음원 다운로드 가능 여부."
              },
              "transcript": {
                "type": "string",
                "description": "음원에서 인식한 텍스트."
              },
              "cer": {
                "type": "number",
                "description": "문자 오류율. 낮을수록 원문과 가깝습니다."
              },
              "coverage": {
                "type": "number",
                "description": "원문에 대한 음성의 포함률."
              },
              "repeat": {
                "type": "object",
                "description": "검출 결과. 분석할 수 없는 항목은 생략되거나 null입니다.",
                "properties": {
                  "detected": {
                    "type": "boolean",
                    "description": "해당 현상이 검출됐는지 여부."
                  },
                  "suspected": {
                    "type": "boolean",
                    "description": "추가 확인이 필요한지 여부."
                  },
                  "correlation": {
                    "type": "number",
                    "description": "비교 구간의 상관도."
                  },
                  "best_lag_sec": {
                    "type": "number",
                    "description": "가장 잘 일치한 시간 차(초)."
                  },
                  "window_start_sec": {
                    "type": "number",
                    "description": "검사 구간 시작(초)."
                  },
                  "window_end_sec": {
                    "type": "number",
                    "description": "검사 구간 끝(초)."
                  },
                  "matched_characters": {
                    "type": "integer",
                    "description": "일치한 글자 수."
                  },
                  "matched_chars": {
                    "type": "integer",
                    "description": "일치한 글자 수."
                  }
                }
              },
              "reference_intrusion": {
                "type": "object",
                "description": "검출 결과. 분석할 수 없는 항목은 생략되거나 null입니다.",
                "properties": {
                  "detected": {
                    "type": "boolean",
                    "description": "해당 현상이 검출됐는지 여부."
                  },
                  "suspected": {
                    "type": "boolean",
                    "description": "추가 확인이 필요한지 여부."
                  },
                  "correlation": {
                    "type": "number",
                    "description": "비교 구간의 상관도."
                  },
                  "best_lag_sec": {
                    "type": "number",
                    "description": "가장 잘 일치한 시간 차(초)."
                  },
                  "window_start_sec": {
                    "type": "number",
                    "description": "검사 구간 시작(초)."
                  },
                  "window_end_sec": {
                    "type": "number",
                    "description": "검사 구간 끝(초)."
                  },
                  "matched_characters": {
                    "type": "integer",
                    "description": "일치한 글자 수."
                  },
                  "matched_chars": {
                    "type": "integer",
                    "description": "일치한 글자 수."
                  }
                }
              },
              "text_qa_status": {
                "type": "string",
                "description": "텍스트 검사 상태."
              },
              "active_start_ms": {
                "type": "number",
                "description": "유효 음성 구간 시작(밀리초)."
              },
              "active_end_ms": {
                "type": "number",
                "description": "유효 음성 구간 끝(밀리초)."
              },
              "tail_guard_attached": {
                "type": "boolean",
                "description": "끝부분 확인용 보호 구간 부착 여부."
              },
              "tail_verified": {
                "type": "boolean",
                "description": "끝부분 검증 완료 여부."
              },
              "tail_verified_at_ms": {
                "type": "number",
                "description": "끝부분을 검증한 시각(밀리초). 검증 전에는 null.",
                "nullable": true
              },
              "tail_body_end_at_ms": {
                "type": "number",
                "description": "본문 끝 위치(밀리초).",
                "nullable": true
              },
              "tail_guard_attached_chunk_ids": {
                "type": "array",
                "description": "보호 구간이 붙은 음성 구간 ID 목록.",
                "items": {
                  "type": "string",
                  "description": "확인한 구간 ID."
                }
              },
              "generation_budget_exhausted": {
                "type": "boolean",
                "description": "해당 발화의 자동 생성 시도 한도 소진 여부."
              },
              "retry_requires_new_regeneration_key": {
                "type": "boolean",
                "description": "새 재생성 키가 필요한 상태인지 여부."
              },
              "candidate_revision": {
                "type": "integer",
                "description": "재시도 회차. 0은 최초 생성이며 재시도할 때 증가합니다.",
                "minimum": 0
              }
            }
          }
        },
        "candidates": {
          "type": "array",
          "description": "음원 후보별 검사 결과.",
          "items": {
            "type": "object",
            "description": "발화·음원 후보별 공개 검사 결과. 단계별로 제공되는 항목만 포함합니다.",
            "properties": {
              "id": {
                "type": "string",
                "description": "발화 식별자."
              },
              "utterance_id": {
                "type": "string",
                "description": "발화 식별자. 예: u001."
              },
              "candidate_id": {
                "type": "string",
                "description": "음성 후보 식별자."
              },
              "status": {
                "type": "string",
                "description": "항목 처리 또는 검사 상태."
              },
              "attempt": {
                "type": "integer",
                "description": "생성 시도 회차."
              },
              "voice_id": {
                "type": "string",
                "description": "요청한 공개 목소리 ID."
              },
              "created_at": {
                "type": "string",
                "description": "항목 생성 일시."
              },
              "elapsed_sec": {
                "type": "number",
                "description": "처리 경과 시간(초)."
              },
              "reasons": {
                "type": "array",
                "description": "검사·실패 사유 목록. 사유가 없으면 빈 배열입니다.",
                "items": {
                  "type": "string",
                  "description": "검사 결과 사유."
                }
              },
              "speech_rate": {
                "type": "object",
                "description": "발화 속도 검사. 검사 단계에 따라 일부 필드는 생략됩니다.",
                "properties": {
                  "characters": {
                    "type": "integer",
                    "description": "발화 글자 수."
                  },
                  "chars": {
                    "type": "integer",
                    "description": "발화 글자 수."
                  },
                  "duration_sec": {
                    "type": "number",
                    "description": "측정 음성 길이(초)."
                  },
                  "duration_ms": {
                    "type": "number",
                    "description": "측정 음성 길이(밀리초)."
                  },
                  "cps": {
                    "type": "number",
                    "description": "초당 발화 글자 수."
                  },
                  "expected_sec": {
                    "type": "number",
                    "description": "예상 발화 길이(초)."
                  },
                  "expected_duration_ms": {
                    "type": "number",
                    "description": "예상 발화 길이(밀리초)."
                  },
                  "duration_ratio": {
                    "type": "number",
                    "description": "실제 길이/예상 길이 비율. 계산할 수 없으면 null.",
                    "nullable": true
                  },
                  "min_cps": {
                    "type": "number",
                    "description": "최소 허용 초당 글자 수."
                  },
                  "minimum_characters": {
                    "type": "integer",
                    "description": "검사에 필요한 최소 글자 수."
                  },
                  "status": {
                    "type": "string",
                    "description": "속도 검사 결과."
                  }
                }
              },
              "audio_sha256": {
                "type": "string",
                "description": "후보 음원 SHA-256. 동일 음원 확인에 사용합니다."
              },
              "audio_duration_ms": {
                "type": "number",
                "description": "음원 길이(밀리초)."
              },
              "audio_available": {
                "type": "boolean",
                "description": "후보 음원 다운로드 가능 여부."
              },
              "transcript": {
                "type": "string",
                "description": "음원에서 인식한 텍스트."
              },
              "cer": {
                "type": "number",
                "description": "문자 오류율. 낮을수록 원문과 가깝습니다."
              },
              "coverage": {
                "type": "number",
                "description": "원문에 대한 음성의 포함률."
              },
              "repeat": {
                "type": "object",
                "description": "검출 결과. 분석할 수 없는 항목은 생략되거나 null입니다.",
                "properties": {
                  "detected": {
                    "type": "boolean",
                    "description": "해당 현상이 검출됐는지 여부."
                  },
                  "suspected": {
                    "type": "boolean",
                    "description": "추가 확인이 필요한지 여부."
                  },
                  "correlation": {
                    "type": "number",
                    "description": "비교 구간의 상관도."
                  },
                  "best_lag_sec": {
                    "type": "number",
                    "description": "가장 잘 일치한 시간 차(초)."
                  },
                  "window_start_sec": {
                    "type": "number",
                    "description": "검사 구간 시작(초)."
                  },
                  "window_end_sec": {
                    "type": "number",
                    "description": "검사 구간 끝(초)."
                  },
                  "matched_characters": {
                    "type": "integer",
                    "description": "일치한 글자 수."
                  },
                  "matched_chars": {
                    "type": "integer",
                    "description": "일치한 글자 수."
                  }
                }
              },
              "reference_intrusion": {
                "type": "object",
                "description": "검출 결과. 분석할 수 없는 항목은 생략되거나 null입니다.",
                "properties": {
                  "detected": {
                    "type": "boolean",
                    "description": "해당 현상이 검출됐는지 여부."
                  },
                  "suspected": {
                    "type": "boolean",
                    "description": "추가 확인이 필요한지 여부."
                  },
                  "correlation": {
                    "type": "number",
                    "description": "비교 구간의 상관도."
                  },
                  "best_lag_sec": {
                    "type": "number",
                    "description": "가장 잘 일치한 시간 차(초)."
                  },
                  "window_start_sec": {
                    "type": "number",
                    "description": "검사 구간 시작(초)."
                  },
                  "window_end_sec": {
                    "type": "number",
                    "description": "검사 구간 끝(초)."
                  },
                  "matched_characters": {
                    "type": "integer",
                    "description": "일치한 글자 수."
                  },
                  "matched_chars": {
                    "type": "integer",
                    "description": "일치한 글자 수."
                  }
                }
              },
              "text_qa_status": {
                "type": "string",
                "description": "텍스트 검사 상태."
              },
              "active_start_ms": {
                "type": "number",
                "description": "유효 음성 구간 시작(밀리초)."
              },
              "active_end_ms": {
                "type": "number",
                "description": "유효 음성 구간 끝(밀리초)."
              },
              "tail_guard_attached": {
                "type": "boolean",
                "description": "끝부분 확인용 보호 구간 부착 여부."
              },
              "tail_verified": {
                "type": "boolean",
                "description": "끝부분 검증 완료 여부."
              },
              "tail_verified_at_ms": {
                "type": "number",
                "description": "끝부분을 검증한 시각(밀리초). 검증 전에는 null.",
                "nullable": true
              },
              "tail_body_end_at_ms": {
                "type": "number",
                "description": "본문 끝 위치(밀리초).",
                "nullable": true
              },
              "tail_guard_attached_chunk_ids": {
                "type": "array",
                "description": "보호 구간이 붙은 음성 구간 ID 목록.",
                "items": {
                  "type": "string",
                  "description": "확인한 구간 ID."
                }
              },
              "generation_budget_exhausted": {
                "type": "boolean",
                "description": "해당 발화의 자동 생성 시도 한도 소진 여부."
              },
              "retry_requires_new_regeneration_key": {
                "type": "boolean",
                "description": "새 재생성 키가 필요한 상태인지 여부."
              },
              "candidate_revision": {
                "type": "integer",
                "description": "재시도 회차. 0은 최초 생성이며 재시도할 때 증가합니다.",
                "minimum": 0
              }
            }
          }
        },
        "final_quality": {
          "type": "object",
          "description": "최종 결과 검사. 최종 검사 전에는 생략됩니다.",
          "properties": {
            "schema_version": {
              "type": "string",
              "description": "품질 결과 규격 버전."
            },
            "attempt": {
              "type": "integer",
              "description": "현재 검사 시도 회차."
            },
            "phase": {
              "type": "string",
              "description": "현재 처리 단계."
            },
            "accepted_utterances": {
              "type": "integer",
              "description": "통과 발화 수."
            },
            "failed_utterances": {
              "type": "integer",
              "description": "실패 발화 수."
            },
            "total_utterances": {
              "type": "integer",
              "description": "전체 발화 수."
            },
            "expires_at": {
              "type": "string",
              "description": "후보 결과 보관 만료 일시.",
              "nullable": true
            },
            "queue_elapsed_sec": {
              "type": "number",
              "description": "대기 시간(초)."
            },
            "generation_elapsed_sec": {
              "type": "number",
              "description": "생성 시간(초)."
            },
            "utterances": {
              "type": "array",
              "description": "발화별 검사 결과.",
              "items": {
                "type": "object",
                "description": "발화·음원 후보별 공개 검사 결과. 단계별로 제공되는 항목만 포함합니다.",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "발화 식별자."
                  },
                  "utterance_id": {
                    "type": "string",
                    "description": "발화 식별자. 예: u001."
                  },
                  "candidate_id": {
                    "type": "string",
                    "description": "음성 후보 식별자."
                  },
                  "status": {
                    "type": "string",
                    "description": "항목 처리 또는 검사 상태."
                  },
                  "attempt": {
                    "type": "integer",
                    "description": "생성 시도 회차."
                  },
                  "voice_id": {
                    "type": "string",
                    "description": "요청한 공개 목소리 ID."
                  },
                  "created_at": {
                    "type": "string",
                    "description": "항목 생성 일시."
                  },
                  "elapsed_sec": {
                    "type": "number",
                    "description": "처리 경과 시간(초)."
                  },
                  "reasons": {
                    "type": "array",
                    "description": "검사·실패 사유 목록. 사유가 없으면 빈 배열입니다.",
                    "items": {
                      "type": "string",
                      "description": "검사 결과 사유."
                    }
                  },
                  "speech_rate": {
                    "type": "object",
                    "description": "발화 속도 검사. 검사 단계에 따라 일부 필드는 생략됩니다.",
                    "properties": {
                      "characters": {
                        "type": "integer",
                        "description": "발화 글자 수."
                      },
                      "chars": {
                        "type": "integer",
                        "description": "발화 글자 수."
                      },
                      "duration_sec": {
                        "type": "number",
                        "description": "측정 음성 길이(초)."
                      },
                      "duration_ms": {
                        "type": "number",
                        "description": "측정 음성 길이(밀리초)."
                      },
                      "cps": {
                        "type": "number",
                        "description": "초당 발화 글자 수."
                      },
                      "expected_sec": {
                        "type": "number",
                        "description": "예상 발화 길이(초)."
                      },
                      "expected_duration_ms": {
                        "type": "number",
                        "description": "예상 발화 길이(밀리초)."
                      },
                      "duration_ratio": {
                        "type": "number",
                        "description": "실제 길이/예상 길이 비율. 계산할 수 없으면 null.",
                        "nullable": true
                      },
                      "min_cps": {
                        "type": "number",
                        "description": "최소 허용 초당 글자 수."
                      },
                      "minimum_characters": {
                        "type": "integer",
                        "description": "검사에 필요한 최소 글자 수."
                      },
                      "status": {
                        "type": "string",
                        "description": "속도 검사 결과."
                      }
                    }
                  },
                  "audio_sha256": {
                    "type": "string",
                    "description": "후보 음원 SHA-256. 동일 음원 확인에 사용합니다."
                  },
                  "audio_duration_ms": {
                    "type": "number",
                    "description": "음원 길이(밀리초)."
                  },
                  "audio_available": {
                    "type": "boolean",
                    "description": "후보 음원 다운로드 가능 여부."
                  },
                  "transcript": {
                    "type": "string",
                    "description": "음원에서 인식한 텍스트."
                  },
                  "cer": {
                    "type": "number",
                    "description": "문자 오류율. 낮을수록 원문과 가깝습니다."
                  },
                  "coverage": {
                    "type": "number",
                    "description": "원문에 대한 음성의 포함률."
                  },
                  "repeat": {
                    "type": "object",
                    "description": "검출 결과. 분석할 수 없는 항목은 생략되거나 null입니다.",
                    "properties": {
                      "detected": {
                        "type": "boolean",
                        "description": "해당 현상이 검출됐는지 여부."
                      },
                      "suspected": {
                        "type": "boolean",
                        "description": "추가 확인이 필요한지 여부."
                      },
                      "correlation": {
                        "type": "number",
                        "description": "비교 구간의 상관도."
                      },
                      "best_lag_sec": {
                        "type": "number",
                        "description": "가장 잘 일치한 시간 차(초)."
                      },
                      "window_start_sec": {
                        "type": "number",
                        "description": "검사 구간 시작(초)."
                      },
                      "window_end_sec": {
                        "type": "number",
                        "description": "검사 구간 끝(초)."
                      },
                      "matched_characters": {
                        "type": "integer",
                        "description": "일치한 글자 수."
                      },
                      "matched_chars": {
                        "type": "integer",
                        "description": "일치한 글자 수."
                      }
                    }
                  },
                  "reference_intrusion": {
                    "type": "object",
                    "description": "검출 결과. 분석할 수 없는 항목은 생략되거나 null입니다.",
                    "properties": {
                      "detected": {
                        "type": "boolean",
                        "description": "해당 현상이 검출됐는지 여부."
                      },
                      "suspected": {
                        "type": "boolean",
                        "description": "추가 확인이 필요한지 여부."
                      },
                      "correlation": {
                        "type": "number",
                        "description": "비교 구간의 상관도."
                      },
                      "best_lag_sec": {
                        "type": "number",
                        "description": "가장 잘 일치한 시간 차(초)."
                      },
                      "window_start_sec": {
                        "type": "number",
                        "description": "검사 구간 시작(초)."
                      },
                      "window_end_sec": {
                        "type": "number",
                        "description": "검사 구간 끝(초)."
                      },
                      "matched_characters": {
                        "type": "integer",
                        "description": "일치한 글자 수."
                      },
                      "matched_chars": {
                        "type": "integer",
                        "description": "일치한 글자 수."
                      }
                    }
                  },
                  "text_qa_status": {
                    "type": "string",
                    "description": "텍스트 검사 상태."
                  },
                  "active_start_ms": {
                    "type": "number",
                    "description": "유효 음성 구간 시작(밀리초)."
                  },
                  "active_end_ms": {
                    "type": "number",
                    "description": "유효 음성 구간 끝(밀리초)."
                  },
                  "tail_guard_attached": {
                    "type": "boolean",
                    "description": "끝부분 확인용 보호 구간 부착 여부."
                  },
                  "tail_verified": {
                    "type": "boolean",
                    "description": "끝부분 검증 완료 여부."
                  },
                  "tail_verified_at_ms": {
                    "type": "number",
                    "description": "끝부분을 검증한 시각(밀리초). 검증 전에는 null.",
                    "nullable": true
                  },
                  "tail_body_end_at_ms": {
                    "type": "number",
                    "description": "본문 끝 위치(밀리초).",
                    "nullable": true
                  },
                  "tail_guard_attached_chunk_ids": {
                    "type": "array",
                    "description": "보호 구간이 붙은 음성 구간 ID 목록.",
                    "items": {
                      "type": "string",
                      "description": "확인한 구간 ID."
                    }
                  },
                  "generation_budget_exhausted": {
                    "type": "boolean",
                    "description": "해당 발화의 자동 생성 시도 한도 소진 여부."
                  },
                  "retry_requires_new_regeneration_key": {
                    "type": "boolean",
                    "description": "새 재생성 키가 필요한 상태인지 여부."
                  },
                  "candidate_revision": {
                    "type": "integer",
                    "description": "재시도 회차. 0은 최초 생성이며 재시도할 때 증가합니다.",
                    "minimum": 0
                  }
                }
              }
            },
            "candidates": {
              "type": "array",
              "description": "음원 후보별 검사 결과.",
              "items": {
                "type": "object",
                "description": "발화·음원 후보별 공개 검사 결과. 단계별로 제공되는 항목만 포함합니다.",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "발화 식별자."
                  },
                  "utterance_id": {
                    "type": "string",
                    "description": "발화 식별자. 예: u001."
                  },
                  "candidate_id": {
                    "type": "string",
                    "description": "음성 후보 식별자."
                  },
                  "status": {
                    "type": "string",
                    "description": "항목 처리 또는 검사 상태."
                  },
                  "attempt": {
                    "type": "integer",
                    "description": "생성 시도 회차."
                  },
                  "voice_id": {
                    "type": "string",
                    "description": "요청한 공개 목소리 ID."
                  },
                  "created_at": {
                    "type": "string",
                    "description": "항목 생성 일시."
                  },
                  "elapsed_sec": {
                    "type": "number",
                    "description": "처리 경과 시간(초)."
                  },
                  "reasons": {
                    "type": "array",
                    "description": "검사·실패 사유 목록. 사유가 없으면 빈 배열입니다.",
                    "items": {
                      "type": "string",
                      "description": "검사 결과 사유."
                    }
                  },
                  "speech_rate": {
                    "type": "object",
                    "description": "발화 속도 검사. 검사 단계에 따라 일부 필드는 생략됩니다.",
                    "properties": {
                      "characters": {
                        "type": "integer",
                        "description": "발화 글자 수."
                      },
                      "chars": {
                        "type": "integer",
                        "description": "발화 글자 수."
                      },
                      "duration_sec": {
                        "type": "number",
                        "description": "측정 음성 길이(초)."
                      },
                      "duration_ms": {
                        "type": "number",
                        "description": "측정 음성 길이(밀리초)."
                      },
                      "cps": {
                        "type": "number",
                        "description": "초당 발화 글자 수."
                      },
                      "expected_sec": {
                        "type": "number",
                        "description": "예상 발화 길이(초)."
                      },
                      "expected_duration_ms": {
                        "type": "number",
                        "description": "예상 발화 길이(밀리초)."
                      },
                      "duration_ratio": {
                        "type": "number",
                        "description": "실제 길이/예상 길이 비율. 계산할 수 없으면 null.",
                        "nullable": true
                      },
                      "min_cps": {
                        "type": "number",
                        "description": "최소 허용 초당 글자 수."
                      },
                      "minimum_characters": {
                        "type": "integer",
                        "description": "검사에 필요한 최소 글자 수."
                      },
                      "status": {
                        "type": "string",
                        "description": "속도 검사 결과."
                      }
                    }
                  },
                  "audio_sha256": {
                    "type": "string",
                    "description": "후보 음원 SHA-256. 동일 음원 확인에 사용합니다."
                  },
                  "audio_duration_ms": {
                    "type": "number",
                    "description": "음원 길이(밀리초)."
                  },
                  "audio_available": {
                    "type": "boolean",
                    "description": "후보 음원 다운로드 가능 여부."
                  },
                  "transcript": {
                    "type": "string",
                    "description": "음원에서 인식한 텍스트."
                  },
                  "cer": {
                    "type": "number",
                    "description": "문자 오류율. 낮을수록 원문과 가깝습니다."
                  },
                  "coverage": {
                    "type": "number",
                    "description": "원문에 대한 음성의 포함률."
                  },
                  "repeat": {
                    "type": "object",
                    "description": "검출 결과. 분석할 수 없는 항목은 생략되거나 null입니다.",
                    "properties": {
                      "detected": {
                        "type": "boolean",
                        "description": "해당 현상이 검출됐는지 여부."
                      },
                      "suspected": {
                        "type": "boolean",
                        "description": "추가 확인이 필요한지 여부."
                      },
                      "correlation": {
                        "type": "number",
                        "description": "비교 구간의 상관도."
                      },
                      "best_lag_sec": {
                        "type": "number",
                        "description": "가장 잘 일치한 시간 차(초)."
                      },
                      "window_start_sec": {
                        "type": "number",
                        "description": "검사 구간 시작(초)."
                      },
                      "window_end_sec": {
                        "type": "number",
                        "description": "검사 구간 끝(초)."
                      },
                      "matched_characters": {
                        "type": "integer",
                        "description": "일치한 글자 수."
                      },
                      "matched_chars": {
                        "type": "integer",
                        "description": "일치한 글자 수."
                      }
                    }
                  },
                  "reference_intrusion": {
                    "type": "object",
                    "description": "검출 결과. 분석할 수 없는 항목은 생략되거나 null입니다.",
                    "properties": {
                      "detected": {
                        "type": "boolean",
                        "description": "해당 현상이 검출됐는지 여부."
                      },
                      "suspected": {
                        "type": "boolean",
                        "description": "추가 확인이 필요한지 여부."
                      },
                      "correlation": {
                        "type": "number",
                        "description": "비교 구간의 상관도."
                      },
                      "best_lag_sec": {
                        "type": "number",
                        "description": "가장 잘 일치한 시간 차(초)."
                      },
                      "window_start_sec": {
                        "type": "number",
                        "description": "검사 구간 시작(초)."
                      },
                      "window_end_sec": {
                        "type": "number",
                        "description": "검사 구간 끝(초)."
                      },
                      "matched_characters": {
                        "type": "integer",
                        "description": "일치한 글자 수."
                      },
                      "matched_chars": {
                        "type": "integer",
                        "description": "일치한 글자 수."
                      }
                    }
                  },
                  "text_qa_status": {
                    "type": "string",
                    "description": "텍스트 검사 상태."
                  },
                  "active_start_ms": {
                    "type": "number",
                    "description": "유효 음성 구간 시작(밀리초)."
                  },
                  "active_end_ms": {
                    "type": "number",
                    "description": "유효 음성 구간 끝(밀리초)."
                  },
                  "tail_guard_attached": {
                    "type": "boolean",
                    "description": "끝부분 확인용 보호 구간 부착 여부."
                  },
                  "tail_verified": {
                    "type": "boolean",
                    "description": "끝부분 검증 완료 여부."
                  },
                  "tail_verified_at_ms": {
                    "type": "number",
                    "description": "끝부분을 검증한 시각(밀리초). 검증 전에는 null.",
                    "nullable": true
                  },
                  "tail_body_end_at_ms": {
                    "type": "number",
                    "description": "본문 끝 위치(밀리초).",
                    "nullable": true
                  },
                  "tail_guard_attached_chunk_ids": {
                    "type": "array",
                    "description": "보호 구간이 붙은 음성 구간 ID 목록.",
                    "items": {
                      "type": "string",
                      "description": "확인한 구간 ID."
                    }
                  },
                  "generation_budget_exhausted": {
                    "type": "boolean",
                    "description": "해당 발화의 자동 생성 시도 한도 소진 여부."
                  },
                  "retry_requires_new_regeneration_key": {
                    "type": "boolean",
                    "description": "새 재생성 키가 필요한 상태인지 여부."
                  },
                  "candidate_revision": {
                    "type": "integer",
                    "description": "재시도 회차. 0은 최초 생성이며 재시도할 때 증가합니다.",
                    "minimum": 0
                  }
                }
              }
            },
            "status": {
              "type": "string",
              "description": "최종 검사 상태."
            },
            "audio_sha256": {
              "type": "string",
              "description": "최종 음원 SHA-256."
            }
          }
        }
      }
    },
    "api": {
      "type": "object",
      "description": "호출 메타데이터.",
      "properties": {
        "success": {
          "type": "boolean",
          "description": "API 공통 처리 여부. HTTP 상태·업무 결과와 함께 확인합니다."
        },
        "cost": {
          "type": "number",
          "description": "이번 호출에서 차감한 포인트. 무료 조회·재전송은 0."
        },
        "pl_id": {
          "type": "integer",
          "description": "과금 기록 ID. 과금 기록이 있을 때만 포함합니다."
        }
      }
    }
  }
}

```

### curl

```curl

curl --fail-with-body --request GET "https://apick.app/rest/tts/jobs/${APICK_JOB_ID}/quality" \
  --header "Authorization: Bearer $APICK_API_KEY"

```

### Node.js (서버 ESM)

```javascript

const response = await fetch(`https://apick.app/rest/tts/jobs/${encodeURIComponent(process.env.APICK_JOB_ID)}/quality`, {
  method: "GET",
  headers: { Authorization: "Bearer " + process.env.APICK_API_KEY },
  signal: AbortSignal.timeout(120_000),
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
const result = await response.json();
console.log(result);

```

### python

```python

import os
import requests
from urllib.parse import quote
response = requests.request("GET", "https://apick.app" + "/rest/tts/jobs/{job_id}/quality".format(job_id=quote(os.environ["APICK_JOB_ID"], safe="")),
    headers={"Authorization": "Bearer " + os.environ["APICK_API_KEY"]},
    timeout=(10, 120))
response.raise_for_status()
result = response.json()
print(result)

```

### php

```php

<?php
$headers = ["Authorization: Bearer " . getenv("APICK_API_KEY")];
$curl = curl_init('https://apick.app/rest/tts/jobs/' . rawurlencode(getenv('APICK_JOB_ID')) . '/quality');
curl_setopt_array($curl, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_TIMEOUT => 120,
]);
$body = curl_exec($curl);
if ($body === false) { throw new RuntimeException(curl_error($curl)); }
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
if ($status >= 400) { throw new RuntimeException($body); }
$result = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
print_r($result);

```

## GET /rest/tts/jobs/:job_id/candidates/:candidate_id/audio 응답 필드

## 결과 받기: GET /rest/tts/jobs/:job_id/candidates/:candidate_id/audio



### 입력



### 응답 명세

```json

{
  "type": "string",
  "format": "binary"
}

```

### curl

```curl

curl --fail-with-body --request GET "https://apick.app/rest/tts/jobs/${APICK_JOB_ID}/candidates/${APICK_CANDIDATE_ID}/audio" \
  --header "Authorization: Bearer $APICK_API_KEY" \
  --dump-header response.headers --output result.wav
# response.headers의 Content-Type을 확인한 뒤 파일을 사용하세요.

```

### Node.js (서버 ESM)

```javascript

const response = await fetch(`https://apick.app/rest/tts/jobs/${encodeURIComponent(process.env.APICK_JOB_ID)}/candidates/${encodeURIComponent(process.env.APICK_CANDIDATE_ID)}/audio`, {
  method: "GET",
  headers: { Authorization: "Bearer " + process.env.APICK_API_KEY },
  signal: AbortSignal.timeout(120_000),
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
if ((response.headers.get("content-type") || "").includes("json")) {
  throw new Error(JSON.stringify(await response.json()));
}
const { writeFile } = await import("node:fs/promises");
await writeFile("result.wav", new Uint8Array(await response.arrayBuffer()));

```

### python

```python

import os
import requests
from urllib.parse import quote
response = requests.request("GET", "https://apick.app" + "/rest/tts/jobs/{job_id}/candidates/{candidate_id}/audio".format(job_id=quote(os.environ["APICK_JOB_ID"], safe=""), candidate_id=quote(os.environ["APICK_CANDIDATE_ID"], safe="")),
    headers={"Authorization": "Bearer " + os.environ["APICK_API_KEY"]},
    timeout=(10, 120), stream=True)
response.raise_for_status()
if "json" in response.headers.get("Content-Type", ""):
    raise RuntimeError(response.json())
with open("result.wav", "wb") as output:
    for chunk in response.iter_content(65536):
        output.write(chunk)

```

### php

```php

<?php
$headers = ["Authorization: Bearer " . getenv("APICK_API_KEY")];
$curl = curl_init('https://apick.app/rest/tts/jobs/' . rawurlencode(getenv('APICK_JOB_ID')) . '/candidates/' . rawurlencode(getenv('APICK_CANDIDATE_ID')) . '/audio');
curl_setopt_array($curl, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_TIMEOUT => 120,
]);
$body = curl_exec($curl);
if ($body === false) { throw new RuntimeException(curl_error($curl)); }
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
$type = curl_getinfo($curl, CURLINFO_CONTENT_TYPE) ?: "";
curl_close($curl);
if ($status >= 400) { throw new RuntimeException($body); }
if (strpos($type, "json") !== false) { throw new RuntimeException($body); }
file_put_contents('result.wav', $body);

```

## POST /rest/tts/jobs/:job_id/retry 응답 필드

- `data` (object): 아래 하위 항목을 확인하세요.

- `data.job_id` (string): 접수 응답에서 받은 작업 ID. 같은 계정의 작업에만 접근할 수 있습니다.

- `data.status` (string): 작업 진행 상태. 완료 여부와 다운로드 가능 여부를 함께 확인합니다. 허용값: waiting, processing, completed, cancelled, failed

- `data.resume_revision` (integer): 재시도 회차. 0은 최초 생성이며 재시도할 때 증가합니다.

- `data.operation_revision` (integer): 이번 재시도 요청이 시작한 회차. 현재 최대 회차와 다를 수 있습니다.

- `api` (object): 호출 메타데이터.

- `api.success` (boolean): API 공통 처리 여부. HTTP 상태·업무 결과와 함께 확인합니다.

- `api.cost` (number): 이번 호출에서 차감한 포인트. 무료 조회·재전송은 0.

- `api.pl_id` (integer): 과금 기록 ID. 과금 기록이 있을 때만 포함합니다.

## 작업 재시도: POST /rest/tts/jobs/:job_id/retry



### 입력

- `idempotency_key` (string, 필수): 동일 재개 요청에 재사용하는 키

- `utterance_ids[0]` (string, 필수): 재시도 API에서 다시 생성할 발화 ID. 예: u001. 접수 API에는 보내지 않습니다.



### 응답 명세

```json

{
  "type": "object",
  "description": "공개 JSON 응답.",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "job_id": {
          "type": "string",
          "description": "접수 응답에서 받은 작업 ID. 같은 계정의 작업에만 접근할 수 있습니다."
        },
        "status": {
          "type": "string",
          "description": "작업 진행 상태. 완료 여부와 다운로드 가능 여부를 함께 확인합니다.",
          "enum": [
            "waiting",
            "processing",
            "completed",
            "cancelled",
            "failed"
          ]
        },
        "resume_revision": {
          "type": "integer",
          "description": "재시도 회차. 0은 최초 생성이며 재시도할 때 증가합니다.",
          "minimum": 0
        },
        "operation_revision": {
          "type": "integer",
          "description": "이번 재시도 요청이 시작한 회차. 현재 최대 회차와 다를 수 있습니다."
        }
      }
    },
    "api": {
      "type": "object",
      "description": "호출 메타데이터.",
      "properties": {
        "success": {
          "type": "boolean",
          "description": "API 공통 처리 여부. HTTP 상태·업무 결과와 함께 확인합니다."
        },
        "cost": {
          "type": "number",
          "description": "이번 호출에서 차감한 포인트. 무료 조회·재전송은 0."
        },
        "pl_id": {
          "type": "integer",
          "description": "과금 기록 ID. 과금 기록이 있을 때만 포함합니다."
        }
      }
    }
  }
}

```

### 정적 응답 예시

```json

{
  "data": {
    "job_id": "7f7e43f578cd459db04696416435c789",
    "status": "cancelled"
  },
  "api": {
    "success": true,
    "cost": 0
  }
}

```

### curl

```curl

curl --fail-with-body --request POST "https://apick.app/rest/tts/jobs/${APICK_JOB_ID}/retry" \
  --header "Authorization: Bearer $APICK_API_KEY" \
  --form-string 'idempotency_key=apick-example-20260921-01' \
  --form-string 'utterance_ids[0]=u001'

```

### Node.js (서버 ESM)

```javascript

const form = new FormData();
form.append("idempotency_key", "apick-example-20260921-01");
form.append("utterance_ids[0]", "u001");
const response = await fetch(`https://apick.app/rest/tts/jobs/${encodeURIComponent(process.env.APICK_JOB_ID)}/retry`, {
  method: "POST",
  headers: { Authorization: "Bearer " + process.env.APICK_API_KEY },
  body: form,
  signal: AbortSignal.timeout(120_000),
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
const result = await response.json();
console.log(result);

```

### python

```python

import os
import requests
from urllib.parse import quote
parts = [
    ("idempotency_key", (None, "apick-example-20260921-01")),
    ("utterance_ids[0]", (None, "u001")),
]
response = requests.request("POST", "https://apick.app" + "/rest/tts/jobs/{job_id}/retry".format(job_id=quote(os.environ["APICK_JOB_ID"], safe="")),
    headers={"Authorization": "Bearer " + os.environ["APICK_API_KEY"]},
    files=parts,
    timeout=(10, 120))
response.raise_for_status()
result = response.json()
print(result)

```

### php

```php

<?php
$headers = ["Authorization: Bearer " . getenv("APICK_API_KEY")];
$form = [
    'idempotency_key' => 'apick-example-20260921-01',
    'utterance_ids[0]' => 'u001',
];
$curl = curl_init('https://apick.app/rest/tts/jobs/' . rawurlencode(getenv('APICK_JOB_ID')) . '/retry');
curl_setopt_array($curl, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_POSTFIELDS => $form,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_TIMEOUT => 120,
]);
$body = curl_exec($curl);
if ($body === false) { throw new RuntimeException(curl_error($curl)); }
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
if ($status >= 400) { throw new RuntimeException($body); }
$result = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
print_r($result);

```

## 코드·오류

- TTS_REQUEST_INVALID (400·413·422): 목소리·문자 수·발화 구조·입력 크기를 확인하세요.

- TTS_AUTH_FAILED (401): 인증키를 확인하세요.

- TTS_ACCESS_DISABLED (403): 계정의 API 이용 제한 상태를 확인하세요.

- TTS_PAYMENT_REQUIRED (403): 최초 결제를 완료한 뒤 이용하세요.

- TTS_INSUFFICIENT_POINTS (402): 필요한 포인트를 충전하세요.

- TTS_NOT_FOUND (404): 작업·후보 ID와 소유 계정을 확인하세요.

- TTS_JOB_CONFLICT (409): 작업 상태·재시도 회차·같은 멱등 키의 요청 내용을 확인하세요.

- TTS_GENERATION_FAILED (409): 실패 상태를 확인하고 입력을 수정하거나 새 작업을 접수하세요.

- TTS_RESULT_UNAVAILABLE (410): 파일이 이미 다운로드됐거나 보관 기간이 만료됐습니다.

- TTS_TEMPORARILY_UNAVAILABLE (429·503): Retry-After 이후 다시 시도하세요. 재시도 요청에는 같은 멱등 키를 사용하세요.

- TTS_BILLING_FAILED (424): 결제를 완료하지 못했습니다. Retry-After 이후 다시 시도하세요.

- TTS_INTERNAL_ERROR (500): 잠시 후 다시 시도하세요.

## 상세 기능·요금

지원 API 요약 음성 작업은 접수한 뒤 상태를 조회하고, 완료되면 MP3와 ASS 자막을 내려받는 흐름입니다. 두 파일은 완료 후 24시간 이내 각각 한 번 내려받을 수 있으며, 취소는 waiting 또는 processing 상태에서 사용할 수 있습니다. MethodAPI entry point기능성공 결과 POST/rest/tts/jobs음성 작업 접수HTTP 202와 job_id GET/rest/tts/jobs/{job_id}작업 상태 조회HTTP 200과 현재 상태 POST/rest/tts/jobs/{job_id}/cancel진행 전·진행 중 작업 취소HTTP 200과 cancelled GET/rest/tts/jobs/{job_id}/resultMP3 음성 다운로드<job_id>.mp3 GET/rest/tts/jobs/{job_id}/subtitlesASS 자막 다운로드<job_id>.ass GET/rest/tts/jobs/{job_id}/quality발화별 품질 이력검수·속도·반복·후보 목록 GET/rest/tts/jobs/{job_id}/candidates/{candidate_id}/audio후보 WAV 재생HTTP 200 또는 Range 206 POST/rest/tts/jobs/{job_id}/retry실패 발화 재개HTTP 202, 추가 과금 없음 1. 작업 접수 구분내용 API entry point 소개POST /rest/tts/jobs 기능 소개목소리와 대본을 전달해 새로운 음성 합성 작업을 접수합니다. 호출 방식Authorization: Bearer와 form-data 본문을 전송합니다. 간단 모드의 text 또는 발화 모드의 utterances 중 하나를 사용합니다. 호출 결과접수 성공 시 HTTP 202를 반환하고 즉시 과금합니다. 이후 취소해도 과금액은 환불되지 않습니다. 응답 결과job_id, waiting 상태, 목소리 ID, 과금 기준 문자 수를 반환합니다. 호출 방식 form-data 전체 예제 보기 응답 결과 { "data": { "job_id": "7f7e43f578cd459db04696416435c789", "status": "waiting", "voice_id": "v2_ann_m_30s_01", "character_count": 27 }, "api": { "success": true, "cost": 10, "pl_id": 12345 } } 품질 검사와 재개 전체 17종 화자에 같은 검사를 적용합니다. NFC·공백 정규화 후 공백 포함 20자 이상에서 초당 6자 미만이고 예상 시간(글자 수÷8.5)의 1.4배를 넘으면 실패합니다. 반복·참조 문장 혼입과 필수 전사 미확인도 완료로 승인되지 않습니다. 상태의 quality에는 phase, accepted_utterances, failed_utterances, utterances, candidates, final_quality가 포함됩니다. 발화의 speech_rate는 글자 수·길이·cps를, repeat와 reference_intrusion은 검사 결과를 나타냅니다. 미측정 시간은 null입니다. 후보는 실행 중 보존하며 종료 후 72시간 동안 작업 소유자만 조회할 수 있습니다. 후보 조회는 최종 MP3·ASS의 1회 다운로드를 소비하지 않습니다. 검수 이력의 candidate_id를 음원 경로에 넣으세요. 재개 요청은 {"utterance_ids":["u001"],"idempotency_key":"repair-request-001"} 형식입니다. ID는 접수 배열 순서대로 u001부터 시작합니다. 같은 요청을 다시 보낼 때는 같은 키를 사용하고, 같은 키의 발화 목록을 변경하지 마세요. 응답의 resume_revision으로 회차를 구분합니다. 기술적 복구에는 추가 과금이 없고, 후보 예산을 소진한 발화는 실패로 남습니다. 3. 작업 취소 구분내용 API entry point 소개POST /rest/tts/jobs/{job_id}/cancel 기능 소개waiting 또는 processing 상태인 음성 작업을 취소합니다. 호출 방식접수 응답의 job_id를 URL에 넣고 Authorization: Bearer 헤더를 전송합니다. 요청 본문은 없습니다. 호출 결과취소 성공 시 HTTP 200을 반환합니다. 이미 종료된 작업은 TTS_JOB_CONFLICT로 거부됩니다. 응답 결과취소된 작업 ID와 cancelled 상태를 반환합니다. 접수 시 차감된 포인트는 환불되지 않습니다. 호출 방식 form-data 전체 예제 보기 응답 결과 { "data": { "job_id": "7f7e43f578cd459db04696416435c789", "status": "cancelled" }, "api": { "success": true, "cost": 0 } } 4. MP3 음성 다운로드 구분내용 API entry point 소개GET /rest/tts/jobs/{job_id}/result 기능 소개완료된 작업의 최종 음성을 MP3 파일로 내려받습니다. 호출 방식상태 응답의 result_available이 true일 때 호출하고 응답 본문을 파일로 저장합니다. 호출 결과HTTP 200과 audio/mpeg 파일을 반환합니다. 완료 후 24시간 안에 한 번만 내려받을 수 있습니다. 응답 결과<job_id>.mp3 파일이며 규격은 24kHz·mono·48kbps입니다. 호출 방식 form-data 전체 예제 보기 응답 결과 Content-Type: audio/mpeg Content-Disposition: attachment; filename="<job_id>.mp3" <job_id>.mp3 # 최종 음성 (24kHz · mono · 48kbps) 5. ASS 자막 다운로드 구분내용 API entry point 소개GET /rest/tts/jobs/{job_id}/subtitles 기능 소개완료된 작업의 발화 타이밍과 일치하는 ASS 자막을 내려받습니다. 호출 방식상태 응답의 subtitles_available이 true일 때 호출하고 응답 본문을 파일로 저장합니다. 호출 결과HTTP 200과 text/plain; charset=utf-8 파일을 반환합니다. MP3와 별도로 24시간 안에 한 번만 내려받을 수 있습니다. 응답 결과<job_id>.ass 파일이며 MP3 다운로드 여부와 독립적으로 제공됩니다. 호출 방식 form-data 전체 예제 보기 응답 결과 Content-Type: text/plain; charset=utf-8 Content-Disposition: attachment; filename="<job_id>.ass" <job_id>.ass # 최종 발화 타임라인과 일치하는 ASS 자막 요금 문자 수차감 포인트 1~100자10P 101~200자20P 201~300자30P 701~800자80P 공백·문장부호·줄바꿈을 포함한 유니코드 문자 수를 100자 단위로 올림해 100자당 10P를 차감합니다. 접수 성공 시 과금되며 이후 취소해도 환불되지 않습니다. 지원 목소리 같은 안내 문장으로 만든 샘플을 들어보고 콘텐츠 분위기에 맞는 목소리를 선택하세요. VOICE01 준호 · 남성 전문 내레이션 01v2_ann_m_30s_01 30대 남성 앵커형 전문 내레이션 음성입니다. 추천 콘텐츠뉴스·다큐멘터리 VOICE SAMPLE 오디오 재생을 지원하지 않는 브라우저입니다. VOICE02 태산 · 남성 전문 내레이션 02v2_ann_m_30s_02 30대 남성 앵커형 전문 내레이션 음성입니다. 추천 콘텐츠뉴스·사건 내레이션 VOICE SAMPLE 오디오 재생을 지원하지 않는 브라우저입니다. VOICE03 강우 · 남성 전문 내레이션 04v2_ann_m_30s_04 30대 남성 앵커형 전문 내레이션 음성입니다. 추천 콘텐츠뉴스·정보 내레이션 VOICE SAMPLE 오디오 재생을 지원하지 않는 브라우저입니다. VOICE04 상현 · 남성 전문 내레이션 05v2_ann_m_30s_05 30대 남성 앵커형 전문 내레이션 음성입니다. 추천 콘텐츠보고·다큐멘터리 VOICE SAMPLE 오디오 재생을 지원하지 않는 브라우저입니다. VOICE05 지윤 · 여성 전문 내레이션 01v2_ann_f_30s_01 30대 여성 앵커형 전문 내레이션 음성입니다. 추천 콘텐츠뉴스·정보 내레이션 VOICE SAMPLE 오디오 재생을 지원하지 않는 브라우저입니다. VOICE06 수빈 · 여성 전문 내레이션 02v2_ann_f_30s_02 30대 여성 앵커형 전문 내레이션 음성입니다. 추천 콘텐츠뉴스·다큐멘터리 VOICE SAMPLE 오디오 재생을 지원하지 않는 브라우저입니다. VOICE07 은채 · 여성 전문 내레이션 03v2_ann_f_30s_03 30대 여성 앵커형 전문 내레이션 음성입니다. 추천 콘텐츠정보·교양 내레이션 VOICE SAMPLE 오디오 재생을 지원하지 않는 브라우저입니다. VOICE08 다인 · 여성 전문 내레이션 04v2_ann_f_30s_04 30대 여성 앵커형 전문 내레이션 음성입니다. 추천 콘텐츠뉴스·정보 내레이션 VOICE SAMPLE 오디오 재생을 지원하지 않는 브라우저입니다. VOICE09 예린 · 여성 전문 내레이션 05v2_ann_f_30s_05 30대 여성 앵커형 전문 내레이션 음성입니다. 추천 콘텐츠교양·다큐멘터리 VOICE SAMPLE 오디오 재생을 지원하지 않는 브라우저입니다. VOICE10 하늘 · 청소년 내레이션v2_m_teen_01 청소년 연령대의 중립 내레이션 음성입니다. 추천 콘텐츠청소년·스토리 내레이션 VOICE SAMPLE 오디오 재생을 지원하지 않는 브라우저입니다. VOICE11 도윤 · 청년 남성 내레이션v2_m_young_01 20대 남성 연령대의 중립 내레이션 음성입니다. 추천 콘텐츠청년·콘텐츠 내레이션 VOICE SAMPLE 오디오 재생을 지원하지 않는 브라우저입니다. VOICE12 정한 · 중년 남성 내레이션v2_m_mid_01 40대 남성 연령대의 중립 내레이션 음성입니다. 추천 콘텐츠교양·다큐멘터리 VOICE SAMPLE 오디오 재생을 지원하지 않는 브라우저입니다. VOICE13 만복 · 장년 남성 내레이션v2_m_senior_01 60대 남성 연령대의 중립 내레이션 음성입니다. 추천 콘텐츠회고·다큐멘터리 VOICE SAMPLE 오디오 재생을 지원하지 않는 브라우저입니다. VOICE14 하람 · 청소년 여성 내레이션v2_f_teen_01 10대 여성 연령대의 중립 내레이션 음성입니다. 추천 콘텐츠청소년·스토리 내레이션 VOICE SAMPLE 오디오 재생을 지원하지 않는 브라우저입니다. VOICE15 서아 · 청년 여성 내레이션v2_f_young_01 20대 여성 연령대의 중립 내레이션 음성입니다. 추천 콘텐츠청년·콘텐츠 내레이션 VOICE SAMPLE 오디오 재생을 지원하지 않는 브라우저입니다. VOICE16 정순 · 장년 여성 내레이션v2_f_senior_01 60대 여성 연령대의 중립 내레이션 음성입니다. 추천 콘텐츠회고·다큐멘터리 VOICE SAMPLE 오디오 재생을 지원하지 않는 브라우저입니다. 대본 작성 가이드 발화 모드에서는 본문·문단·발화 경계의 쉼만 조절합니다. 배열의 모든 text 글자 수는 공백·문장부호·줄바꿈을 포함해 합산하며, 한 요청의 합계가 800자를 넘으면 거부됩니다. 1. 대본 본문 마침표·물음표·느낌표·말줄임표·쉼표로 억양과 짧은 쉼이 반영되며, 문장 분리는 자동 문장 쉼이 적용됩니다. --form-string 'text=정말 아무도 몰랐던 걸까요?' --form-string 'text=하지만… 기록은 그 사실을 분명히 말하고 있었습니다.' 2. 배열 글자 수 계산 JSON 키와 옵션값은 800자 계산에 포함하지 않습니다. 각 항목이 아니라 모든 text의 합계가 800자 이하여야 합니다. --form-string 'voice_id=v2_ann_m_30s_01' \ --form-string 'utterances[0][text]=첫 번째 문장입니다.' \ --form-string 'utterances[1][text]=두 번째 문장입니다.' 예를 들어 500자와 300자는 합계 800자로 허용되고, 500자와 301자는 합계 801자로 거부됩니다. 3. 문단 그룹 paragraph_id가 같으면 같은 문단 흐름으로 처리되고, 값이 바뀌면 문단 전환 경계로 처리됩니다. [ { "paragraph_id": "p001", "text": "조사는 계속됐습니다." }, { "paragraph_id": "p002", "text": "하지만 결정적인 증거는 나오지 않았습니다." } ] 4. 발화 뒤 쉼 (pause_after) 생략하면 앞뒤 발화의 문맥(문장 이어짐, 대화 전환, 문단·주제 전환 등)에 맞춰 자동으로 지정합니다. 직접 지정한 값은 그대로 사용합니다. 값적용 none쉼 없음 micro약 150ms normal약 450ms strong약 900ms paragraph약 1,000ms [ { "pause_after": "normal", "text": "그 기록은 마지막으로 확인된 자료였습니다." }, { "text": "그리고 그날 이후, 모든 흔적이 사라졌습니다." } ] 5. 발화 시작 전 쉼 (pause_before_ms) 다음 발화 앞에 직접 쉼을 지정합니다. 허용 범위는 0~10000밀리초 정수입니다. [ { "text": "첫 번째 기록입니다." }, { "pause_before_ms": 800, "text": "두 번째 기록은 전혀 다른 내용을 담고 있었습니다." } ] 6. 자동 내부 운율 별도 옵션 없이도 일부 한국어 문장 구조를 분석해 합성용 문장에 자연스러운 쉼표를 추가합니다. 표시용 원문은 그대로 유지됩니다. --form-string 'text=시간이 늦었으니까 서둘러야 합니다.' 합성용 내부 예: 시간이 늦었으니까, 서둘러야 합니다. 7. 숫자·날짜·단위 숫자와 날짜는 발음 정규화 규칙에 따라 처리되므로 오탈자 없이 작성합니다. --form-string 'text=2003년 7월 14일, 오전 2시 30분에 신고가 접수됐습니다.' 권장 형식 --form-string 'voice_id=v2_ann_m_30s_01' \ --form-string 'utterances[0][paragraph_id]=p004' \ --form-string 'utterances[0][pause_after]=normal' \ --form-string 'utterances[0][text]=그날 밤, 마을에는 이상할 만큼 고요한 정적이 내려앉았습니다. 하지만 한 집의 불빛만은 꺼지지 않았습니다.'

## 상세 요청

입력 상세 Header 이름필수설명 AuthorizationOBearer 인증키 Content-TypeOmultipart/form-data; boundary는 클라이언트가 자동 설정합니다. utterances[]에는 위 네 필드만 사용할 수 있습니다. 발화 식별자·화자·발화 종류·감정값은 서버가 생성·고정하므로 요청 필드가 아닙니다. 자유 감정 지시문, performance, SSML, 임의 속도·음높이, 문장 중간 무음 지시는 지원하지 않습니다.

## 상세 코드·정책

2. 작업 상태 조회 구분내용 API entry point 소개GET /rest/tts/jobs/{job_id} 기능 소개접수한 작업의 현재 상태와 음성·자막 다운로드 가능 여부를 확인합니다. 호출 방식접수 응답의 job_id를 URL에 넣고 Authorization: Bearer 헤더를 전송합니다. 완료 전에는 2~5초 간격 조회를 권장합니다. 호출 결과HTTP 200과 waiting, processing, completed, cancelled, failed 중 하나를 반환합니다. 응답 결과result_available은 MP3, subtitles_available은 ASS 자막의 다운로드 가능 여부입니다. 호출 방식 form-data 전체 예제 보기 응답 결과 { "data": { "job_id": "7f7e43f578cd459db04696416435c789", "status": "completed", "result_available": true, "subtitles_available": true }, "api": { "success": true, "cost": 0 } } 응답과 상태 status의미 waiting접수되어 처리 시작을 기다리는 중 processing음성 생성 중 completed완료, MP3·ASS 자막 다운로드 가능 cancelled취소 완료 failed생성 실패 처리 설비나 서버 구성 정보는 API 계약에 포함되지 않습니다. 상태 조회는 2~5초 간격을 권장합니다. 상태 오류 APICK이 입력·인증·소유권·저장된 작업 상태로 판정할 수 있는 요청은 음성 서비스 호출 전에 차단합니다. 오류 응답에는 아래 공개 코드와 간단한 안내만 포함하며, 상류 원문·세부 단계·파일 경로·자원 및 모델 상태·진단 정보는 공개하지 않습니다. 코드HTTP원인해결책 TTS_REQUEST_INVALID400·413·422요청 내용이 올바르지 않음입력 형식과 지원 조건 확인 TTS_AUTH_FAILED401인증 실패인증키 확인 TTS_NOT_FOUND404작업을 찾을 수 없음접수 응답의 작업 ID 확인 TTS_JOB_CONFLICT409현재 상태에서 요청을 처리할 수 없음최신 상태 확인 후 다시 요청 TTS_TEMPORARILY_UNAVAILABLE429·503일시적으로 서비스 이용 불가Retry-After 이후 재시도 TTS_GENERATION_FAILED409음성 또는 자막 생성 실패입력 확인 후 새 작업 접수 TTS_RESULT_UNAVAILABLE410해당 파일의 1회 다운로드 완료 또는 24시간 만료보관본이 없으면 새 작업 접수 TTS_INTERNAL_ERROR500분류되지 않은 서비스 오류잠시 후 재시도 정상 취소는 오류가 아니라 HTTP 200과 cancelled 상태를 반환합니다.

## 상세 예제

전체 호출 예시 form-data 전체 예제 보기
