# 발신 전화 생성 (/docs/api/calls/createCall)
**POST /v1/accounts/{accountId}/calls**
```json
{
  "operationId": "createCall",
  "summary": "발신 전화 생성",
  "description": "아웃바운드 전화를 발신합니다. From 번호는 계정에 등록된 번호여야 합니다.\n\n**전화 발신**: To에 전화번호를 입력하면 일반 전화로 발신됩니다.\n- 예: `\"To\": \"01012345678\"`\n\n**매니지드 에이전트**: `AgentId`를 지정하면 콘솔에서 만든 AI 에이전트가 통화를 처리합니다.\n이때 `CallContext`로 **이번 통화에만** 적용되는 요구사항(`Instruction`)과 참조 데이터\n(`Variables`)를 얹을 수 있습니다. 콘솔에 저장된 에이전트 설정은 바뀌지 않으므로 같은\n에이전트로 동시에 거는 다른 통화에는 영향이 없습니다. `AgentId` 모드 전용이라 다른\n모드와 함께 보내면 400으로 거절됩니다.\n\n**Agent SDK**: `Url`, `AgentId`, `CallFlowId`를 모두 생략하면 From 번호에 연결된\nAgent SDK로 통화가 연결됩니다. Agent가 연결되어 있지 않으면 409 에러를 반환합니다.\n\n`Url`, `AgentId`, `CallFlowId`는 서로 배타적입니다. `201 Created`는 발신 요청이\n큐에 들어갔다는 뜻이며 통화 연결 성공을 뜻하지 않습니다. 반환된 `callId`를\n`GET /v1/accounts/{accountId}/calls/{callId}`로 조회해 최종 상태를 확인하세요.\n\n**AI Completion 모드는 종료되었습니다.** AI 필드를 포함한 요청은 410으로 거절됩니다.\nUrl(VoiceML), AgentId, CallFlowId 또는 Agent SDK를 사용하세요.",
  "tags": [
    "Calls"
  ],
  "parameters": [
    {
      "name": "accountId",
      "in": "path",
      "required": true,
      "schema": {
        "type": "string"
      },
      "description": "계정 ID",
      "example": "AC1a2b3c4d"
    }
  ],
  "requestBody": {
    "required": true,
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "required": [
            "To",
            "From"
          ],
          "properties": {
            "To": {
              "type": "string",
              "description": "수신 전화번호",
              "example": "01012345678"
            },
            "From": {
              "type": "string",
              "example": "07052358010",
              "description": "발신 번호 (계정에 등록된 번호). `CallToken`을 보낼 때는 걸려온 통화의 발신자 번호를 넣습니다 — 받는 쪽에 표시할 번호입니다.\n"
            },
            "CallToken": {
              "type": "string",
              "example": "ctk_Q2FsbFRva2VuRXhhbXBsZTAxMjM0NTY3",
              "description": "걸려온 통화의 웹훅에서 받은 값. 그 통화의 발신자 번호를 From에 넣으면 받는 쪽에 그 번호가 표시됩니다. 발신번호를 바꿔 새로 거는 것이 아니라 걸려온 전화를 넘기는 착신전환입니다. `Url`과 함께만 사용합니다. [CallToken](/docs/call-token)\n"
            },
            "Url": {
              "type": "string",
              "example": "https://my-app.com/voiceml",
              "description": "통화 연결 시 VoiceML을 반환할 URL. AgentId·CallFlowId와 배타."
            },
            "AgentId": {
              "type": "string",
              "example": "cmagent123",
              "description": "콘솔에서 만든 매니지드 에이전트 ID. Url·CallFlowId와 배타."
            },
            "CallContext": {
              "type": "object",
              "additionalProperties": false,
              "description": "AgentId 에이전트의 이번 통화에만 적용되는 컨텍스트. `Instruction`·`Variables` 중 하나는 있어야 합니다(둘 다 비면 400).\n",
              "minProperties": 1,
              "properties": {
                "Instruction": {
                  "type": "string",
                  "maxLength": 4000,
                  "description": "이번 통화에서 수행할 실행 요구사항. 데이터만 넘길 때는 생략합니다."
                },
                "Variables": {
                  "type": "object",
                  "maxProperties": 50,
                  "additionalProperties": {
                    "oneOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "number"
                      },
                      {
                        "type": "boolean"
                      }
                    ]
                  },
                  "description": "요구사항에서 참조할 통화별 구조화 데이터."
                }
              }
            },
            "CallFlowId": {
              "type": "string",
              "example": "cmryw3ycm000001s6on0kp9a8",
              "description": "콜 플로우(결정적 ARS) ID. 지정하면 그 플로우가 통화를 진행합니다. Url·AgentId와 동시에 사용할 수 없습니다. ID는 `GET /v1/accounts/{accountId}/call-flows`로 조회합니다.\n"
            },
            "Variables": {
              "type": "object",
              "additionalProperties": {
                "oneOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "number"
                  },
                  {
                    "type": "boolean"
                  }
                ]
              },
              "example": {
                "name": "홍길동",
                "orderId": "A-1234"
              },
              "description": "콜 플로우 시작 변수. 멘트·URL·본문의 `{{이름}}`이 이 값으로 치환됩니다. CallFlowId와 함께일 때만 사용할 수 있습니다(단독 지정 시 400).\n\n값은 문자열로 정규화되며 숫자·불리언도 허용합니다. 이름은 영문/숫자/밑줄이어야 하고 숫자로 시작할 수 없습니다. 최대 50개, 전체 8KB. `caller`·`callee`·`recording_url`·`recording_duration`·`http_status`·`dial_status`는 통화 중 자동으로 채워지는 예약 변수라 지정할 수 없습니다(400).\n\n지정하지 않은 `{{변수}}`는 빈 문자열로 치환됩니다.\n"
            },
            "Timeout": {
              "type": "integer",
              "example": 60,
              "description": "벨 대기 시간 (초). 상대가 받지 않으면 이 시간 뒤 `no-answer` 로 종료됩니다. 미지정이거나 유효하지 않으면 30초, 600초를 넘으면 600초로 제한됩니다.\n"
            },
            "StatusCallback": {
              "type": "string",
              "example": "https://my-app.com/status",
              "description": "통화 상태 변경 시 콜백을 받을 URL"
            },
            "StatusCallbackEvent": {
              "type": "string",
              "example": "initiated ringing answered completed transfer",
              "description": "수신할 상태 이벤트 목록(공백 구분). 미지정 시 `initiated ringing answered completed` 가 적용됩니다. `transfer`(호전환 진행 상황)는 기본에 포함되지 않으므로 받으려면 직접 나열하세요. 전체 목록은 [Webhooks](/webhooks).\n"
            },
            "MachineDetection": {
              "type": "string",
              "enum": [
                "Enable",
                "Hangup"
              ],
              "description": "자동응답기/음성사서함 감지(AMD). Enable=감지 후 AnsweredBy 통보(통화 계속), Hangup=음성사서함이면 자동 종료. 미설정 시 비활성(기본).\n"
            }
          }
        }
      },
      "application/x-www-form-urlencoded": {
        "schema": {
          "type": "object",
          "required": [
            "To",
            "From"
          ],
          "properties": {
            "To": {
              "type": "string",
              "description": "수신 번호"
            },
            "From": {
              "type": "string",
              "description": "발신 번호 (계정에 등록된 번호). `CallToken`을 보낼 때는 걸려온 통화의 발신자 번호를 넣습니다 — 받는 쪽에 표시할 번호입니다.\n"
            },
            "CallToken": {
              "type": "string",
              "description": "걸려온 통화의 웹훅에서 받은 값. `Url`과 함께만 사용합니다."
            },
            "Url": {
              "type": "string",
              "description": "통화 연결 시 VoiceML을 반환할 URL. AgentId·CallFlowId와 배타."
            },
            "AgentId": {
              "type": "string",
              "description": "콘솔에서 만든 매니지드 에이전트 ID. Url·CallFlowId와 배타."
            },
            "CallContext": {
              "type": "string",
              "example": "{\"Instruction\":\"예약 가능 여부를 확인한다\",\"Variables\":{\"preferredTime\":\"15:00\"}}",
              "description": "AgentId 에이전트의 이번 통화에만 적용되는 컨텍스트 JSON 객체 문자열."
            },
            "CallFlowId": {
              "type": "string",
              "description": "콜 플로우(결정적 ARS) ID. Url·AgentId와 배타."
            },
            "Variables": {
              "type": "string",
              "example": "{\"name\":\"홍길동\",\"orderId\":\"A-1234\"}",
              "description": "콜 플로우 시작 변수. form 인코딩에서는 **JSON 객체 문자열**로 보냅니다 (JSON 본문에서는 객체 그대로). 규칙은 JSON 스키마의 Variables와 같습니다.\n"
            },
            "Timeout": {
              "type": "integer",
              "description": "벨 대기 시간 (초). 미지정이거나 유효하지 않으면 30초, 600초를 넘으면 600초로 제한.\n"
            },
            "StatusCallback": {
              "type": "string",
              "description": "통화 상태 변경 시 콜백을 받을 URL"
            },
            "StatusCallbackEvent": {
              "type": "string",
              "description": "수신할 상태 이벤트 목록 (공백 구분)"
            },
            "MachineDetection": {
              "type": "string",
              "enum": [
                "Enable",
                "Hangup"
              ],
              "description": "자동응답기/음성사서함 감지(AMD). Enable=감지 후 AnsweredBy 통보(통화 계속), Hangup=음성사서함이면 자동 종료. 미설정 시 비활성(기본).\n"
            }
          }
        }
      }
    }
  },
  "responses": {
    "201": {
      "description": "발신 요청이 큐에 등록됨. 실제 연결 여부는 반환된 callId를 조회해 확인합니다.",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "callId": {
                "type": "string",
                "example": "CAabcdef1234567890"
              },
              "status": {
                "type": "string",
                "enum": [
                  "queued",
                  "ringing",
                  "in-progress",
                  "completed",
                  "failed",
                  "busy",
                  "no-answer",
                  "canceled",
                  "rejected"
                ],
                "description": "통화 상태. 진행 중: queued(발신 대기) / ringing(벨) / in-progress(통화 중).\n종료 상태(실제 종료 사유): completed(응답 후 정상 종료) / no-answer(벨은 울렸으나 무응답,\nTimeout 초과로 발신 취소) / busy(통화중) / rejected(수신 거절) / canceled(응답 전 발신 측 취소) /\nfailed(시스템·망 오류). completed 만이 통화가 실제로 연결됐음을 의미합니다.\n"
              },
              "to": {
                "type": "string",
                "example": "01012345678"
              },
              "from": {
                "type": "string",
                "example": "07052358010"
              },
              "direction": {
                "type": "string",
                "enum": [
                  "outbound",
                  "inbound"
                ]
              },
              "duration": {
                "type": "integer",
                "nullable": true,
                "description": "통화 시간 (초)",
                "example": 30
              },
              "accountId": {
                "type": "string",
                "example": "AC1a2b3c4d"
              },
              "answeredBy": {
                "type": "string",
                "nullable": true,
                "enum": [
                  "human",
                  "machine",
                  "unknown",
                  null
                ],
                "description": "AMD(MachineDetection) 결과. MachineDetection 을 켠 발신 통화에만 값이 있으며,\n사람 응답=human, 자동응답기/음성사서함=machine, 판정 불가=unknown. 미사용 시 null.\n"
              },
              "forwardedFrom": {
                "type": "string",
                "nullable": true,
                "description": "착신전환으로 들어온 수신 통화에서 발신자가 원래 건 번호. `to` 는 실제로 받은 번호입니다.\n발신 통화와 직접 걸려온 수신 통화, 이 필드가 생기기 전의 수신 통화는 null.\n"
              },
              "callerIdRestricted": {
                "type": "boolean",
                "nullable": true,
                "description": "수신 통화에서 발신자가 번호 표시제한(`*23#` 등)을 걸고 건 통화면 true, 아니면 false.\n번호는 `from` 에 그대로 전달됩니다. 통신사가 표시제한 여부를 보내지 않는 경로로 들어온\n통화는 false 로 올 수 있습니다. 발신 통화와 2026-09-29 이전의 수신 통화는 null.\n",
                "example": false
              },
              "recordingUrl": {
                "type": "string",
                "nullable": true,
                "description": "녹음 다운로드 경로 (녹음이 있는 통화만)",
                "example": "/v1/accounts/AC1a2b3c4d/recordings/CAabcdef1234567890"
              },
              "hangupCause": {
                "type": "string",
                "nullable": true,
                "description": "통화 종료 사유. `status` 가 왜 그렇게 끝났는지를 구분합니다. 종료 전이거나 사유\n미상이면 null.\n\n네 갈래로 나뉩니다 — 번호 자체가 문제라 재시도해도 소용없는 것(`invalid_number` 등),\n일시적이라 재시도 가치가 있는 것(`no_answer`·`user_busy` 등), 번호가 아니라 **계정**\n문제인 것(`concurrency_limit_exceeded`·`subscription_inactive` 등), 통화 처리 오류\n(`app_error`·`call_stuck`). `app_error` 에는 웹훅·VoiceML 응답 실패가 포함됩니다.\n\n고객 설정이 받지 않고 거절한 수신 통화는 따로 갈립니다 — 수신 통화 차단 목록에 있는 번호\n(`caller_blocked`), 번호 표시제한 통화 거절 설정(`caller_id_restricted_rejected`). 둘 다\n`status=rejected` 이며 재시도 대상이 아닙니다.\n\n**종료 사유로 통화를 필터링하려면 [Calls API](/api-reference/claw-ops-api/calls/list-calls)를 참고하세요.**\n여기 값을 나열하지 않는 이유: 사유가 늘 때마다 spec·문서·대시보드가 각각 갱신돼야 하는데\n한 곳만 빠지면 조용히 어긋난다(실제로 그렇게 어긋난 적이 있다).\n",
                "example": "invalid_number"
              },
              "hangupCauseQ850": {
                "type": "integer",
                "nullable": true,
                "description": "통신망 Q.850 cause code. 1·5·28=결번, 16=정상해제, 17=통화중, 18/19/20=무응답,\n21=거절, 38=망장애. 사유 미상이면 null.\n",
                "example": 1
              },
              "sipResponseCode": {
                "type": "integer",
                "nullable": true,
                "description": "종료를 유발한 SIP 응답코드 (404=없는 번호, 486=통화중, 500=망 오류 등). 수신 통화를 받지 않고 거절했으면 한국AI통신이 보낸 응답(403=거절, 486=통화중)입니다. 응답코드 없이 끝났으면 null.",
                "example": 404
              },
              "hangupSource": {
                "type": "string",
                "nullable": true,
                "enum": [
                  "carrier",
                  "callee",
                  "caller",
                  "app",
                  "system",
                  null
                ],
                "description": "종료 책임 주체. carrier(통신망) / callee(수신 측) / caller(발신 측) /\napp·system(한국AI통신 측 — 이 경우 재시도를 권장합니다). 통화 후 정상 종료에서는\n먼저 끊은 쪽의 역할입니다: 착신 통화에서 상대가 끊으면 caller, 여러분의 앱이\n끊으면 callee(발신 통화는 그 반대). 판정하지 못하면 null.\n",
                "example": "carrier"
              },
              "transferTo": {
                "type": "string",
                "nullable": true,
                "description": "전환 대상 번호. **읽기 전용** — 값을 지정하는 요청 필드는 없고 실제로 일어난 전환의\n결과가 기록됩니다. 전환이 없었으면 null.\n\n에이전트 전환과 SIP REFER 전환에서만 채워집니다(VoiceML `<Dial>` 은 제외 — 그 결과는\n`DialCallStatus` 로 받습니다).\n\n**전체 설명은 [통화 전환 결과](/call-transfers) 가 정본입니다.**\n",
                "example": "01012345678"
              },
              "transferStatus": {
                "type": "string",
                "nullable": true,
                "enum": [
                  "completed",
                  "failed",
                  "no-answer",
                  "busy",
                  "canceled",
                  null
                ],
                "description": "전환 결과(읽기 전용, 전환이 없었으면 null).\n\ncompleted(연결 후 정상 종료) / no-answer(대상이 받지 않음) / busy(통화중) /\ncanceled(연결 전에 취소·중단) / failed(그 외 실패 — 사유는 transferHangupCauseQ850 ·\ntransferSipResponseCode · transferReasonText).\n\n**종료된 전환의 결과만 담습니다.** 진행 중 상태는 transfers[].status 또는 Status Callback\n의 `transfer` 이벤트로 보세요.\n"
              },
              "transferDuration": {
                "type": "integer",
                "nullable": true,
                "description": "전환 통화 시간(초) — 대상이 받은 시점부터 그 전환 leg 가 끝날 때까지의 **관측값**입니다.\n연결되지 못한 전환은 null.\n\n⚠️ 과금 초가 아닙니다. 과금 대상 초는 transfers[].billableDuration 입니다.\n",
                "example": 60
              },
              "transferHangupCauseQ850": {
                "type": "integer",
                "nullable": true,
                "description": "전환 leg 의 통신망 Q.850 cause (예: 16=정상해제, 17=통화중, 19=무응답, 21=거절,\n38=망장애). 통신망이 SIP 5xx 로 보낸 실패의 실제 사유로 교정된 값. 사유 미상이면 null.\n",
                "example": 16
              },
              "transferSipResponseCode": {
                "type": "integer",
                "nullable": true,
                "description": "전환 leg 의 실제 SIP 응답코드 (예 500). 사유 미상이면 null.",
                "example": 500
              },
              "transferReasonText": {
                "type": "string",
                "nullable": true,
                "description": "전환 실패 원본 진단 텍스트. 사유 미상이면 null.",
                "example": "CS_NORMAL_RELEASE"
              },
              "transfers": {
                "type": "array",
                "description": "전환 leg 정본 체인(sequence 순). 다단계/재시도 전환의 전체 이력을 제공한다. **단건 조회에만\n포함되며(리스트 응답엔 생략)**, 전환이 없었던 통화는 빈 배열.\n\n위 transfer* 단일 필드는 이 체인에서 파생한 하위호환용 **대표 leg** 다 — 종료된 leg 중\ncompleted 우선, 동률이면 sequence 최대. 전체 시도는 이 배열로 본다.\n",
                "items": {
                  "type": "object",
                  "properties": {
                    "sequence": {
                      "type": "integer",
                      "description": "통화 내 전환 순번(1부터)"
                    },
                    "to": {
                      "type": "string",
                      "nullable": true,
                      "description": "전환 대상 번호 또는 SIP URI"
                    },
                    "mode": {
                      "type": "string",
                      "nullable": true,
                      "description": "blind | warm | refer | refer-attended"
                    },
                    "destinationType": {
                      "type": "string",
                      "nullable": true,
                      "description": "pstn(통신망 번호) | sip(SIP URI 직결). 2026-07-10 이전 전환은 null"
                    },
                    "status": {
                      "type": "string",
                      "nullable": true,
                      "description": "initiated|ringing|connected|completed|failed|no-answer|busy|canceled|interrupted"
                    },
                    "duration": {
                      "type": "integer",
                      "nullable": true,
                      "description": "connected→종료 초(관측용)"
                    },
                    "billable": {
                      "type": "boolean",
                      "description": "과금 대상 여부(통화당 대표 leg 1건만 true)"
                    },
                    "billableDuration": {
                      "type": "integer",
                      "nullable": true,
                      "description": "과금 대상 초(completed 대표 leg 만)"
                    },
                    "hangupCauseQ850": {
                      "type": "integer",
                      "nullable": true,
                      "description": "이 leg 의 통신망 Q.850 cause. 사유 미상이면 null"
                    },
                    "sipResponseCode": {
                      "type": "integer",
                      "nullable": true,
                      "description": "이 leg 의 SIP 응답코드. 사유 미상이면 null"
                    },
                    "reasonText": {
                      "type": "string",
                      "nullable": true,
                      "description": "통신망 원본 진단 텍스트(자유 형식 — 분기 조건으로 쓰지 말 것)"
                    },
                    "startedAt": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "description": "전환을 시작한 시각"
                    },
                    "answeredAt": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "description": "대상이 전화를 받은 시각. 응답까지 걸린 시간은 `answeredAt - startedAt` 이다. `connectedAt` 과 다르다 — 연결 전 안내(warm 전환의 whisper)가 있으면 그 안내가 끝난 뒤에 연결되고, 안내 도중 통화가 끝나면 `connectedAt` 은 null 이어도 이 값은 남는다. 받았는지 판정: 이 값이 있으면 받은 것이다 — status 가 failed·canceled·no-answer 여도 그렇다(연결 전 안내 도중 끝난 warm 전환). 이 값이 없으면 connectedAt 이 있거나 status 가 completed 일 때만 받은 것이다. ⚠️ 2026-10-13 이전 전환은 받았어도 null 이고, 안내 도중 끝난 경우는 구분되지 않는다.\n"
                    },
                    "connectedAt": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "description": "발신자와 대상이 연결된 시각. 연결 전 안내(whisper)가 있으면 안내가 끝난 뒤 시각이라 `answeredAt` 보다 늦다. 연결되지 못했으면 null. ⚠️ 2026-07-10 이전 전환은 연결됐어도 null 이므로 연결 여부 판정에 쓰지 말 것(status·duration 을 볼 것).\n"
                    },
                    "endedAt": {
                      "type": "string",
                      "format": "date-time",
                      "description": "이 leg 가 끝난 시각",
                      "nullable": true
                    },
                    "timeout": {
                      "type": "integer",
                      "nullable": true,
                      "description": "이 전환에 적용한 대기 한도(초). 대상이 이 시간 안에 받지 않으면 `no-answer` 로 끝난다. 2026-10-13 이전 전환은 null.\n"
                    }
                  }
                }
              },
              "dateCreated": {
                "type": "string",
                "format": "date-time"
              },
              "dateUpdated": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "통화 종료 시각"
              }
            }
          }
        }
      }
    },
    "400": {
      "description": "잘못된 요청. 다음 케이스에서 발생:\n  - 필수 파라미터 누락 (To, From)\n  - From 번호 미등록\n  - Url·AgentId·CallFlowId를 동시에 지정\n  - Variables를 CallFlowId 없이 지정하거나 이름·값·크기 규칙 위반\n  - Url 또는 StatusCallback에 내부/사설 주소 지정\n  - CallToken 오류 — `call_token_invalid`(유효하지 않음), `call_token_from_mismatch`(From이 걸려온 통화의 발신자 번호와 다름), `call_token_mode_unsupported`(Url 없이 사용)\n  - To 전화번호 정규화 실패. `code` 필드:\n    - `INVALID_PHONE_NUMBER`: 한국 번호 형식 아님 (포맷 오류, 자릿수 오류, +82-15XX 대표번호 E.164 등)\n    - `UNSUPPORTED_COUNTRY`: 국제 발신 미지원 (+82 외 국가코드)",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "error": {
                "type": "string",
                "description": "사람이 읽을 수 있는 에러 메시지"
              },
              "code": {
                "type": "string",
                "description": "기계 판독용 에러 코드. **분기는 이 값으로 하세요** — `error` 문구는 안내를 다듬으면서\n바뀔 수 있지만 코드는 계약입니다.\n\n같은 상태 코드라도 대응이 갈리는 경우가 있습니다. 예를 들어 발신의 `422` 는\n  - `recipient_blocked`: 수신거부 명단에 있는 번호입니다. 재시도하지 말고 명단에서\n    해제해야 발신됩니다.\n  - `quota_exceeded`: 플랜 한도를 넘었습니다. 다음 주기에 다시 발신됩니다.\n\n전화번호 정규화 관련:\n  - `INVALID_PHONE_NUMBER`: 전화번호 포맷 오류 (한국 번호 형식 아님)\n  - `UNSUPPORTED_COUNTRY`: 국제 발신 미지원 (+82 외 국가코드)",
                "example": "recipient_blocked"
              },
              "ip": {
                "type": "string",
                "description": "`overseas_ip_blocked` 일 때만 옵니다. 국외 IP 라고 판정한 요청 IP 입니다.\n해외 리전 클라우드 서버에서 호출한다면 이 값이 그 서버의 공인 IP 이며, 콘솔\n「국외 접속 예외」에서 예외를 신청할 때 이 고정 IP 를 적습니다.",
                "example": "52.79.213.41"
              },
              "processedAt": {
                "type": "string",
                "format": "date-time",
                "description": "문자 발송 요청을 거부한 서버가 오류 응답을 생성한 시각(UTC). 콘솔은 이 값을 한국 시각으로 표시합니다. 인증·요청 형식 검증 등 발송 서비스 진입 전 오류에는 없을 수 있습니다.",
                "example": "2026-10-21T04:10:34.303Z"
              },
              "blockers": {
                "type": "array",
                "description": "`certificate_not_eligible` 일 때만 옵니다. 발급할 수 없는 번호와 그 이유입니다.",
                "items": {
                  "type": "object",
                  "description": "번호 하나가 발급되지 않는(또는 안내가 필요한) 이유.\n\n| code | 뜻 | 발급 |\n|---|---|---|\n| `number_not_owned` | 이 계정이 보유한 번호가 아님(반납·재배정 포함) | 막힘 |\n| `number_not_carrier_issued` | 한국AI통신이 개통한 070·대표번호가 아님(모바일 게이트웨이, 타사 번호) | 막힘 |\n| `business_info_incomplete` | 사업자 계정인데(관리번호 제외) 상호·사업자등록번호·대표자명·사업장 주소 중 빈 칸 | 막힘 |\n| `identity_unverified` | 개인 계정 번호 또는 관리번호인데 그 번호에 본인확인 정보가 없음 | 막힘 |\n| `account_restricted` | 이용 제한 계정 | 막힘 |\n| `business_recheck_pending` | 사업자 계정인데 사업자 정보 재확인이 진행 중(통과 전) — 관리번호를 뺀 계정의 모든 번호 | 막힘 |\n| `holder_is_personal` | 개인 명의로 찍힌다는 안내 | 가능 |",
                  "properties": {
                    "number": {
                      "type": "string",
                      "description": "422 응답의 blockers 에만 있다",
                      "example": "07012340002"
                    },
                    "code": {
                      "type": "string",
                      "enum": [
                        "number_not_owned",
                        "number_not_carrier_issued",
                        "business_info_incomplete",
                        "identity_unverified",
                        "account_restricted",
                        "business_recheck_pending",
                        "holder_is_personal"
                      ],
                      "example": "number_not_carrier_issued"
                    },
                    "message": {
                      "type": "string",
                      "example": "이용증명원은 한국AI통신이 개통한 070·대표번호만 발급됩니다."
                    }
                  },
                  "required": [
                    "code",
                    "message"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "401": {
      "description": "인증 실패",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "error": {
                "type": "string",
                "description": "사람이 읽을 수 있는 에러 메시지"
              },
              "code": {
                "type": "string",
                "description": "기계 판독용 에러 코드. **분기는 이 값으로 하세요** — `error` 문구는 안내를 다듬으면서\n바뀔 수 있지만 코드는 계약입니다.\n\n같은 상태 코드라도 대응이 갈리는 경우가 있습니다. 예를 들어 발신의 `422` 는\n  - `recipient_blocked`: 수신거부 명단에 있는 번호입니다. 재시도하지 말고 명단에서\n    해제해야 발신됩니다.\n  - `quota_exceeded`: 플랜 한도를 넘었습니다. 다음 주기에 다시 발신됩니다.\n\n전화번호 정규화 관련:\n  - `INVALID_PHONE_NUMBER`: 전화번호 포맷 오류 (한국 번호 형식 아님)\n  - `UNSUPPORTED_COUNTRY`: 국제 발신 미지원 (+82 외 국가코드)",
                "example": "recipient_blocked"
              },
              "ip": {
                "type": "string",
                "description": "`overseas_ip_blocked` 일 때만 옵니다. 국외 IP 라고 판정한 요청 IP 입니다.\n해외 리전 클라우드 서버에서 호출한다면 이 값이 그 서버의 공인 IP 이며, 콘솔\n「국외 접속 예외」에서 예외를 신청할 때 이 고정 IP 를 적습니다.",
                "example": "52.79.213.41"
              },
              "processedAt": {
                "type": "string",
                "format": "date-time",
                "description": "문자 발송 요청을 거부한 서버가 오류 응답을 생성한 시각(UTC). 콘솔은 이 값을 한국 시각으로 표시합니다. 인증·요청 형식 검증 등 발송 서비스 진입 전 오류에는 없을 수 있습니다.",
                "example": "2026-10-21T04:10:34.303Z"
              },
              "blockers": {
                "type": "array",
                "description": "`certificate_not_eligible` 일 때만 옵니다. 발급할 수 없는 번호와 그 이유입니다.",
                "items": {
                  "type": "object",
                  "description": "번호 하나가 발급되지 않는(또는 안내가 필요한) 이유.\n\n| code | 뜻 | 발급 |\n|---|---|---|\n| `number_not_owned` | 이 계정이 보유한 번호가 아님(반납·재배정 포함) | 막힘 |\n| `number_not_carrier_issued` | 한국AI통신이 개통한 070·대표번호가 아님(모바일 게이트웨이, 타사 번호) | 막힘 |\n| `business_info_incomplete` | 사업자 계정인데(관리번호 제외) 상호·사업자등록번호·대표자명·사업장 주소 중 빈 칸 | 막힘 |\n| `identity_unverified` | 개인 계정 번호 또는 관리번호인데 그 번호에 본인확인 정보가 없음 | 막힘 |\n| `account_restricted` | 이용 제한 계정 | 막힘 |\n| `business_recheck_pending` | 사업자 계정인데 사업자 정보 재확인이 진행 중(통과 전) — 관리번호를 뺀 계정의 모든 번호 | 막힘 |\n| `holder_is_personal` | 개인 명의로 찍힌다는 안내 | 가능 |",
                  "properties": {
                    "number": {
                      "type": "string",
                      "description": "422 응답의 blockers 에만 있다",
                      "example": "07012340002"
                    },
                    "code": {
                      "type": "string",
                      "enum": [
                        "number_not_owned",
                        "number_not_carrier_issued",
                        "business_info_incomplete",
                        "identity_unverified",
                        "account_restricted",
                        "business_recheck_pending",
                        "holder_is_personal"
                      ],
                      "example": "number_not_carrier_issued"
                    },
                    "message": {
                      "type": "string",
                      "example": "이용증명원은 한국AI통신이 개통한 070·대표번호만 발급됩니다."
                    }
                  },
                  "required": [
                    "code",
                    "message"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "403": {
      "description": "접근 권한 없음 또는 활성 구독 없음.",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "error": {
                "type": "string",
                "description": "사람이 읽을 수 있는 에러 메시지"
              },
              "code": {
                "type": "string",
                "description": "기계 판독용 에러 코드. **분기는 이 값으로 하세요** — `error` 문구는 안내를 다듬으면서\n바뀔 수 있지만 코드는 계약입니다.\n\n같은 상태 코드라도 대응이 갈리는 경우가 있습니다. 예를 들어 발신의 `422` 는\n  - `recipient_blocked`: 수신거부 명단에 있는 번호입니다. 재시도하지 말고 명단에서\n    해제해야 발신됩니다.\n  - `quota_exceeded`: 플랜 한도를 넘었습니다. 다음 주기에 다시 발신됩니다.\n\n전화번호 정규화 관련:\n  - `INVALID_PHONE_NUMBER`: 전화번호 포맷 오류 (한국 번호 형식 아님)\n  - `UNSUPPORTED_COUNTRY`: 국제 발신 미지원 (+82 외 국가코드)",
                "example": "recipient_blocked"
              },
              "ip": {
                "type": "string",
                "description": "`overseas_ip_blocked` 일 때만 옵니다. 국외 IP 라고 판정한 요청 IP 입니다.\n해외 리전 클라우드 서버에서 호출한다면 이 값이 그 서버의 공인 IP 이며, 콘솔\n「국외 접속 예외」에서 예외를 신청할 때 이 고정 IP 를 적습니다.",
                "example": "52.79.213.41"
              },
              "processedAt": {
                "type": "string",
                "format": "date-time",
                "description": "문자 발송 요청을 거부한 서버가 오류 응답을 생성한 시각(UTC). 콘솔은 이 값을 한국 시각으로 표시합니다. 인증·요청 형식 검증 등 발송 서비스 진입 전 오류에는 없을 수 있습니다.",
                "example": "2026-10-21T04:10:34.303Z"
              },
              "blockers": {
                "type": "array",
                "description": "`certificate_not_eligible` 일 때만 옵니다. 발급할 수 없는 번호와 그 이유입니다.",
                "items": {
                  "type": "object",
                  "description": "번호 하나가 발급되지 않는(또는 안내가 필요한) 이유.\n\n| code | 뜻 | 발급 |\n|---|---|---|\n| `number_not_owned` | 이 계정이 보유한 번호가 아님(반납·재배정 포함) | 막힘 |\n| `number_not_carrier_issued` | 한국AI통신이 개통한 070·대표번호가 아님(모바일 게이트웨이, 타사 번호) | 막힘 |\n| `business_info_incomplete` | 사업자 계정인데(관리번호 제외) 상호·사업자등록번호·대표자명·사업장 주소 중 빈 칸 | 막힘 |\n| `identity_unverified` | 개인 계정 번호 또는 관리번호인데 그 번호에 본인확인 정보가 없음 | 막힘 |\n| `account_restricted` | 이용 제한 계정 | 막힘 |\n| `business_recheck_pending` | 사업자 계정인데 사업자 정보 재확인이 진행 중(통과 전) — 관리번호를 뺀 계정의 모든 번호 | 막힘 |\n| `holder_is_personal` | 개인 명의로 찍힌다는 안내 | 가능 |",
                  "properties": {
                    "number": {
                      "type": "string",
                      "description": "422 응답의 blockers 에만 있다",
                      "example": "07012340002"
                    },
                    "code": {
                      "type": "string",
                      "enum": [
                        "number_not_owned",
                        "number_not_carrier_issued",
                        "business_info_incomplete",
                        "identity_unverified",
                        "account_restricted",
                        "business_recheck_pending",
                        "holder_is_personal"
                      ],
                      "example": "number_not_carrier_issued"
                    },
                    "message": {
                      "type": "string",
                      "example": "이용증명원은 한국AI통신이 개통한 070·대표번호만 발급됩니다."
                    }
                  },
                  "required": [
                    "code",
                    "message"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "404": {
      "description": "AgentId 또는 CallFlowId에 해당하는 대상을 찾을 수 없음",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "error": {
                "type": "string",
                "description": "사람이 읽을 수 있는 에러 메시지"
              },
              "code": {
                "type": "string",
                "description": "기계 판독용 에러 코드. **분기는 이 값으로 하세요** — `error` 문구는 안내를 다듬으면서\n바뀔 수 있지만 코드는 계약입니다.\n\n같은 상태 코드라도 대응이 갈리는 경우가 있습니다. 예를 들어 발신의 `422` 는\n  - `recipient_blocked`: 수신거부 명단에 있는 번호입니다. 재시도하지 말고 명단에서\n    해제해야 발신됩니다.\n  - `quota_exceeded`: 플랜 한도를 넘었습니다. 다음 주기에 다시 발신됩니다.\n\n전화번호 정규화 관련:\n  - `INVALID_PHONE_NUMBER`: 전화번호 포맷 오류 (한국 번호 형식 아님)\n  - `UNSUPPORTED_COUNTRY`: 국제 발신 미지원 (+82 외 국가코드)",
                "example": "recipient_blocked"
              },
              "ip": {
                "type": "string",
                "description": "`overseas_ip_blocked` 일 때만 옵니다. 국외 IP 라고 판정한 요청 IP 입니다.\n해외 리전 클라우드 서버에서 호출한다면 이 값이 그 서버의 공인 IP 이며, 콘솔\n「국외 접속 예외」에서 예외를 신청할 때 이 고정 IP 를 적습니다.",
                "example": "52.79.213.41"
              },
              "processedAt": {
                "type": "string",
                "format": "date-time",
                "description": "문자 발송 요청을 거부한 서버가 오류 응답을 생성한 시각(UTC). 콘솔은 이 값을 한국 시각으로 표시합니다. 인증·요청 형식 검증 등 발송 서비스 진입 전 오류에는 없을 수 있습니다.",
                "example": "2026-10-21T04:10:34.303Z"
              },
              "blockers": {
                "type": "array",
                "description": "`certificate_not_eligible` 일 때만 옵니다. 발급할 수 없는 번호와 그 이유입니다.",
                "items": {
                  "type": "object",
                  "description": "번호 하나가 발급되지 않는(또는 안내가 필요한) 이유.\n\n| code | 뜻 | 발급 |\n|---|---|---|\n| `number_not_owned` | 이 계정이 보유한 번호가 아님(반납·재배정 포함) | 막힘 |\n| `number_not_carrier_issued` | 한국AI통신이 개통한 070·대표번호가 아님(모바일 게이트웨이, 타사 번호) | 막힘 |\n| `business_info_incomplete` | 사업자 계정인데(관리번호 제외) 상호·사업자등록번호·대표자명·사업장 주소 중 빈 칸 | 막힘 |\n| `identity_unverified` | 개인 계정 번호 또는 관리번호인데 그 번호에 본인확인 정보가 없음 | 막힘 |\n| `account_restricted` | 이용 제한 계정 | 막힘 |\n| `business_recheck_pending` | 사업자 계정인데 사업자 정보 재확인이 진행 중(통과 전) — 관리번호를 뺀 계정의 모든 번호 | 막힘 |\n| `holder_is_personal` | 개인 명의로 찍힌다는 안내 | 가능 |",
                  "properties": {
                    "number": {
                      "type": "string",
                      "description": "422 응답의 blockers 에만 있다",
                      "example": "07012340002"
                    },
                    "code": {
                      "type": "string",
                      "enum": [
                        "number_not_owned",
                        "number_not_carrier_issued",
                        "business_info_incomplete",
                        "identity_unverified",
                        "account_restricted",
                        "business_recheck_pending",
                        "holder_is_personal"
                      ],
                      "example": "number_not_carrier_issued"
                    },
                    "message": {
                      "type": "string",
                      "example": "이용증명원은 한국AI통신이 개통한 070·대표번호만 발급됩니다."
                    }
                  },
                  "required": [
                    "code",
                    "message"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "409": {
      "description": "From 번호에 연결된 Agent가 없습니다 (Url 미지정 시). 또는 CallToken의 걸려온 통화가 이미 끊김 (`call_token_expired`)",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "error": {
                "type": "string",
                "description": "사람이 읽을 수 있는 에러 메시지"
              },
              "code": {
                "type": "string",
                "description": "기계 판독용 에러 코드. **분기는 이 값으로 하세요** — `error` 문구는 안내를 다듬으면서\n바뀔 수 있지만 코드는 계약입니다.\n\n같은 상태 코드라도 대응이 갈리는 경우가 있습니다. 예를 들어 발신의 `422` 는\n  - `recipient_blocked`: 수신거부 명단에 있는 번호입니다. 재시도하지 말고 명단에서\n    해제해야 발신됩니다.\n  - `quota_exceeded`: 플랜 한도를 넘었습니다. 다음 주기에 다시 발신됩니다.\n\n전화번호 정규화 관련:\n  - `INVALID_PHONE_NUMBER`: 전화번호 포맷 오류 (한국 번호 형식 아님)\n  - `UNSUPPORTED_COUNTRY`: 국제 발신 미지원 (+82 외 국가코드)",
                "example": "recipient_blocked"
              },
              "ip": {
                "type": "string",
                "description": "`overseas_ip_blocked` 일 때만 옵니다. 국외 IP 라고 판정한 요청 IP 입니다.\n해외 리전 클라우드 서버에서 호출한다면 이 값이 그 서버의 공인 IP 이며, 콘솔\n「국외 접속 예외」에서 예외를 신청할 때 이 고정 IP 를 적습니다.",
                "example": "52.79.213.41"
              },
              "processedAt": {
                "type": "string",
                "format": "date-time",
                "description": "문자 발송 요청을 거부한 서버가 오류 응답을 생성한 시각(UTC). 콘솔은 이 값을 한국 시각으로 표시합니다. 인증·요청 형식 검증 등 발송 서비스 진입 전 오류에는 없을 수 있습니다.",
                "example": "2026-10-21T04:10:34.303Z"
              },
              "blockers": {
                "type": "array",
                "description": "`certificate_not_eligible` 일 때만 옵니다. 발급할 수 없는 번호와 그 이유입니다.",
                "items": {
                  "type": "object",
                  "description": "번호 하나가 발급되지 않는(또는 안내가 필요한) 이유.\n\n| code | 뜻 | 발급 |\n|---|---|---|\n| `number_not_owned` | 이 계정이 보유한 번호가 아님(반납·재배정 포함) | 막힘 |\n| `number_not_carrier_issued` | 한국AI통신이 개통한 070·대표번호가 아님(모바일 게이트웨이, 타사 번호) | 막힘 |\n| `business_info_incomplete` | 사업자 계정인데(관리번호 제외) 상호·사업자등록번호·대표자명·사업장 주소 중 빈 칸 | 막힘 |\n| `identity_unverified` | 개인 계정 번호 또는 관리번호인데 그 번호에 본인확인 정보가 없음 | 막힘 |\n| `account_restricted` | 이용 제한 계정 | 막힘 |\n| `business_recheck_pending` | 사업자 계정인데 사업자 정보 재확인이 진행 중(통과 전) — 관리번호를 뺀 계정의 모든 번호 | 막힘 |\n| `holder_is_personal` | 개인 명의로 찍힌다는 안내 | 가능 |",
                  "properties": {
                    "number": {
                      "type": "string",
                      "description": "422 응답의 blockers 에만 있다",
                      "example": "07012340002"
                    },
                    "code": {
                      "type": "string",
                      "enum": [
                        "number_not_owned",
                        "number_not_carrier_issued",
                        "business_info_incomplete",
                        "identity_unverified",
                        "account_restricted",
                        "business_recheck_pending",
                        "holder_is_personal"
                      ],
                      "example": "number_not_carrier_issued"
                    },
                    "message": {
                      "type": "string",
                      "example": "이용증명원은 한국AI통신이 개통한 070·대표번호만 발급됩니다."
                    }
                  },
                  "required": [
                    "code",
                    "message"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "410": {
      "description": "종료된 AI Completion 모드 요청",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "error": {
                "type": "string",
                "description": "사람이 읽을 수 있는 에러 메시지"
              },
              "code": {
                "type": "string",
                "description": "기계 판독용 에러 코드. **분기는 이 값으로 하세요** — `error` 문구는 안내를 다듬으면서\n바뀔 수 있지만 코드는 계약입니다.\n\n같은 상태 코드라도 대응이 갈리는 경우가 있습니다. 예를 들어 발신의 `422` 는\n  - `recipient_blocked`: 수신거부 명단에 있는 번호입니다. 재시도하지 말고 명단에서\n    해제해야 발신됩니다.\n  - `quota_exceeded`: 플랜 한도를 넘었습니다. 다음 주기에 다시 발신됩니다.\n\n전화번호 정규화 관련:\n  - `INVALID_PHONE_NUMBER`: 전화번호 포맷 오류 (한국 번호 형식 아님)\n  - `UNSUPPORTED_COUNTRY`: 국제 발신 미지원 (+82 외 국가코드)",
                "example": "recipient_blocked"
              },
              "ip": {
                "type": "string",
                "description": "`overseas_ip_blocked` 일 때만 옵니다. 국외 IP 라고 판정한 요청 IP 입니다.\n해외 리전 클라우드 서버에서 호출한다면 이 값이 그 서버의 공인 IP 이며, 콘솔\n「국외 접속 예외」에서 예외를 신청할 때 이 고정 IP 를 적습니다.",
                "example": "52.79.213.41"
              },
              "processedAt": {
                "type": "string",
                "format": "date-time",
                "description": "문자 발송 요청을 거부한 서버가 오류 응답을 생성한 시각(UTC). 콘솔은 이 값을 한국 시각으로 표시합니다. 인증·요청 형식 검증 등 발송 서비스 진입 전 오류에는 없을 수 있습니다.",
                "example": "2026-10-21T04:10:34.303Z"
              },
              "blockers": {
                "type": "array",
                "description": "`certificate_not_eligible` 일 때만 옵니다. 발급할 수 없는 번호와 그 이유입니다.",
                "items": {
                  "type": "object",
                  "description": "번호 하나가 발급되지 않는(또는 안내가 필요한) 이유.\n\n| code | 뜻 | 발급 |\n|---|---|---|\n| `number_not_owned` | 이 계정이 보유한 번호가 아님(반납·재배정 포함) | 막힘 |\n| `number_not_carrier_issued` | 한국AI통신이 개통한 070·대표번호가 아님(모바일 게이트웨이, 타사 번호) | 막힘 |\n| `business_info_incomplete` | 사업자 계정인데(관리번호 제외) 상호·사업자등록번호·대표자명·사업장 주소 중 빈 칸 | 막힘 |\n| `identity_unverified` | 개인 계정 번호 또는 관리번호인데 그 번호에 본인확인 정보가 없음 | 막힘 |\n| `account_restricted` | 이용 제한 계정 | 막힘 |\n| `business_recheck_pending` | 사업자 계정인데 사업자 정보 재확인이 진행 중(통과 전) — 관리번호를 뺀 계정의 모든 번호 | 막힘 |\n| `holder_is_personal` | 개인 명의로 찍힌다는 안내 | 가능 |",
                  "properties": {
                    "number": {
                      "type": "string",
                      "description": "422 응답의 blockers 에만 있다",
                      "example": "07012340002"
                    },
                    "code": {
                      "type": "string",
                      "enum": [
                        "number_not_owned",
                        "number_not_carrier_issued",
                        "business_info_incomplete",
                        "identity_unverified",
                        "account_restricted",
                        "business_recheck_pending",
                        "holder_is_personal"
                      ],
                      "example": "number_not_carrier_issued"
                    },
                    "message": {
                      "type": "string",
                      "example": "이용증명원은 한국AI통신이 개통한 070·대표번호만 발급됩니다."
                    }
                  },
                  "required": [
                    "code",
                    "message"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "422": {
      "description": "통화 분 할당량 초과, 발신 미지원 플랜, AMD 애드온 비활성, 또는 수신거부 명단에 등록된 번호 (`recipient_blocked`). 수신거부로 막힌 경우 통화기록에 `hangup_cause=recipient_blocked` 로 남아 나중에 몇 건이 걸러졌는지 확인할 수 있습니다.",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "error": {
                "type": "string",
                "description": "사람이 읽을 수 있는 에러 메시지"
              },
              "code": {
                "type": "string",
                "description": "기계 판독용 에러 코드. **분기는 이 값으로 하세요** — `error` 문구는 안내를 다듬으면서\n바뀔 수 있지만 코드는 계약입니다.\n\n같은 상태 코드라도 대응이 갈리는 경우가 있습니다. 예를 들어 발신의 `422` 는\n  - `recipient_blocked`: 수신거부 명단에 있는 번호입니다. 재시도하지 말고 명단에서\n    해제해야 발신됩니다.\n  - `quota_exceeded`: 플랜 한도를 넘었습니다. 다음 주기에 다시 발신됩니다.\n\n전화번호 정규화 관련:\n  - `INVALID_PHONE_NUMBER`: 전화번호 포맷 오류 (한국 번호 형식 아님)\n  - `UNSUPPORTED_COUNTRY`: 국제 발신 미지원 (+82 외 국가코드)",
                "example": "recipient_blocked"
              },
              "ip": {
                "type": "string",
                "description": "`overseas_ip_blocked` 일 때만 옵니다. 국외 IP 라고 판정한 요청 IP 입니다.\n해외 리전 클라우드 서버에서 호출한다면 이 값이 그 서버의 공인 IP 이며, 콘솔\n「국외 접속 예외」에서 예외를 신청할 때 이 고정 IP 를 적습니다.",
                "example": "52.79.213.41"
              },
              "processedAt": {
                "type": "string",
                "format": "date-time",
                "description": "문자 발송 요청을 거부한 서버가 오류 응답을 생성한 시각(UTC). 콘솔은 이 값을 한국 시각으로 표시합니다. 인증·요청 형식 검증 등 발송 서비스 진입 전 오류에는 없을 수 있습니다.",
                "example": "2026-10-21T04:10:34.303Z"
              },
              "blockers": {
                "type": "array",
                "description": "`certificate_not_eligible` 일 때만 옵니다. 발급할 수 없는 번호와 그 이유입니다.",
                "items": {
                  "type": "object",
                  "description": "번호 하나가 발급되지 않는(또는 안내가 필요한) 이유.\n\n| code | 뜻 | 발급 |\n|---|---|---|\n| `number_not_owned` | 이 계정이 보유한 번호가 아님(반납·재배정 포함) | 막힘 |\n| `number_not_carrier_issued` | 한국AI통신이 개통한 070·대표번호가 아님(모바일 게이트웨이, 타사 번호) | 막힘 |\n| `business_info_incomplete` | 사업자 계정인데(관리번호 제외) 상호·사업자등록번호·대표자명·사업장 주소 중 빈 칸 | 막힘 |\n| `identity_unverified` | 개인 계정 번호 또는 관리번호인데 그 번호에 본인확인 정보가 없음 | 막힘 |\n| `account_restricted` | 이용 제한 계정 | 막힘 |\n| `business_recheck_pending` | 사업자 계정인데 사업자 정보 재확인이 진행 중(통과 전) — 관리번호를 뺀 계정의 모든 번호 | 막힘 |\n| `holder_is_personal` | 개인 명의로 찍힌다는 안내 | 가능 |",
                  "properties": {
                    "number": {
                      "type": "string",
                      "description": "422 응답의 blockers 에만 있다",
                      "example": "07012340002"
                    },
                    "code": {
                      "type": "string",
                      "enum": [
                        "number_not_owned",
                        "number_not_carrier_issued",
                        "business_info_incomplete",
                        "identity_unverified",
                        "account_restricted",
                        "business_recheck_pending",
                        "holder_is_personal"
                      ],
                      "example": "number_not_carrier_issued"
                    },
                    "message": {
                      "type": "string",
                      "example": "이용증명원은 한국AI통신이 개통한 070·대표번호만 발급됩니다."
                    }
                  },
                  "required": [
                    "code",
                    "message"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "429": {
      "description": "동시 통화 한도 초과 (플랜의 maxAgents 초과)",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "error": {
                "type": "string",
                "description": "사람이 읽을 수 있는 에러 메시지"
              },
              "code": {
                "type": "string",
                "description": "기계 판독용 에러 코드. **분기는 이 값으로 하세요** — `error` 문구는 안내를 다듬으면서\n바뀔 수 있지만 코드는 계약입니다.\n\n같은 상태 코드라도 대응이 갈리는 경우가 있습니다. 예를 들어 발신의 `422` 는\n  - `recipient_blocked`: 수신거부 명단에 있는 번호입니다. 재시도하지 말고 명단에서\n    해제해야 발신됩니다.\n  - `quota_exceeded`: 플랜 한도를 넘었습니다. 다음 주기에 다시 발신됩니다.\n\n전화번호 정규화 관련:\n  - `INVALID_PHONE_NUMBER`: 전화번호 포맷 오류 (한국 번호 형식 아님)\n  - `UNSUPPORTED_COUNTRY`: 국제 발신 미지원 (+82 외 국가코드)",
                "example": "recipient_blocked"
              },
              "ip": {
                "type": "string",
                "description": "`overseas_ip_blocked` 일 때만 옵니다. 국외 IP 라고 판정한 요청 IP 입니다.\n해외 리전 클라우드 서버에서 호출한다면 이 값이 그 서버의 공인 IP 이며, 콘솔\n「국외 접속 예외」에서 예외를 신청할 때 이 고정 IP 를 적습니다.",
                "example": "52.79.213.41"
              },
              "processedAt": {
                "type": "string",
                "format": "date-time",
                "description": "문자 발송 요청을 거부한 서버가 오류 응답을 생성한 시각(UTC). 콘솔은 이 값을 한국 시각으로 표시합니다. 인증·요청 형식 검증 등 발송 서비스 진입 전 오류에는 없을 수 있습니다.",
                "example": "2026-10-21T04:10:34.303Z"
              },
              "blockers": {
                "type": "array",
                "description": "`certificate_not_eligible` 일 때만 옵니다. 발급할 수 없는 번호와 그 이유입니다.",
                "items": {
                  "type": "object",
                  "description": "번호 하나가 발급되지 않는(또는 안내가 필요한) 이유.\n\n| code | 뜻 | 발급 |\n|---|---|---|\n| `number_not_owned` | 이 계정이 보유한 번호가 아님(반납·재배정 포함) | 막힘 |\n| `number_not_carrier_issued` | 한국AI통신이 개통한 070·대표번호가 아님(모바일 게이트웨이, 타사 번호) | 막힘 |\n| `business_info_incomplete` | 사업자 계정인데(관리번호 제외) 상호·사업자등록번호·대표자명·사업장 주소 중 빈 칸 | 막힘 |\n| `identity_unverified` | 개인 계정 번호 또는 관리번호인데 그 번호에 본인확인 정보가 없음 | 막힘 |\n| `account_restricted` | 이용 제한 계정 | 막힘 |\n| `business_recheck_pending` | 사업자 계정인데 사업자 정보 재확인이 진행 중(통과 전) — 관리번호를 뺀 계정의 모든 번호 | 막힘 |\n| `holder_is_personal` | 개인 명의로 찍힌다는 안내 | 가능 |",
                  "properties": {
                    "number": {
                      "type": "string",
                      "description": "422 응답의 blockers 에만 있다",
                      "example": "07012340002"
                    },
                    "code": {
                      "type": "string",
                      "enum": [
                        "number_not_owned",
                        "number_not_carrier_issued",
                        "business_info_incomplete",
                        "identity_unverified",
                        "account_restricted",
                        "business_recheck_pending",
                        "holder_is_personal"
                      ],
                      "example": "number_not_carrier_issued"
                    },
                    "message": {
                      "type": "string",
                      "example": "이용증명원은 한국AI통신이 개통한 070·대표번호만 발급됩니다."
                    }
                  },
                  "required": [
                    "code",
                    "message"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "500": {
      "description": "발신 실패",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "error": {
                "type": "string",
                "description": "사람이 읽을 수 있는 에러 메시지"
              },
              "code": {
                "type": "string",
                "description": "기계 판독용 에러 코드. **분기는 이 값으로 하세요** — `error` 문구는 안내를 다듬으면서\n바뀔 수 있지만 코드는 계약입니다.\n\n같은 상태 코드라도 대응이 갈리는 경우가 있습니다. 예를 들어 발신의 `422` 는\n  - `recipient_blocked`: 수신거부 명단에 있는 번호입니다. 재시도하지 말고 명단에서\n    해제해야 발신됩니다.\n  - `quota_exceeded`: 플랜 한도를 넘었습니다. 다음 주기에 다시 발신됩니다.\n\n전화번호 정규화 관련:\n  - `INVALID_PHONE_NUMBER`: 전화번호 포맷 오류 (한국 번호 형식 아님)\n  - `UNSUPPORTED_COUNTRY`: 국제 발신 미지원 (+82 외 국가코드)",
                "example": "recipient_blocked"
              },
              "ip": {
                "type": "string",
                "description": "`overseas_ip_blocked` 일 때만 옵니다. 국외 IP 라고 판정한 요청 IP 입니다.\n해외 리전 클라우드 서버에서 호출한다면 이 값이 그 서버의 공인 IP 이며, 콘솔\n「국외 접속 예외」에서 예외를 신청할 때 이 고정 IP 를 적습니다.",
                "example": "52.79.213.41"
              },
              "processedAt": {
                "type": "string",
                "format": "date-time",
                "description": "문자 발송 요청을 거부한 서버가 오류 응답을 생성한 시각(UTC). 콘솔은 이 값을 한국 시각으로 표시합니다. 인증·요청 형식 검증 등 발송 서비스 진입 전 오류에는 없을 수 있습니다.",
                "example": "2026-10-21T04:10:34.303Z"
              },
              "blockers": {
                "type": "array",
                "description": "`certificate_not_eligible` 일 때만 옵니다. 발급할 수 없는 번호와 그 이유입니다.",
                "items": {
                  "type": "object",
                  "description": "번호 하나가 발급되지 않는(또는 안내가 필요한) 이유.\n\n| code | 뜻 | 발급 |\n|---|---|---|\n| `number_not_owned` | 이 계정이 보유한 번호가 아님(반납·재배정 포함) | 막힘 |\n| `number_not_carrier_issued` | 한국AI통신이 개통한 070·대표번호가 아님(모바일 게이트웨이, 타사 번호) | 막힘 |\n| `business_info_incomplete` | 사업자 계정인데(관리번호 제외) 상호·사업자등록번호·대표자명·사업장 주소 중 빈 칸 | 막힘 |\n| `identity_unverified` | 개인 계정 번호 또는 관리번호인데 그 번호에 본인확인 정보가 없음 | 막힘 |\n| `account_restricted` | 이용 제한 계정 | 막힘 |\n| `business_recheck_pending` | 사업자 계정인데 사업자 정보 재확인이 진행 중(통과 전) — 관리번호를 뺀 계정의 모든 번호 | 막힘 |\n| `holder_is_personal` | 개인 명의로 찍힌다는 안내 | 가능 |",
                  "properties": {
                    "number": {
                      "type": "string",
                      "description": "422 응답의 blockers 에만 있다",
                      "example": "07012340002"
                    },
                    "code": {
                      "type": "string",
                      "enum": [
                        "number_not_owned",
                        "number_not_carrier_issued",
                        "business_info_incomplete",
                        "identity_unverified",
                        "account_restricted",
                        "business_recheck_pending",
                        "holder_is_personal"
                      ],
                      "example": "number_not_carrier_issued"
                    },
                    "message": {
                      "type": "string",
                      "example": "이용증명원은 한국AI통신이 개통한 070·대표번호만 발급됩니다."
                    }
                  },
                  "required": [
                    "code",
                    "message"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "503": {
      "description": "발신을 처리할 콜 노드가 일시적으로 준비되지 않음 (`code: ARI_NOT_READY` / `service_unavailable`). 재시도 가능.\n",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "error": {
                "type": "string",
                "description": "사람이 읽을 수 있는 에러 메시지"
              },
              "code": {
                "type": "string",
                "description": "기계 판독용 에러 코드. **분기는 이 값으로 하세요** — `error` 문구는 안내를 다듬으면서\n바뀔 수 있지만 코드는 계약입니다.\n\n같은 상태 코드라도 대응이 갈리는 경우가 있습니다. 예를 들어 발신의 `422` 는\n  - `recipient_blocked`: 수신거부 명단에 있는 번호입니다. 재시도하지 말고 명단에서\n    해제해야 발신됩니다.\n  - `quota_exceeded`: 플랜 한도를 넘었습니다. 다음 주기에 다시 발신됩니다.\n\n전화번호 정규화 관련:\n  - `INVALID_PHONE_NUMBER`: 전화번호 포맷 오류 (한국 번호 형식 아님)\n  - `UNSUPPORTED_COUNTRY`: 국제 발신 미지원 (+82 외 국가코드)",
                "example": "recipient_blocked"
              },
              "ip": {
                "type": "string",
                "description": "`overseas_ip_blocked` 일 때만 옵니다. 국외 IP 라고 판정한 요청 IP 입니다.\n해외 리전 클라우드 서버에서 호출한다면 이 값이 그 서버의 공인 IP 이며, 콘솔\n「국외 접속 예외」에서 예외를 신청할 때 이 고정 IP 를 적습니다.",
                "example": "52.79.213.41"
              },
              "processedAt": {
                "type": "string",
                "format": "date-time",
                "description": "문자 발송 요청을 거부한 서버가 오류 응답을 생성한 시각(UTC). 콘솔은 이 값을 한국 시각으로 표시합니다. 인증·요청 형식 검증 등 발송 서비스 진입 전 오류에는 없을 수 있습니다.",
                "example": "2026-10-21T04:10:34.303Z"
              },
              "blockers": {
                "type": "array",
                "description": "`certificate_not_eligible` 일 때만 옵니다. 발급할 수 없는 번호와 그 이유입니다.",
                "items": {
                  "type": "object",
                  "description": "번호 하나가 발급되지 않는(또는 안내가 필요한) 이유.\n\n| code | 뜻 | 발급 |\n|---|---|---|\n| `number_not_owned` | 이 계정이 보유한 번호가 아님(반납·재배정 포함) | 막힘 |\n| `number_not_carrier_issued` | 한국AI통신이 개통한 070·대표번호가 아님(모바일 게이트웨이, 타사 번호) | 막힘 |\n| `business_info_incomplete` | 사업자 계정인데(관리번호 제외) 상호·사업자등록번호·대표자명·사업장 주소 중 빈 칸 | 막힘 |\n| `identity_unverified` | 개인 계정 번호 또는 관리번호인데 그 번호에 본인확인 정보가 없음 | 막힘 |\n| `account_restricted` | 이용 제한 계정 | 막힘 |\n| `business_recheck_pending` | 사업자 계정인데 사업자 정보 재확인이 진행 중(통과 전) — 관리번호를 뺀 계정의 모든 번호 | 막힘 |\n| `holder_is_personal` | 개인 명의로 찍힌다는 안내 | 가능 |",
                  "properties": {
                    "number": {
                      "type": "string",
                      "description": "422 응답의 blockers 에만 있다",
                      "example": "07012340002"
                    },
                    "code": {
                      "type": "string",
                      "enum": [
                        "number_not_owned",
                        "number_not_carrier_issued",
                        "business_info_incomplete",
                        "identity_unverified",
                        "account_restricted",
                        "business_recheck_pending",
                        "holder_is_personal"
                      ],
                      "example": "number_not_carrier_issued"
                    },
                    "message": {
                      "type": "string",
                      "example": "이용증명원은 한국AI통신이 개통한 070·대표번호만 발급됩니다."
                    }
                  },
                  "required": [
                    "code",
                    "message"
                  ]
                }
              }
            }
          }
        }
      }
    }
  }
}
```