{
  "components": {
    "schemas": {
      "BulkBatchResponse": {
        "properties": {
          "data": {
            "description": "일괄 주문 결과입니다. 부분 성공 방식으로 실패한 줄은 다른 줄을 막지 않고 `done` 줄만 차감합니다. LPA/QR은 포함하지 않으며 각 `order_id`로 GET /v1/orders/{id}에서 조회하세요.",
            "properties": {
              "created_at": {
                "format": "date-time",
                "type": "string"
              },
              "external_ref": {
                "example": "batch-2026-001",
                "nullable": true,
                "type": "string"
              },
              "failed_lines": {
                "type": "integer"
              },
              "id": {
                "format": "uuid",
                "type": "string"
              },
              "items": {
                "items": {
                  "$ref": "#/components/schemas/BulkLineResult"
                },
                "type": "array"
              },
              "mode": {
                "$ref": "#/components/schemas/ModeEcho"
              },
              "status": {
                "description": "`pending`은 중단되어 아직 실행되지 않은 행이 있다는 뜻입니다. 같은 `Idempotency-Key`로 다시 호출해 나머지를 완료하세요.",
                "enum": [
                  "pending",
                  "completed",
                  "partial",
                  "failed"
                ],
                "type": "string"
              },
              "succeeded_lines": {
                "type": "integer"
              },
              "total_charged": {
                "$ref": "#/components/schemas/Money"
              },
              "total_lines": {
                "type": "integer"
              }
            },
            "type": "object"
          },
          "ok": {
            "enum": [
              true
            ],
            "type": "boolean"
          }
        },
        "required": [
          "ok",
          "data"
        ],
        "type": "object"
      },
      "BulkLineResult": {
        "properties": {
          "charged": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Money"
              }
            ],
            "nullable": true
          },
          "error": {
            "description": "실제 `domain.reason` 오류 코드입니다. 예: `wallet.insufficient_balance`, `esim.out_of_stock`, `order.package_not_allowed`, `wallet.velocity_exceeded`.",
            "nullable": true,
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              }
            },
            "type": "object"
          },
          "external_ref": {
            "example": "po-1001",
            "nullable": true,
            "type": "string"
          },
          "line_no": {
            "description": "제출한 순서 그대로 1부터 시작합니다.",
            "type": "integer"
          },
          "order_id": {
            "format": "uuid",
            "nullable": true,
            "type": "string"
          },
          "package_code": {
            "type": "string"
          },
          "quantity": {
            "type": "integer"
          },
          "status": {
            "enum": [
              "pending",
              "done",
              "failed"
            ],
            "type": "string"
          }
        },
        "type": "object"
      },
      "BulkRequest": {
        "properties": {
          "external_ref": {
            "description": "전체 일괄 요청의 참조 코드이며 일괄 응답에 반환됩니다.",
            "example": "batch-2026-001",
            "nullable": true,
            "type": "string"
          },
          "items": {
            "description": "각 항목은 독립 주문 하나를 생성합니다. 행 수 한도는 설정 가능하며 기본 100입니다. 초과 시 `internal.limit_exceeded`(422)를 반환합니다.",
            "items": {
              "properties": {
                "external_ref": {
                  "description": "이 줄만의 참조 코드이며 해당 줄의 결과에 그대로 반환됩니다.",
                  "example": "po-1001",
                  "nullable": true,
                  "type": "string"
                },
                "package_code": {
                  "description": "자사 카탈로그의 요금제 코드인 `public_sku`입니다. 공급업체가 변경되어도 요금제별로 불변이므로 대사 키로 안전하게 사용할 수 있습니다. 예시는 형식만 맞고 실제로 작동하지 않으니 `GET /v1/catalog/packages`에서 실제 코드를 조회하세요.",
                  "example": "TKE-VN-30D-X3K9F",
                  "type": "string"
                },
                "quantity": {
                  "example": 5,
                  "minimum": 1,
                  "type": "integer"
                }
              },
              "required": [
                "package_code",
                "quantity"
              ],
              "type": "object"
            },
            "minItems": 1,
            "type": "array"
          }
        },
        "required": [
          "items"
        ],
        "type": "object"
      },
      "CancelResponse": {
        "properties": {
          "data": {
            "properties": {
              "cancelled_at": {
                "format": "date-time",
                "type": "string"
              },
              "esim_id": {
                "format": "uuid",
                "type": "string"
              },
              "mode": {
                "$ref": "#/components/schemas/ModeEcho"
              },
              "refund_suggested": {
                "description": "`true`이면 환불 요청이 수동 승인 대기 중이며 자금은 아직 이동하지 않았습니다. `refunded.amount = 0`을 환불 없음으로 해석하지 마세요.",
                "type": "boolean"
              },
              "refunded": {
                "$ref": "#/components/schemas/Money",
                "description": "이번 취소로 실제 지갑에 반환된 금액입니다. 실운영에서는 보통 `0`이므로 결론을 내리기 전에 `refund_suggested`를 확인하세요."
              },
              "status": {
                "example": "cancelled",
                "type": "string"
              }
            },
            "type": "object"
          },
          "ok": {
            "enum": [
              true
            ],
            "type": "boolean"
          }
        },
        "required": [
          "ok",
          "data"
        ],
        "type": "object"
      },
      "Cancellable": {
        "description": "eSIM 취소 가능 여부와 불가 사유입니다. `POST /v1/esims/{order_item_id}/cancel` 호출 전에 읽으세요. 답변이므로 항상 존재하고 `null`이 아닙니다.",
        "properties": {
          "allowed": {
            "type": "boolean"
          },
          "disclosed_at": {
            "description": "코드가 시스템 밖으로 공개된 시각(ISO-8601 UTC)입니다. 아무도 보지 않았으면 `null`이며, 고객이 수신하지 못했는데 취소 불가라고 주장할 때 확인할 기록입니다.",
            "format": "date-time",
            "nullable": true,
            "type": "string"
          },
          "reason": {
            "description": "취소 불가 사유: `code_disclosed`(전송 또는 표시됨), `wrong_status`(취소 불가 상태), `expired`(만료), `not_supported`(취소 기능 미선언). `allowed = true`이면 `null`입니다. `esim.not_cancellable`의 `meta.reason`과 같은 코드입니다.",
            "enum": [
              "code_disclosed",
              "wrong_status",
              "expired",
              "not_supported",
              null
            ],
            "nullable": true,
            "type": "string"
          }
        },
        "type": "object"
      },
      "ChangePlanRequest": {
        "properties": {
          "package_code": {
            "description": "자사 카탈로그의 요금제 코드인 `public_sku`입니다. 공급업체가 변경되어도 요금제별로 불변이므로 대사 키로 안전하게 사용할 수 있습니다. 예시는 형식만 맞고 실제로 작동하지 않으니 `GET /v1/catalog/packages`에서 실제 코드를 조회하세요.",
            "example": "TKE-VN-7D-P4M2Q",
            "type": "string"
          }
        },
        "required": [
          "package_code"
        ],
        "type": "object"
      },
      "ChangePlanResponse": {
        "properties": {
          "data": {
            "description": "eSIM 요금제 변경 결과입니다.",
            "properties": {
              "charged": {
                "$ref": "#/components/schemas/Money"
              },
              "current_plan": {
                "properties": {
                  "code": {
                    "type": "string"
                  },
                  "expires_at": {
                    "format": "date-time",
                    "nullable": true,
                    "type": "string"
                  },
                  "started_at": {
                    "format": "date-time",
                    "nullable": true,
                    "type": "string"
                  }
                },
                "type": "object"
              },
              "esim_id": {
                "format": "uuid",
                "type": "string"
              },
              "mode": {
                "$ref": "#/components/schemas/ModeEcho"
              },
              "order_id": {
                "format": "uuid",
                "type": "string"
              },
              "previous_plan": {
                "nullable": true,
                "properties": {
                  "cancelled_at": {
                    "format": "date-time",
                    "nullable": true,
                    "type": "string"
                  },
                  "code": {
                    "type": "string"
                  },
                  "remaining_bytes_forfeited": {
                    "format": "int64",
                    "nullable": true,
                    "type": "integer"
                  }
                },
                "type": "object"
              },
              "warning": {
                "type": "string"
              }
            },
            "type": "object"
          },
          "ok": {
            "enum": [
              true
            ],
            "type": "boolean"
          }
        },
        "required": [
          "ok",
          "data"
        ],
        "type": "object"
      },
      "CreateOrderRequest": {
        "properties": {
          "external_ref": {
            "description": "응답 및 웹훅에 그대로 반환되는 자체 참조 코드입니다.",
            "example": "po-1001",
            "nullable": true,
            "type": "string"
          },
          "include": {
            "description": "추가 블록 요청: `[\"lpa\"]` 또는 `[\"lpa\",\"qr\"]`. 생략하면 `items[].install`은 `null`이고 모든 eSIM의 취소 권리가 유지됩니다. **코드 반환은 공개를 의미합니다**. `lpa`를 요청하면 주문 시점에 취소 가능 기간이 종료됩니다.",
            "example": [
              "lpa"
            ],
            "items": {
              "enum": [
                "lpa",
                "qr"
              ],
              "type": "string"
            },
            "nullable": true,
            "type": "array"
          },
          "invoice_buyer": {
            "$ref": "#/components/schemas/MemberInvoiceBuyer"
          },
          "items": {
            "description": "구매할 요금제 및 수량 목록입니다(eSIM 최대 50개).",
            "items": {
              "properties": {
                "package_code": {
                  "description": "자사 카탈로그의 요금제 코드인 `public_sku`입니다. 공급업체가 변경되어도 요금제별로 불변이므로 대사 키로 안전하게 사용할 수 있습니다. 예시는 형식만 맞고 실제로 작동하지 않으니 `GET /v1/catalog/packages`에서 실제 코드를 조회하세요.",
                  "example": "TKE-VN-30D-X3K9F",
                  "type": "string"
                },
                "quantity": {
                  "description": "이 요금제로 구매할 eSIM 수량입니다(≥ 1).",
                  "example": 2,
                  "type": "integer"
                }
              },
              "required": [
                "package_code",
                "quantity"
              ],
              "type": "object"
            },
            "type": "array"
          }
        },
        "required": [
          "items"
        ],
        "type": "object"
      },
      "CreateWebhookResponse": {
        "properties": {
          "data": {
            "properties": {
              "active": {
                "description": "`false`이면 새 이벤트를 받지 않습니다. 대시보드에서 중지하거나 API 키를 폐기하면 같은 트랜잭션에서 채널이 종료됩니다. CHECK_HEALTH를 통과한 `PUT /v1/webhooks/{id}`로 다시 활성화합니다.",
                "type": "boolean"
              },
              "created_at": {
                "format": "date-time",
                "type": "string"
              },
              "events": {
                "description": "비어 있으면 모두 수신합니다.",
                "items": {
                  "enum": [
                    "order.completed",
                    "order.failed",
                    "esim.delivered",
                    "esim.activated",
                    "esim.usage_threshold",
                    "esim.expiring",
                    "wallet.low_balance",
                    "catalog.updated"
                  ],
                  "type": "string"
                },
                "type": "array"
              },
              "health_check": {
                "enum": [
                  "passed"
                ],
                "type": "string"
              },
              "id": {
                "description": "`/v1/webhooks/{id}`에 넣는 엔드포인트 ID입니다. 생성할 때마다 새로 발급되므로 삭제 후 재생성은 기존 복구가 아닌 새 엔드포인트입니다.",
                "format": "uuid",
                "type": "string"
              },
              "last_delivery_at": {
                "description": "이 엔드포인트로 마지막 전송한 시각입니다. `null`은 전송 실패가 아닌 전송한 적 없음을 뜻하며, 파트너가 웹훅을 못 받았다고 할 때 먼저 확인할 값입니다.",
                "format": "date-time",
                "nullable": true,
                "type": "string"
              },
              "mode": {
                "$ref": "#/components/schemas/ModeEcho"
              },
              "secret_last4": {
                "description": "웹훅 비밀키의 마지막 네 글자입니다. 비밀키 전체를 다시 노출하지 않고 보유한 키가 서명에 쓰이는 키인지 확인합니다. 전체 비밀키는 생성 시 한 번만 표시됩니다.",
                "type": "string"
              },
              "url": {
                "type": "string"
              },
              "webhook_secret": {
                "description": "생성 시 한 번만 표시합니다(접두사 `whsec_`).",
                "type": "string"
              }
            },
            "type": "object"
          },
          "ok": {
            "enum": [
              true
            ],
            "type": "boolean"
          }
        },
        "required": [
          "ok",
          "data"
        ],
        "type": "object"
      },
      "DeleteWebhookResponse": {
        "properties": {
          "data": {
            "properties": {
              "deleted_at": {
                "format": "date-time",
                "type": "string"
              },
              "id": {
                "format": "uuid",
                "type": "string"
              },
              "mode": {
                "$ref": "#/components/schemas/ModeEcho"
              }
            },
            "type": "object"
          },
          "ok": {
            "enum": [
              true
            ],
            "type": "boolean"
          }
        },
        "required": [
          "ok",
          "data"
        ],
        "type": "object"
      },
      "Delivery": {
        "properties": {
          "attempts": {
            "type": "integer"
          },
          "created_at": {
            "format": "date-time",
            "type": "string"
          },
          "event_id": {
            "description": "이벤트 식별자입니다. 재전송은 같은 `event_id`를 가진 새 전송을 생성하므로 전송 `id`가 아닌 `event_id`로 중복을 제거하세요.",
            "format": "uuid",
            "type": "string"
          },
          "event_type": {
            "type": "string"
          },
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "last_attempt_at": {
            "format": "date-time",
            "nullable": true,
            "type": "string"
          },
          "next_retry_at": {
            "format": "date-time",
            "nullable": true,
            "type": "string"
          },
          "response_code": {
            "nullable": true,
            "type": "integer"
          },
          "status": {
            "enum": [
              "pending",
              "delivered",
              "failed"
            ],
            "type": "string"
          },
          "webhook_id": {
            "format": "uuid",
            "type": "string"
          }
        },
        "type": "object"
      },
      "DeliveryListResponse": {
        "properties": {
          "data": {
            "properties": {
              "items": {
                "items": {
                  "$ref": "#/components/schemas/Delivery"
                },
                "type": "array"
              },
              "mode": {
                "$ref": "#/components/schemas/ModeEcho"
              },
              "next_cursor": {
                "description": "다음 페이지를 조회할 때 값을 그대로 전달하세요. `null`만이 종료 신호이며, `page_size`보다 적게 반환되어도 다음 페이지가 있을 수 있습니다.",
                "nullable": true,
                "type": "string"
              },
              "page_size": {
                "description": "서버가 이 페이지에 적용한 최대 레코드 수이며 상한이 반영된 값입니다. 실제 `items` 항목 수가 아닙니다.",
                "nullable": true,
                "type": "integer"
              },
              "total": {
                "description": "필터에 맞는 레코드 수입니다. 집계 비용이 너무 높으면 `null`입니다. 마지막 페이지 판단에는 이 값이 아닌 `next_cursor`를 사용하세요.",
                "format": "int64",
                "nullable": true,
                "type": "integer"
              },
              "warnings": {
                "description": "목록에 대한 설명이며 특이사항이 없으면 비어 있습니다. 고정 코드: `filtered_by_key_package_filters`, `filtered_by_provider_scope`, `no_price_for_org`, `price_filter_removed_rows`, `provider_disabled`, `capability_missing`. 각각 키 제한, 조직 공급원 범위, 미설정 가격, 가격 필터, 공급원 비활성, 기능 미선언을 뜻합니다. `count`는 해당 행 수이며 수치화할 수 없으면 `null`입니다.",
                "example": [],
                "items": {
                  "$ref": "#/components/schemas/ListWarning"
                },
                "type": "array"
              }
            },
            "type": "object"
          },
          "ok": {
            "enum": [
              true
            ],
            "type": "boolean"
          }
        },
        "required": [
          "ok",
          "data"
        ],
        "type": "object"
      },
      "DeliveryReplayResponse": {
        "properties": {
          "data": {
            "properties": {
              "attempts": {
                "type": "integer"
              },
              "created_at": {
                "format": "date-time",
                "type": "string"
              },
              "event_id": {
                "description": "이벤트 식별자입니다. 재전송은 같은 `event_id`를 가진 새 전송을 생성하므로 전송 `id`가 아닌 `event_id`로 중복을 제거하세요.",
                "format": "uuid",
                "type": "string"
              },
              "event_type": {
                "type": "string"
              },
              "id": {
                "format": "uuid",
                "type": "string"
              },
              "last_attempt_at": {
                "format": "date-time",
                "nullable": true,
                "type": "string"
              },
              "mode": {
                "$ref": "#/components/schemas/ModeEcho"
              },
              "next_retry_at": {
                "format": "date-time",
                "nullable": true,
                "type": "string"
              },
              "response_code": {
                "nullable": true,
                "type": "integer"
              },
              "status": {
                "enum": [
                  "pending",
                  "delivered",
                  "failed"
                ],
                "type": "string"
              },
              "webhook_id": {
                "format": "uuid",
                "type": "string"
              }
            },
            "type": "object"
          },
          "ok": {
            "enum": [
              true
            ],
            "type": "boolean"
          }
        },
        "required": [
          "ok",
          "data"
        ],
        "type": "object"
      },
      "ErrorEnvelope": {
        "properties": {
          "error": {
            "properties": {
              "code": {
                "description": "`domain.reason` 형식의 코드입니다(오류 코드 표 참고).",
                "type": "string"
              },
              "field": {
                "nullable": true,
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "meta": {
                "nullable": true,
                "type": "object"
              },
              "request_id": {
                "type": "string"
              }
            },
            "required": [
              "code",
              "message",
              "request_id"
            ],
            "type": "object"
          },
          "ok": {
            "enum": [
              false
            ],
            "type": "boolean"
          }
        },
        "required": [
          "ok",
          "error"
        ],
        "type": "object"
      },
      "Esim": {
        "properties": {
          "data": {
            "properties": {
              "cancellable": {
                "$ref": "#/components/schemas/Cancellable"
              },
              "external_ref": {
                "description": "주문 시 보낸 `external_ref`로 eSIM을 주문과 연결합니다. 참조 없이 주문했으면 `null`입니다.",
                "nullable": true,
                "type": "string"
              },
              "iccid": {
                "example": "8984012345678901234",
                "nullable": true,
                "type": "string"
              },
              "id": {
                "description": "모든 `/v1/esims/{id}/…` 경로에 사용하는 eSIM ID이며 웹훅의 `order_item_id`와 같습니다. ICCID만 있으면 `GET /v1/esims?iccid=…`로 `id`를 조회하세요.",
                "format": "uuid",
                "type": "string"
              },
              "install": {
                "$ref": "#/components/schemas/Install"
              },
              "mode": {
                "$ref": "#/components/schemas/ModeEcho"
              },
              "msisdn": {
                "nullable": true,
                "type": "string"
              },
              "order_id": {
                "format": "uuid",
                "type": "string"
              },
              "package_code": {
                "description": "카탈로그의 요금제 코드로, eSIM을 카탈로그와 연결하는 키입니다. 원본 요금제가 카탈로그에서 제거된 경우에만 `null`입니다.",
                "nullable": true,
                "type": "string"
              },
              "package_name": {
                "description": "변경될 수 있는 사람이 읽는 표시 이름입니다. 대사 키로 사용하지 마세요.",
                "type": "string"
              },
              "plan": {
                "$ref": "#/components/schemas/PlanView"
              },
              "smdp_status": {
                "example": "released",
                "nullable": true,
                "type": "string"
              },
              "status": {
                "example": "delivered",
                "type": "string"
              },
              "updated_at": {
                "format": "date-time",
                "type": "string"
              },
              "usage": {
                "$ref": "#/components/schemas/Usage"
              }
            },
            "type": "object"
          },
          "ok": {
            "enum": [
              true
            ],
            "type": "boolean"
          }
        },
        "required": [
          "ok",
          "data"
        ],
        "type": "object"
      },
      "EsimItem": {
        "properties": {
          "cancellable": {
            "$ref": "#/components/schemas/Cancellable"
          },
          "external_ref": {
            "description": "주문 시 보낸 `external_ref`로 eSIM을 주문과 연결합니다. 참조 없이 주문했으면 `null`입니다.",
            "nullable": true,
            "type": "string"
          },
          "iccid": {
            "example": "8984012345678901234",
            "nullable": true,
            "type": "string"
          },
          "id": {
            "description": "모든 `/v1/esims/{id}/…` 경로에 사용하는 eSIM ID이며 웹훅의 `order_item_id`와 같습니다. ICCID만 있으면 `GET /v1/esims?iccid=…`로 `id`를 조회하세요.",
            "format": "uuid",
            "type": "string"
          },
          "install": {
            "$ref": "#/components/schemas/Install"
          },
          "msisdn": {
            "nullable": true,
            "type": "string"
          },
          "order_id": {
            "format": "uuid",
            "type": "string"
          },
          "package_code": {
            "description": "카탈로그의 요금제 코드로, eSIM을 카탈로그와 연결하는 키입니다. 원본 요금제가 카탈로그에서 제거된 경우에만 `null`입니다.",
            "nullable": true,
            "type": "string"
          },
          "package_name": {
            "description": "변경될 수 있는 사람이 읽는 표시 이름입니다. 대사 키로 사용하지 마세요.",
            "type": "string"
          },
          "plan": {
            "$ref": "#/components/schemas/PlanView"
          },
          "smdp_status": {
            "example": "released",
            "nullable": true,
            "type": "string"
          },
          "status": {
            "example": "delivered",
            "type": "string"
          },
          "updated_at": {
            "format": "date-time",
            "type": "string"
          },
          "usage": {
            "$ref": "#/components/schemas/Usage"
          }
        },
        "type": "object"
      },
      "EsimListResponse": {
        "properties": {
          "data": {
            "properties": {
              "items": {
                "items": {
                  "$ref": "#/components/schemas/EsimItem"
                },
                "type": "array"
              },
              "mode": {
                "$ref": "#/components/schemas/ModeEcho"
              },
              "next_cursor": {
                "description": "다음 페이지를 조회할 때 값을 그대로 전달하세요. `null`만이 종료 신호이며, `page_size`보다 적게 반환되어도 다음 페이지가 있을 수 있습니다.",
                "nullable": true,
                "type": "string"
              },
              "page_size": {
                "description": "서버가 이 페이지에 적용한 최대 레코드 수이며 상한이 반영된 값입니다. 실제 `items` 항목 수가 아닙니다.",
                "nullable": true,
                "type": "integer"
              },
              "total": {
                "description": "필터에 맞는 레코드 수입니다. 집계 비용이 너무 높으면 `null`입니다. 마지막 페이지 판단에는 이 값이 아닌 `next_cursor`를 사용하세요.",
                "format": "int64",
                "nullable": true,
                "type": "integer"
              },
              "warnings": {
                "description": "목록에 대한 설명이며 특이사항이 없으면 비어 있습니다. 고정 코드: `filtered_by_key_package_filters`, `filtered_by_provider_scope`, `no_price_for_org`, `price_filter_removed_rows`, `provider_disabled`, `capability_missing`. 각각 키 제한, 조직 공급원 범위, 미설정 가격, 가격 필터, 공급원 비활성, 기능 미선언을 뜻합니다. `count`는 해당 행 수이며 수치화할 수 없으면 `null`입니다.",
                "example": [],
                "items": {
                  "$ref": "#/components/schemas/ListWarning"
                },
                "type": "array"
              }
            },
            "type": "object"
          },
          "ok": {
            "enum": [
              true
            ],
            "type": "boolean"
          }
        },
        "required": [
          "ok",
          "data"
        ],
        "type": "object"
      },
      "EsimUsage": {
        "properties": {
          "data": {
            "properties": {
              "esim_id": {
                "format": "uuid",
                "type": "string"
              },
              "mode": {
                "$ref": "#/components/schemas/ModeEcho"
              },
              "usage": {
                "$ref": "#/components/schemas/Usage"
              }
            },
            "type": "object"
          },
          "ok": {
            "enum": [
              true
            ],
            "type": "boolean"
          }
        },
        "required": [
          "ok",
          "data"
        ],
        "type": "object"
      },
      "Install": {
        "description": "이 eSIM 설치에 필요한 모든 정보입니다. `null`은 `include=lpa`로 요청하지 않았다는 뜻입니다. 아직 설치 코드가 없는 경우와는 다르며, 그 경우 블록은 존재하고 `lpa: null`입니다.\n\n이 블록이 포함된 응답에는 항상 `Cache-Control: no-store`가 설정됩니다.",
        "nullable": true,
        "properties": {
          "android_url": {
            "nullable": true,
            "type": "string"
          },
          "apn": {
            "description": "기기가 자동 구성하지 못할 때 입력할 APN입니다. 현재 버전에서는 항상 `null`이며 알 수 없다는 뜻이지 불필요하다는 뜻이 아닙니다.",
            "nullable": true,
            "type": "string"
          },
          "ios_url": {
            "nullable": true,
            "type": "string"
          },
          "lpa": {
            "description": "eSIM 활성화 코드이며 판매 가능한 비밀 정보입니다. 이 문자열만으로 QR 코드를 생성할 수 있습니다.",
            "example": "LPA:1$smdp.example.com$MATCH-ABC123",
            "nullable": true,
            "type": "string"
          },
          "matching_id": {
            "example": "MATCH-ABC123",
            "nullable": true,
            "type": "string"
          },
          "qr_code_base64": {
            "description": "QR 코드의 PNG data-URI입니다. 상세 엔드포인트에서 `include=qr`을 요청한 경우에만 포함되며 목록에는 포함되지 않습니다(행당 약 11KB, 100행이면 약 1.1MB). 목록에서는 `lpa`로 QR 코드를 생성하세요.",
            "nullable": true,
            "type": "string"
          },
          "smdp_address": {
            "example": "smdp.example.com",
            "nullable": true,
            "type": "string"
          }
        },
        "type": "object"
      },
      "ListWarning": {
        "description": "목록에 대한 설명이며 특이사항이 없으면 비어 있습니다. 고정 코드: `filtered_by_key_package_filters`, `filtered_by_provider_scope`, `no_price_for_org`, `price_filter_removed_rows`, `provider_disabled`, `capability_missing`. 각각 키 제한, 조직 공급원 범위, 미설정 가격, 가격 필터, 공급원 비활성, 기능 미선언을 뜻합니다. `count`는 해당 행 수이며 수치화할 수 없으면 `null`입니다.",
        "properties": {
          "code": {
            "enum": [
              "filtered_by_key_package_filters",
              "filtered_by_provider_scope",
              "no_price_for_org",
              "price_filter_removed_rows",
              "provider_disabled",
              "capability_missing"
            ],
            "example": "no_price_for_org",
            "type": "string"
          },
          "count": {
            "example": 12,
            "format": "int64",
            "nullable": true,
            "type": "integer"
          },
          "message": {
            "example": "12 gói bị lược vì tổ chức bạn chưa có giá.",
            "type": "string"
          }
        },
        "type": "object"
      },
      "MemberInvoiceBuyer": {
        "description": "회원 키 전용입니다. 생략하면 조직이나 베트남 법인 없이 소비자 흐름을 사용합니다. 입력 시 기존 개인 검증인 full_name, 12자리 개인 tax_code 및 checkout의 address/email 규칙을 적용합니다. 기업 청구서는 구매 후 요청합니다. 테스트 모드는 스냅샷만 검증하며 MISA 청구서를 발행하지 않습니다.",
        "nullable": true,
        "properties": {
          "address": {
            "nullable": true,
            "type": "string"
          },
          "email": {
            "nullable": true,
            "type": "string"
          },
          "full_name": {
            "nullable": true,
            "type": "string"
          },
          "legal_name": {
            "nullable": true,
            "type": "string"
          },
          "tax_code": {
            "nullable": true,
            "type": "string"
          }
        },
        "type": "object"
      },
      "MemberRefundRequest": {
        "properties": {
          "decided_at": {
            "format": "date-time",
            "nullable": true,
            "type": "string"
          },
          "decision_note": {
            "nullable": true,
            "type": "string"
          },
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "order_id": {
            "format": "uuid",
            "type": "string"
          },
          "order_item_id": {
            "format": "uuid",
            "type": "string"
          },
          "reason": {
            "type": "string"
          },
          "refunded": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Money"
              }
            ],
            "nullable": true
          },
          "requested_at": {
            "format": "date-time",
            "type": "string"
          },
          "status": {
            "enum": [
              "pending",
              "approved",
              "rejected"
            ],
            "type": "string"
          },
          "suggested": {
            "$ref": "#/components/schemas/Money"
          }
        },
        "type": "object"
      },
      "MemberRefundRequestInput": {
        "properties": {
          "reason": {
            "description": "앞뒤 공백을 제거한 후 5~1000자의 환불 사유입니다.",
            "maxLength": 1000,
            "minLength": 5,
            "type": "string"
          }
        },
        "required": [
          "reason"
        ],
        "type": "object"
      },
      "MemberRefundRequestListResponse": {
        "properties": {
          "data": {
            "properties": {
              "has_open_request": {
                "type": "boolean"
              },
              "items": {
                "items": {
                  "$ref": "#/components/schemas/MemberRefundRequest"
                },
                "type": "array"
              },
              "mode": {
                "$ref": "#/components/schemas/ModeEcho"
              },
              "next_cursor": {
                "description": "다음 페이지를 조회할 때 값을 그대로 전달하세요. `null`만이 종료 신호이며, `page_size`보다 적게 반환되어도 다음 페이지가 있을 수 있습니다.",
                "nullable": true,
                "type": "string"
              },
              "page_size": {
                "description": "서버가 이 페이지에 적용한 최대 레코드 수이며 상한이 반영된 값입니다. 실제 `items` 항목 수가 아닙니다.",
                "nullable": true,
                "type": "integer"
              },
              "total": {
                "description": "필터에 맞는 레코드 수입니다. 집계 비용이 너무 높으면 `null`입니다. 마지막 페이지 판단에는 이 값이 아닌 `next_cursor`를 사용하세요.",
                "format": "int64",
                "nullable": true,
                "type": "integer"
              },
              "warnings": {
                "description": "목록에 대한 설명이며 특이사항이 없으면 비어 있습니다. 고정 코드: `filtered_by_key_package_filters`, `filtered_by_provider_scope`, `no_price_for_org`, `price_filter_removed_rows`, `provider_disabled`, `capability_missing`. 각각 키 제한, 조직 공급원 범위, 미설정 가격, 가격 필터, 공급원 비활성, 기능 미선언을 뜻합니다. `count`는 해당 행 수이며 수치화할 수 없으면 `null`입니다.",
                "example": [],
                "items": {
                  "$ref": "#/components/schemas/ListWarning"
                },
                "type": "array"
              }
            },
            "type": "object"
          },
          "ok": {
            "enum": [
              true
            ],
            "type": "boolean"
          }
        },
        "required": [
          "ok",
          "data"
        ],
        "type": "object"
      },
      "MemberRefundRequestResponse": {
        "properties": {
          "data": {
            "properties": {
              "decided_at": {
                "format": "date-time",
                "nullable": true,
                "type": "string"
              },
              "decision_note": {
                "nullable": true,
                "type": "string"
              },
              "id": {
                "format": "uuid",
                "type": "string"
              },
              "mode": {
                "$ref": "#/components/schemas/ModeEcho"
              },
              "order_id": {
                "format": "uuid",
                "type": "string"
              },
              "order_item_id": {
                "format": "uuid",
                "type": "string"
              },
              "reason": {
                "type": "string"
              },
              "refunded": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Money"
                  }
                ],
                "nullable": true
              },
              "requested_at": {
                "format": "date-time",
                "type": "string"
              },
              "status": {
                "enum": [
                  "pending",
                  "approved",
                  "rejected"
                ],
                "type": "string"
              },
              "suggested": {
                "$ref": "#/components/schemas/Money"
              }
            },
            "type": "object"
          },
          "ok": {
            "enum": [
              true
            ],
            "type": "boolean"
          }
        },
        "required": [
          "ok",
          "data"
        ],
        "type": "object"
      },
      "ModeEcho": {
        "description": "호출 키의 환경이며 X-TKE-Mode 헤더와 일치합니다. 조직 키는 tke_live_/tke_test_, 회원 키는 tke_member_live_/tke_member_test_입니다. 실제 및 테스트 호스트는 키 모드를 검사합니다.",
        "enum": [
          "test",
          "live"
        ],
        "example": "live",
        "type": "string"
      },
      "Money": {
        "description": "금액입니다. `/v1` 전체에서 동일한 구조를 사용하며 객체와 숫자를 혼용하지 않습니다.",
        "properties": {
          "amount": {
            "description": "`currency`의 최소 단위로 표시한 정수입니다(VND에는 소수 단위가 없음).",
            "example": 273000,
            "format": "int64",
            "type": "integer"
          },
          "currency": {
            "example": "VND",
            "type": "string"
          }
        },
        "type": "object"
      },
      "OkEnvelope": {
        "properties": {
          "data": {
            "description": "페이로드는 엔드포인트에 따라 다릅니다.",
            "type": "object"
          },
          "ok": {
            "enum": [
              true
            ],
            "type": "boolean"
          }
        },
        "required": [
          "ok",
          "data"
        ],
        "type": "object"
      },
      "OrderItem": {
        "properties": {
          "cancellable": {
            "$ref": "#/components/schemas/Cancellable"
          },
          "external_ref": {
            "description": "주문 시 보낸 `external_ref`로 eSIM을 주문과 연결합니다. 참조 없이 주문했으면 `null`입니다.",
            "nullable": true,
            "type": "string"
          },
          "iccid": {
            "example": "8984012345678901234",
            "nullable": true,
            "type": "string"
          },
          "id": {
            "description": "모든 `/v1/esims/{id}/…` 경로에 사용하는 eSIM ID이며 웹훅의 `order_item_id`와 같습니다. ICCID만 있으면 `GET /v1/esims?iccid=…`로 `id`를 조회하세요.",
            "format": "uuid",
            "type": "string"
          },
          "install": {
            "$ref": "#/components/schemas/Install"
          },
          "msisdn": {
            "nullable": true,
            "type": "string"
          },
          "order_id": {
            "format": "uuid",
            "type": "string"
          },
          "package_code": {
            "description": "카탈로그의 요금제 코드로, eSIM을 카탈로그와 연결하는 키입니다. 원본 요금제가 카탈로그에서 제거된 경우에만 `null`입니다.",
            "nullable": true,
            "type": "string"
          },
          "package_name": {
            "description": "변경될 수 있는 사람이 읽는 표시 이름입니다. 대사 키로 사용하지 마세요.",
            "type": "string"
          },
          "plan": {
            "$ref": "#/components/schemas/PlanView"
          },
          "smdp_status": {
            "example": "released",
            "nullable": true,
            "type": "string"
          },
          "status": {
            "example": "delivered",
            "type": "string"
          },
          "updated_at": {
            "format": "date-time",
            "type": "string"
          },
          "usage": {
            "$ref": "#/components/schemas/Usage"
          }
        },
        "type": "object"
      },
      "OrderListItem": {
        "properties": {
          "created_at": {
            "format": "date-time",
            "type": "string"
          },
          "external_ref": {
            "example": "po-1001",
            "nullable": true,
            "type": "string"
          },
          "fulfillment_status": {
            "enum": [
              "fulfilled",
              "partially_fulfilled",
              "unfulfilled"
            ],
            "type": "string"
          },
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "item_count": {
            "format": "int64",
            "type": "integer"
          },
          "net": {
            "$ref": "#/components/schemas/Money"
          },
          "public_ref": {
            "example": "TKE-DH-2A4C7Q",
            "nullable": true,
            "type": "string"
          },
          "refunded": {
            "$ref": "#/components/schemas/Money"
          },
          "status": {
            "type": "string"
          },
          "total": {
            "$ref": "#/components/schemas/Money"
          },
          "updated_at": {
            "format": "date-time",
            "type": "string"
          }
        },
        "type": "object"
      },
      "OrderListResponse": {
        "properties": {
          "data": {
            "properties": {
              "items": {
                "items": {
                  "$ref": "#/components/schemas/OrderListItem"
                },
                "type": "array"
              },
              "mode": {
                "$ref": "#/components/schemas/ModeEcho"
              },
              "next_cursor": {
                "description": "다음 페이지를 조회할 때 값을 그대로 전달하세요. `null`만이 종료 신호이며, `page_size`보다 적게 반환되어도 다음 페이지가 있을 수 있습니다.",
                "nullable": true,
                "type": "string"
              },
              "page_size": {
                "description": "서버가 이 페이지에 적용한 최대 레코드 수이며 상한이 반영된 값입니다. 실제 `items` 항목 수가 아닙니다.",
                "nullable": true,
                "type": "integer"
              },
              "total": {
                "description": "필터에 맞는 레코드 수입니다. 집계 비용이 너무 높으면 `null`입니다. 마지막 페이지 판단에는 이 값이 아닌 `next_cursor`를 사용하세요.",
                "format": "int64",
                "nullable": true,
                "type": "integer"
              },
              "warnings": {
                "description": "목록에 대한 설명이며 특이사항이 없으면 비어 있습니다. 고정 코드: `filtered_by_key_package_filters`, `filtered_by_provider_scope`, `no_price_for_org`, `price_filter_removed_rows`, `provider_disabled`, `capability_missing`. 각각 키 제한, 조직 공급원 범위, 미설정 가격, 가격 필터, 공급원 비활성, 기능 미선언을 뜻합니다. `count`는 해당 행 수이며 수치화할 수 없으면 `null`입니다.",
                "example": [],
                "items": {
                  "$ref": "#/components/schemas/ListWarning"
                },
                "type": "array"
              }
            },
            "type": "object"
          },
          "ok": {
            "enum": [
              true
            ],
            "type": "boolean"
          }
        },
        "required": [
          "ok",
          "data"
        ],
        "type": "object"
      },
      "OrderResponse": {
        "properties": {
          "data": {
            "description": "파트너 주문입니다.",
            "properties": {
              "created_at": {
                "format": "date-time",
                "type": "string"
              },
              "external_ref": {
                "example": "po-1001",
                "nullable": true,
                "type": "string"
              },
              "fulfillment_status": {
                "description": "실제로 제공된 수량으로, `status`와 별개입니다. eSIM 3개 중 2개가 제공되고 1개가 실패해도 `status=completed`이며, `fulfillment_status=partially_fulfilled`, `refunded_amount > 0`이 됩니다.",
                "enum": [
                  "fulfilled",
                  "partially_fulfilled",
                  "unfulfilled"
                ],
                "type": "string"
              },
              "id": {
                "description": "주문 ID(UUID)입니다.",
                "format": "uuid",
                "type": "string"
              },
              "idempotent_replay": {
                "description": "이전 성공 요청의 멱등 재실행이면 참입니다.",
                "nullable": true,
                "type": "boolean"
              },
              "invoice_no": {
                "description": "발행 후 부여되는 청구서 번호입니다.",
                "nullable": true,
                "type": "string"
              },
              "invoice_status": {
                "description": "주문의 VAT 청구서 상태입니다. `none`은 아직 미발행입니다.",
                "enum": [
                  "none",
                  "pending",
                  "issuing",
                  "issued",
                  "failed",
                  "cancelled"
                ],
                "type": "string"
              },
              "items": {
                "items": {
                  "$ref": "#/components/schemas/OrderItem"
                },
                "type": "array"
              },
              "mode": {
                "$ref": "#/components/schemas/ModeEcho"
              },
              "money_settled": {
                "description": "주문 금액이 정산되었는지 여부입니다(진행 중인 환불 없음). `false`이면 청구서를 발행할 수 없습니다.",
                "type": "boolean"
              },
              "net": {
                "$ref": "#/components/schemas/Money"
              },
              "public_ref": {
                "description": "지원 요청에 사용할 짧고 읽기 쉬운 주문 코드입니다.",
                "example": "TKE-DH-2A4C7Q",
                "nullable": true,
                "type": "string"
              },
              "refunded": {
                "$ref": "#/components/schemas/Money"
              },
              "status": {
                "enum": [
                  "completed",
                  "pending_provider",
                  "provider_failed",
                  "cancelled"
                ],
                "type": "string"
              },
              "total": {
                "$ref": "#/components/schemas/Money"
              }
            },
            "type": "object"
          },
          "ok": {
            "enum": [
              true
            ],
            "type": "boolean"
          }
        },
        "required": [
          "ok",
          "data"
        ],
        "type": "object"
      },
      "Package": {
        "description": "**`null`은 정보가 없다는 뜻이며 긍정도 부정도 아닙니다.** 빈 필드로 약속을 추론하지 마세요. `true`/`false`와 `features.apps[]`에 존재하는 항목만 공급업체가 명시한 정보입니다.",
        "properties": {
          "capabilities": {
            "$ref": "#/components/schemas/PackageCapabilities"
          },
          "code": {
            "description": "자사 카탈로그의 요금제 코드인 `public_sku`입니다. 공급업체가 변경되어도 요금제별로 불변이므로 대사 키로 안전하게 사용할 수 있습니다. 예시는 형식만 맞고 실제로 작동하지 않으니 `GET /v1/catalog/packages`에서 실제 코드를 조회하세요.",
            "example": "TKE-VN-30D-X3K9F",
            "type": "string"
          },
          "coverage": {
            "description": "패키지 사용 가능 지역입니다.",
            "properties": {
              "countries": {
                "description": "ISO-3166 alpha-2 코드입니다. 글로벌 요금제(200개국을 모두 나열하지 않음)와 지원 국가가 명시되지 않은 요금제는 빈 배열입니다.",
                "example": [
                  "CN"
                ],
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              "country_count": {
                "description": "모든 데이터를 조회하고 배열을 직접 세지 않고도 다국가 요금제를 정렬하거나 필터링할 수 있도록 제공하는 지원 국가 수입니다.",
                "example": 1,
                "type": "integer"
              },
              "group": {
                "description": "범위: 국가 목록(`country`), 지역(`region`), 전 세계(`global`). 열린 열거형이므로 알 수 없는 값을 무시해야 합니다.",
                "example": "country",
                "type": "string"
              },
              "region": {
                "description": "항상 `null`입니다. 지역은 패키지가 아닌 국가에 연결되므로 값을 추론하지 않습니다. `?region=` 필터는 계속 작동합니다.",
                "nullable": true,
                "type": "string"
              }
            },
            "type": "object"
          },
          "data": {
            "description": "요금제 데이터 용량입니다. 이중 반올림을 피하도록 모든 수치는 MB/GB가 아닌 **바이트** 단위입니다.",
            "properties": {
              "daily_bytes": {
                "description": "바이트 단위의 일일 데이터 용량입니다. `fixed`/`unlimited` 요금제는 `null`입니다.",
                "example": 1073741824,
                "format": "int64",
                "nullable": true,
                "type": "integer"
              },
              "label": {
                "description": "모든 화면에서 사용하는 동일한 함수로 생성한 표시 이름입니다.",
                "example": "1GB/ngày",
                "type": "string"
              },
              "model": {
                "description": "용량 계산 방식: `daily`(일일 용량), `fixed`(전체 기간 총량), `unlimited`입니다. 확장 가능한 열거형이므로 클라이언트는 알 수 없는 값을 무시해야 합니다.",
                "enum": [
                  "daily",
                  "fixed",
                  "unlimited"
                ],
                "example": "daily",
                "type": "string"
              },
              "reset": {
                "description": "일일 데이터 초기화 시점입니다. 늦은 시간 구매 시 첫날 이용량에 영향을 주는 판매 정보입니다. `null`은 미선언입니다.",
                "nullable": true,
                "properties": {
                  "at": {
                    "description": "`timezone` 기준 현지 초기화 시각입니다(`00:00`, `00:00:01`).",
                    "example": "00:00",
                    "nullable": true,
                    "type": "string"
                  },
                  "note": {
                    "nullable": true,
                    "type": "string"
                  },
                  "timezone": {
                    "description": "초기화 시점의 시간대입니다(`UTC+8`, `UTC+7`).",
                    "example": "UTC+8",
                    "nullable": true,
                    "type": "string"
                  }
                },
                "type": "object"
              },
              "total_bytes": {
                "description": "전체 기간 데이터 용량(바이트)입니다. `daily`/`unlimited`는 `null`입니다. 일일 용량에 일수를 곱한 값은 공급업체가 보장한 총량이 아닙니다.",
                "example": null,
                "format": "int64",
                "nullable": true,
                "type": "integer"
              }
            },
            "type": "object"
          },
          "description": {
            "description": "패키지 판매 설명입니다. 작성되지 않았으면 `null`입니다.",
            "nullable": true,
            "type": "string"
          },
          "description_en": {
            "description": "영문 설명입니다. 제공되지 않으면 `null`입니다.",
            "nullable": true,
            "type": "string"
          },
          "features": {
            "description": "패키지 기능을 코드 배열 대신 타입이 있는 객체로 표시합니다. `[]`로는 핫스팟 미지원과 미확인을 구분할 수 없지만 `false`와 `null`은 구분할 수 있습니다.",
            "properties": {
              "apps": {
                "description": "운영체제별 앱 지원 상태입니다.\n\n**배열에 없는 앱은 정보가 없다는 뜻이며, 지원한다는 뜻이 아닙니다.** 목록에 있는 항목만 공급업체가 명시한 정보이고 현재는 TikTok만 명시되어 있습니다.\n\n통합 필드는 의도적으로 제공하지 않습니다. 실제 카탈로그에서 2,465개 요금제가 iPhone의 TikTok을 지원하지만 Android에서는 지원하지 않습니다. 하나의 통합 플래그로 모두 미지원 처리하면 카탈로그의 약 3분의 1을 잘못 안내하게 됩니다.",
                "items": {
                  "properties": {
                    "android": {
                      "description": "`supported`(공급업체 지원 명시), `blocked`(미지원 명시), `unknown`(해당 OS 정보 없음). 열린 열거형입니다.",
                      "enum": [
                        "supported",
                        "blocked",
                        "unknown"
                      ],
                      "example": "blocked",
                      "type": "string"
                    },
                    "app": {
                      "description": "소문자 앱 코드입니다(예: `tiktok`).",
                      "example": "tiktok",
                      "type": "string"
                    },
                    "ios": {
                      "description": "`supported`(공급업체 지원 명시), `blocked`(미지원 명시), `unknown`(해당 OS 정보 없음). 열린 열거형입니다.",
                      "enum": [
                        "supported",
                        "blocked",
                        "unknown"
                      ],
                      "example": "supported",
                      "type": "string"
                    },
                    "note": {
                      "nullable": true,
                      "type": "string"
                    }
                  },
                  "type": "object"
                },
                "type": "array"
              },
              "hotspot": {
                "description": "다른 기기와 Wi-Fi 공유 기능입니다. `null`은 미선언이며 `false`와 다릅니다.",
                "example": true,
                "nullable": true,
                "type": "boolean"
              },
              "kyc_required": {
                "description": "사용 전에 신원 확인(KYC)이 필요합니다. `null`은 미명시를 뜻합니다.",
                "example": false,
                "nullable": true,
                "type": "boolean"
              },
              "sms": {
                "description": "SMS입니다. `false`이면 문자 수신을 지원하지 않아 은행 OTP도 받을 수 없습니다. `null`은 미명시입니다.",
                "example": false,
                "nullable": true,
                "type": "boolean"
              },
              "voice": {
                "description": "음성 통화입니다. `false`는 공급업체가 미지원을 명시한 것이며 데이터 전용 회선은 전화를 받을 수 없습니다. `null`은 미선언입니다.",
                "example": false,
                "nullable": true,
                "type": "boolean"
              }
            },
            "type": "object"
          },
          "fup": {
            "description": "고속 데이터 소진 후 동작입니다. `null`은 속도 제한 정책 미선언입니다.",
            "nullable": true,
            "properties": {
              "behavior": {
                "description": "`throttle`(속도 제한), `cutoff`(연결 종료), `null`(미선언). 열린 열거형입니다.",
                "enum": [
                  "throttle",
                  "cutoff",
                  null
                ],
                "nullable": true,
                "type": "string"
              },
              "high_speed_bytes": {
                "description": "속도 제한 전 고속 데이터 바이트 수입니다.",
                "example": 1048576,
                "format": "int64",
                "nullable": true,
                "type": "integer"
              },
              "note": {
                "nullable": true,
                "type": "string"
              },
              "speed_kbps": {
                "description": "고속 용량을 소진한 이후 속도(kbps)입니다. 연결이 끊기거나 정보가 미명시이면 `null`입니다. 전체 요금제 속도 상한인 `network.speed_cap_kbps`와 다릅니다.",
                "example": 128,
                "nullable": true,
                "type": "integer"
              }
            },
            "type": "object"
          },
          "market": {
            "description": "요금제의 공급 시스템으로 확장 가능한 열거형이므로 알 수 없는 값은 무시해야 합니다. 재고 유무와 판매 후 작업을 결정합니다. `domestic`은 키트를 판매하며 충전·취소·사용량 조회를 지원하고, `international`은 요청 시 공급업체에 주문하므로 재고가 없습니다.",
            "enum": [
              "domestic",
              "international"
            ],
            "example": "international",
            "type": "string"
          },
          "name": {
            "example": "eSIM Trung Quốc Mainland Multi - 1GB/ngày - 24 ngày",
            "type": "string"
          },
          "name_en": {
            "description": "영문 이름입니다. 제공되지 않으면 `null`입니다.",
            "nullable": true,
            "type": "string"
          },
          "network": {
            "description": "패키지가 사용하는 네트워크입니다.",
            "properties": {
              "apn": {
                "description": "자동 설정이 되지 않는 일부 Android 기기에 수동 입력할 APN입니다. 설치 안내에 필요한 정보이며 없으면 고객 지원 문의로 이어집니다. `null`은 미명시입니다.",
                "example": "e-ideas",
                "nullable": true,
                "type": "string"
              },
              "carriers": {
                "description": "요금제가 사용하는 통신사입니다. 어느 무선망을 쓰는지에 대한 eSIM 사양이며 공급업체가 아닙니다.",
                "items": {
                  "properties": {
                    "name": {
                      "example": "China Unicom",
                      "type": "string"
                    }
                  },
                  "type": "object"
                },
                "type": "array"
              },
              "generations": {
                "description": "사용 가능한 이동통신 세대입니다(`[\"4g\", \"5g\"]`). `null`은 미명시이며 2G 전용이라는 뜻이 아닙니다.",
                "example": [
                  "4g",
                  "5g"
                ],
                "items": {
                  "type": "string"
                },
                "nullable": true,
                "type": "array"
              },
              "speed_cap_kbps": {
                "description": "전체 요금제의 속도 상한(kbps)으로, 고속 용량 소진 후 적용하는 `fup.speed_kbps`와 다릅니다.",
                "nullable": true,
                "type": "integer"
              }
            },
            "type": "object"
          },
          "price": {
            "$ref": "#/components/schemas/Money",
            "description": "조직이 API로 지불하는 가격으로 `POST /v1/orders`가 실제 차감할 금액과 같습니다. 항상 `{amount, currency}` 객체이며 숫자만 반환하지 않습니다. 원가는 공개하지 않습니다."
          },
          "tags": {
            "description": "소문자와 하이픈으로 정규화한 상품 태그로, 키의 카탈로그 제한에도 사용됩니다. 현재 태그가 있는 요금제가 없으므로 판매자가 태그를 추가하기 전까지 `?tag=`는 빈 목록을 반환합니다.",
            "example": [],
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "validity": {
            "description": "요금제 유효기간과 시작 시점입니다.",
            "properties": {
              "days": {
                "example": 24,
                "type": "integer"
              },
              "install_by_days": {
                "description": "구매 후 QR 스캔 또는 eSIM 설치가 가능한 기한(일)입니다. `null`은 미명시이며 언제든 설치 가능하다는 뜻이 아닙니다.",
                "example": 365,
                "nullable": true,
                "type": "integer"
              },
              "label": {
                "example": "24 ngày",
                "type": "string"
              },
              "reclaim_on_expiry": {
                "description": "만료 시 공급업체가 회선을 회수하여 충전과 요금제 변경이 불가능해집니다. 갱신 판매 시 기한을 알아야 합니다. `null`은 미선언입니다.",
                "example": true,
                "nullable": true,
                "type": "boolean"
              },
              "starts_when": {
                "description": "기간 시작 시점: `on_install`(설치), `on_purchase`(구매), `null`. 만료일 계산에 중요한 정보이며 `null`이면 특정 만료일을 약속하지 마세요.",
                "enum": [
                  "on_install",
                  "on_purchase",
                  null
                ],
                "example": "on_install",
                "nullable": true,
                "type": "string"
              },
              "unused_valid_days": {
                "description": "구매 후 사용하지 않고 보관할 수 있는 만료 전 일수입니다. `null`은 미명시이며 무기한이 아닙니다. 보관 유효기간은 설치 기한인 `install_by_days`와 별개입니다.",
                "nullable": true,
                "type": "integer"
              }
            },
            "type": "object"
          }
        },
        "type": "object"
      },
      "PackageCapabilities": {
        "description": "공급업체 유형으로 추론하지 않고 패키지가 실제 선언한 판매 후 기능입니다. 미선언 패키지는 모든 값이 `false`이며 반드시 `422 capability.not_supported`가 될 작업을 약속하지 않습니다.",
        "properties": {
          "cancel": {
            "properties": {
              "restriction": {
                "description": "`code_not_disclosed`는 고객 전달, 대시보드 열람, `?include=lpa` 등으로 아무도 코드를 보지 않았을 때만 취소할 수 있다는 뜻입니다. 실제 취소 조건이며 시스템이 알 수 없는 설치 여부를 의미하지 않습니다. 이전 `unused_only` 표기는 부정확했습니다.",
                "enum": [
                  "code_not_disclosed",
                  null
                ],
                "nullable": true,
                "type": "string"
              },
              "supported": {
                "type": "boolean"
              }
            },
            "type": "object"
          },
          "plan_change": {
            "properties": {
              "policy": {
                "$ref": "#/components/schemas/PlanChangePolicy"
              },
              "supported": {
                "type": "boolean"
              }
            },
            "type": "object"
          },
          "usage_check": {
            "properties": {
              "supported": {
                "type": "boolean"
              }
            },
            "type": "object"
          }
        },
        "type": "object"
      },
      "PackageDetail": {
        "properties": {
          "data": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Package"
              },
              {
                "properties": {
                  "mode": {
                    "$ref": "#/components/schemas/ModeEcho"
                  }
                },
                "type": "object"
              }
            ]
          },
          "ok": {
            "enum": [
              true
            ],
            "type": "boolean"
          }
        },
        "required": [
          "ok",
          "data"
        ],
        "type": "object"
      },
      "PackageListResponse": {
        "properties": {
          "data": {
            "properties": {
              "items": {
                "items": {
                  "$ref": "#/components/schemas/Package"
                },
                "type": "array"
              },
              "mode": {
                "$ref": "#/components/schemas/ModeEcho"
              },
              "next_cursor": {
                "description": "다음 페이지를 조회할 때 값을 그대로 전달하세요. `null`만이 종료 신호이며, `page_size`보다 적게 반환되어도 다음 페이지가 있을 수 있습니다.",
                "nullable": true,
                "type": "string"
              },
              "page_size": {
                "description": "서버가 이 페이지에 적용한 최대 레코드 수이며 상한이 반영된 값입니다. 실제 `items` 항목 수가 아닙니다.",
                "nullable": true,
                "type": "integer"
              },
              "total": {
                "description": "필터에 맞는 총 패키지 수입니다. 국제 또는 `market` 미지정 등 계산 비용이 크면 `null`입니다. 키 제한과 조직 가격 검사 전에 계산하므로 구매 가능 수가 아닌 카탈로그 일치 수입니다.",
                "format": "int64",
                "nullable": true,
                "type": "integer"
              },
              "warnings": {
                "description": "목록에 대한 설명이며 특이사항이 없으면 비어 있습니다. 고정 코드: `filtered_by_key_package_filters`, `filtered_by_provider_scope`, `no_price_for_org`, `price_filter_removed_rows`, `provider_disabled`, `capability_missing`. 각각 키 제한, 조직 공급원 범위, 미설정 가격, 가격 필터, 공급원 비활성, 기능 미선언을 뜻합니다. `count`는 해당 행 수이며 수치화할 수 없으면 `null`입니다.",
                "example": [],
                "items": {
                  "$ref": "#/components/schemas/ListWarning"
                },
                "type": "array"
              }
            },
            "type": "object"
          },
          "ok": {
            "enum": [
              true
            ],
            "type": "boolean"
          }
        },
        "required": [
          "ok",
          "data"
        ],
        "type": "object"
      },
      "PlanChangePolicy": {
        "description": "이 공급업체에서 새 요금제를 추가 충전하는 방식입니다. `null`은 충전할 수 없거나 공급업체 정책을 아직 확인하지 못했다는 뜻입니다. 추측해서는 안 됩니다. 모든 값이 `false`인 객체가 아무것도 취소되지 않음을 보장하는 것과는 의미가 다릅니다.",
        "nullable": true,
        "properties": {
          "note": {
            "nullable": true,
            "type": "string"
          },
          "requires_cancel_first": {
            "description": "이 공급업체는 요금제를 누적하지 않으므로 새 요금제를 주문하기 전에 사용 중인 요금제를 취소합니다. 고객이 새 요금제 충전 버튼을 누르기 전에 안내하세요.",
            "type": "boolean"
          },
          "stacking": {
            "description": "새 요금제의 기간과 용량을 기존 요금제에 합산하는지 여부입니다.",
            "type": "boolean"
          }
        },
        "type": "object"
      },
      "PlanOptionsResponse": {
        "properties": {
          "data": {
            "description": "현재 eSIM 공급업체로 미리 필터링한 충전 패키지입니다. 각 항목은 카탈로그와 같은 완전한 `Package`입니다. `policy`는 현재 공급업체의 정책이며 `null`은 미확인이지 아무것도 취소되지 않는다는 뜻이 아닙니다.",
            "properties": {
              "items": {
                "items": {
                  "$ref": "#/components/schemas/Package"
                },
                "type": "array"
              },
              "mode": {
                "$ref": "#/components/schemas/ModeEcho"
              },
              "next_cursor": {
                "description": "다음 페이지를 조회할 때 값을 그대로 전달하세요. `null`만이 종료 신호이며, `page_size`보다 적게 반환되어도 다음 페이지가 있을 수 있습니다.",
                "nullable": true,
                "type": "string"
              },
              "page_size": {
                "description": "서버가 이 페이지에 적용한 최대 레코드 수이며 상한이 반영된 값입니다. 실제 `items` 항목 수가 아닙니다.",
                "type": "integer"
              },
              "policy": {
                "$ref": "#/components/schemas/PlanChangePolicy"
              },
              "total": {
                "description": "필터에 맞는 총 패키지 수입니다. 국제 또는 `market` 미지정 등 계산 비용이 크면 `null`입니다. 키 제한과 조직 가격 검사 전에 계산하므로 구매 가능 수가 아닌 카탈로그 일치 수입니다.",
                "format": "int64",
                "nullable": true,
                "type": "integer"
              },
              "warnings": {
                "description": "목록에 대한 설명이며 특이사항이 없으면 비어 있습니다. 고정 코드: `filtered_by_key_package_filters`, `filtered_by_provider_scope`, `no_price_for_org`, `price_filter_removed_rows`, `provider_disabled`, `capability_missing`. 각각 키 제한, 조직 공급원 범위, 미설정 가격, 가격 필터, 공급원 비활성, 기능 미선언을 뜻합니다. `count`는 해당 행 수이며 수치화할 수 없으면 `null`입니다.",
                "example": [],
                "items": {
                  "$ref": "#/components/schemas/ListWarning"
                },
                "type": "array"
              }
            },
            "type": "object"
          },
          "ok": {
            "enum": [
              true
            ],
            "type": "boolean"
          }
        },
        "required": [
          "ok",
          "data"
        ],
        "type": "object"
      },
      "PlanView": {
        "description": "이 eSIM에 현재 적용된 요금제입니다.",
        "nullable": true,
        "properties": {
          "current_code": {
            "type": "string"
          },
          "expires_at": {
            "format": "date-time",
            "nullable": true,
            "type": "string"
          },
          "started_at": {
            "format": "date-time",
            "nullable": true,
            "type": "string"
          }
        },
        "type": "object"
      },
      "ResendResponse": {
        "properties": {
          "data": {
            "properties": {
              "id": {
                "description": "방금 다시 전송한 주문의 ID입니다.",
                "format": "uuid",
                "type": "string"
              },
              "mode": {
                "$ref": "#/components/schemas/ModeEcho"
              },
              "resent_at": {
                "format": "date-time",
                "type": "string"
              },
              "resent_to": {
                "description": "일부 가린 수신 주소입니다. 파트너 API는 고객의 전체 이메일을 다시 노출하지 않습니다.",
                "example": "ab***@x.com",
                "type": "string"
              }
            },
            "type": "object"
          },
          "ok": {
            "enum": [
              true
            ],
            "type": "boolean"
          }
        },
        "required": [
          "ok",
          "data"
        ],
        "type": "object"
      },
      "SimulateRequest": {
        "properties": {
          "data": {
            "description": "샘플 페이로드의 `data` 필드를 부분적으로 덮어씁니다.",
            "type": "object"
          }
        },
        "type": "object"
      },
      "SimulateResponse": {
        "properties": {
          "data": {
            "properties": {
              "delivery_id": {
                "format": "uuid",
                "type": "string"
              },
              "event_id": {
                "format": "uuid",
                "type": "string"
              },
              "mode": {
                "$ref": "#/components/schemas/ModeEcho"
              }
            },
            "type": "object"
          },
          "ok": {
            "enum": [
              true
            ],
            "type": "boolean"
          }
        },
        "required": [
          "ok",
          "data"
        ],
        "type": "object"
      },
      "TestModeEsimState": {
        "properties": {
          "data": {
            "properties": {
              "cancellable": {
                "$ref": "#/components/schemas/Cancellable"
              },
              "external_ref": {
                "description": "주문 시 보낸 `external_ref`로 eSIM을 주문과 연결합니다. 참조 없이 주문했으면 `null`입니다.",
                "nullable": true,
                "type": "string"
              },
              "iccid": {
                "example": "8984012345678901234",
                "nullable": true,
                "type": "string"
              },
              "id": {
                "description": "모든 `/v1/esims/{id}/…` 경로에 사용하는 eSIM ID이며 웹훅의 `order_item_id`와 같습니다. ICCID만 있으면 `GET /v1/esims?iccid=…`로 `id`를 조회하세요.",
                "format": "uuid",
                "type": "string"
              },
              "install": {
                "$ref": "#/components/schemas/Install"
              },
              "mode": {
                "$ref": "#/components/schemas/ModeEcho"
              },
              "msisdn": {
                "nullable": true,
                "type": "string"
              },
              "order_id": {
                "format": "uuid",
                "type": "string"
              },
              "package_code": {
                "description": "카탈로그의 요금제 코드로, eSIM을 카탈로그와 연결하는 키입니다. 원본 요금제가 카탈로그에서 제거된 경우에만 `null`입니다.",
                "nullable": true,
                "type": "string"
              },
              "package_name": {
                "description": "변경될 수 있는 사람이 읽는 표시 이름입니다. 대사 키로 사용하지 마세요.",
                "type": "string"
              },
              "plan": {
                "$ref": "#/components/schemas/PlanView"
              },
              "simulated": {
                "description": "시나리오 적용 후의 시뮬레이션 상태입니다.",
                "properties": {
                  "esim_state": {
                    "description": "테스트 eSIM의 기술적 수명주기입니다. 실운영에서는 `smdp_status`에서 읽지만 테스트 eSIM에는 SM-DP+ 프로필이 없으므로 다른 테스트 전용 필드와 함께 제공합니다.",
                    "enum": [
                      "released",
                      "installed",
                      "enabled",
                      "disabled"
                    ],
                    "type": "string"
                  },
                  "last_via": {
                    "description": "가장 최근 이 eSIM을 변경한 흐름입니다.",
                    "enum": [
                      "open_api",
                      "simulate",
                      "seed"
                    ],
                    "type": "string"
                  },
                  "via": {
                    "description": "이 테스트 eSIM을 생성한 흐름입니다.",
                    "enum": [
                      "open_api",
                      "simulate",
                      "seed"
                    ],
                    "type": "string"
                  }
                },
                "type": "object"
              },
              "smdp_status": {
                "example": "released",
                "nullable": true,
                "type": "string"
              },
              "status": {
                "example": "delivered",
                "type": "string"
              },
              "updated_at": {
                "format": "date-time",
                "type": "string"
              },
              "usage": {
                "$ref": "#/components/schemas/Usage"
              }
            },
            "type": "object"
          },
          "ok": {
            "enum": [
              true
            ],
            "type": "boolean"
          }
        },
        "required": [
          "ok",
          "data"
        ],
        "type": "object"
      },
      "TestModeFailNextRequest": {
        "properties": {
          "count": {
            "default": 1,
            "maximum": 5,
            "minimum": 1,
            "type": "integer"
          }
        },
        "type": "object"
      },
      "TestModeFailNextResponse": {
        "properties": {
          "data": {
            "properties": {
              "endpoint_id": {
                "format": "uuid",
                "type": "string"
              },
              "mode": {
                "$ref": "#/components/schemas/ModeEcho"
              },
              "testmode_fail_next": {
                "type": "integer"
              }
            },
            "type": "object"
          },
          "ok": {
            "enum": [
              true
            ],
            "type": "boolean"
          }
        },
        "required": [
          "ok",
          "data"
        ],
        "type": "object"
      },
      "TestModeReset": {
        "properties": {
          "data": {
            "properties": {
              "esim_states_deleted": {
                "format": "int64",
                "type": "integer"
              },
              "mode": {
                "$ref": "#/components/schemas/ModeEcho"
              },
              "order_items_deleted": {
                "format": "int64",
                "type": "integer"
              },
              "orders_deleted": {
                "format": "int64",
                "type": "integer"
              },
              "wallet_balance": {
                "description": "초기화 후 테스트 지갑 잔액이며 항상 0입니다. 원장은 삭제하지 않고 상계 분개로 잔액을 0으로 만듭니다.",
                "format": "int64",
                "type": "integer"
              }
            },
            "type": "object"
          },
          "ok": {
            "enum": [
              true
            ],
            "type": "boolean"
          }
        },
        "required": [
          "ok",
          "data"
        ],
        "type": "object"
      },
      "TestModeResetInput": {
        "properties": {
          "reason": {
            "example": "Reset test data",
            "maxLength": 1000,
            "minLength": 1,
            "type": "string"
          }
        },
        "type": "object"
      },
      "TestModeSeed": {
        "properties": {
          "data": {
            "properties": {
              "already_seeded": {
                "type": "boolean"
              },
              "esims_created": {
                "type": "integer"
              },
              "mode": {
                "$ref": "#/components/schemas/ModeEcho"
              },
              "orders_created": {
                "type": "integer"
              },
              "seeded": {
                "type": "boolean"
              }
            },
            "type": "object"
          },
          "ok": {
            "enum": [
              true
            ],
            "type": "boolean"
          }
        },
        "required": [
          "ok",
          "data"
        ],
        "type": "object"
      },
      "TestModeSimulateRequest": {
        "description": "적용할 시나리오입니다. 모든 필드는 선택 사항이지만 하나 이상 필요합니다. 빈 본문은 성공 처리하지 않고 `422 testmode.invalid_scenario`를 반환합니다.",
        "properties": {
          "data_used_mb": {
            "description": "이미 사용한 데이터(MB, 이진 1 MiB 단위)입니다. 허용량보다 크면 허용량으로 제한하며 이는 데이터 소진 시나리오이지 오류가 아닙니다.",
            "example": 4096,
            "format": "int64",
            "minimum": 0,
            "type": "integer"
          },
          "expire_at": {
            "description": "만료 시각을 지정합니다(ISO-8601 UTC).",
            "format": "date-time",
            "type": "string"
          },
          "expire_now": {
            "description": "`true`이면 요금제를 즉시 만료시킵니다(`esim_status`가 `expired`로 변경).",
            "type": "boolean"
          },
          "provider_reject": {
            "description": "다음 작업(충전/취소)에서 공급업체 거절을 시뮬레이션합니다.",
            "type": "boolean"
          },
          "status": {
            "description": "공급업체 용어로 표현한 eSIM 프로필의 기술적 수명주기입니다. eSIM 조회가 반환하는 비즈니스 상태 `esim_status`와 다릅니다.",
            "enum": [
              "released",
              "installed",
              "enabled",
              "disabled"
            ],
            "example": "enabled",
            "type": "string"
          },
          "throttled": {
            "description": "`true`이면 회선이 제한 속도 상태입니다(무제한 패키지의 고속 데이터 한도 초과).",
            "type": "boolean"
          }
        },
        "type": "object"
      },
      "TestModeStatus": {
        "properties": {
          "data": {
            "properties": {
              "base_url_testing": {
                "description": "테스트 모드 호스트입니다. tke_test_ 또는 tke_member_test_ 키만 사용하세요. 실제 호스트 호출은 403 partner.wrong_host를 반환합니다.",
                "type": "string"
              },
              "capabilities": {
                "properties": {
                  "bulk_orders": {
                    "type": "boolean"
                  },
                  "cancel_refund": {
                    "type": "boolean"
                  },
                  "refund_requests": {
                    "type": "boolean"
                  },
                  "webhooks": {
                    "type": "boolean"
                  }
                },
                "type": "object"
              },
              "checklist": {
                "description": "동일 소유자의 테스트 모드 실제 API 기록으로 통합 단계를 계산합니다. 웹훅 단계는 조직에만 적용됩니다.",
                "items": {
                  "properties": {
                    "done": {
                      "type": "boolean"
                    },
                    "label": {
                      "type": "string"
                    },
                    "last_at": {
                      "format": "date-time",
                      "nullable": true,
                      "type": "string"
                    },
                    "step": {
                      "type": "string"
                    }
                  },
                  "type": "object"
                },
                "type": "array"
              },
              "drift": {
                "description": "모의 사용량 증가 주기의 활성 상태, 간격, 최근 실행 시각입니다. 임계값 웹훅은 웹훅을 지원하는 조직에만 전송됩니다.",
                "properties": {
                  "enabled": {
                    "type": "boolean"
                  },
                  "interval_secs": {
                    "format": "int64",
                    "type": "integer"
                  },
                  "last_run_at": {
                    "format": "date-time",
                    "nullable": true,
                    "type": "string"
                  }
                },
                "type": "object"
              },
              "mode": {
                "enum": [
                  "test",
                  "live"
                ],
                "type": "string"
              },
              "ready": {
                "description": "키 소유자가 지원되는 체크리스트 단계를 모두 완료했는지 나타냅니다. 회원은 웹훅 테스트가 필요하지 않습니다.",
                "type": "boolean"
              },
              "sample_counts": {
                "properties": {
                  "test_esims": {
                    "format": "int64",
                    "type": "integer"
                  },
                  "test_orders": {
                    "format": "int64",
                    "type": "integer"
                  }
                },
                "type": "object"
              },
              "seeded": {
                "description": "키 소유자에게 샘플 테스트 주문과 eSIM이 이미 있는지 나타냅니다.",
                "type": "boolean"
              },
              "test_key_count": {
                "format": "int64",
                "type": "integer"
              },
              "wallet_balance": {
                "description": "키 소유자의 가상 VND 테스트 지갑 잔액이며 실제 지갑과 분리됩니다.",
                "format": "int64",
                "type": "integer"
              },
              "webhook": {
                "properties": {
                  "endpoint_url": {
                    "nullable": true,
                    "type": "string"
                  },
                  "fail_next": {
                    "type": "integer"
                  },
                  "status": {
                    "nullable": true,
                    "type": "string"
                  }
                },
                "type": "object"
              }
            },
            "type": "object"
          },
          "ok": {
            "enum": [
              true
            ],
            "type": "boolean"
          }
        },
        "required": [
          "ok",
          "data"
        ],
        "type": "object"
      },
      "TestModeWebhookFireRequest": {
        "properties": {
          "data": {
            "description": "샘플 페이로드의 `data` 필드를 부분적으로 덮어씁니다.",
            "type": "object"
          },
          "event_type": {
            "description": "발생시킬 웹훅 이벤트 유형입니다.",
            "enum": [
              "order.completed",
              "order.failed",
              "esim.delivered",
              "esim.activated",
              "esim.usage_threshold",
              "esim.expiring",
              "wallet.low_balance",
              "catalog.updated"
            ],
            "type": "string"
          }
        },
        "required": [
          "event_type"
        ],
        "type": "object"
      },
      "Usage": {
        "description": "eSIM 데이터 사용량 통계입니다. 조회한 적이 없으면 `updated_at = null`입니다。",
        "nullable": true,
        "properties": {
          "expires_at": {
            "format": "date-time",
            "nullable": true,
            "type": "string"
          },
          "remaining_bytes": {
            "format": "int64",
            "nullable": true,
            "type": "integer"
          },
          "source": {
            "enum": [
              "poll",
              "webhook"
            ],
            "nullable": true,
            "type": "string"
          },
          "total_bytes": {
            "format": "int64",
            "nullable": true,
            "type": "integer"
          },
          "updated_at": {
            "format": "date-time",
            "nullable": true,
            "type": "string"
          },
          "used_bytes": {
            "format": "int64",
            "nullable": true,
            "type": "integer"
          }
        },
        "type": "object"
      },
      "WalletBalance": {
        "properties": {
          "data": {
            "properties": {
              "available": {
                "$ref": "#/components/schemas/Money"
              },
              "balance": {
                "$ref": "#/components/schemas/Money"
              },
              "credit_limit": {
                "$ref": "#/components/schemas/Money"
              },
              "mode": {
                "$ref": "#/components/schemas/ModeEcho"
              }
            },
            "type": "object"
          },
          "ok": {
            "enum": [
              true
            ],
            "type": "boolean"
          }
        },
        "required": [
          "ok",
          "data"
        ],
        "type": "object"
      },
      "WebhookConfig": {
        "properties": {
          "data": {
            "properties": {
              "active": {
                "description": "`false`이면 새 이벤트를 받지 않습니다. 대시보드에서 중지하거나 API 키를 폐기하면 같은 트랜잭션에서 채널이 종료됩니다. CHECK_HEALTH를 통과한 `PUT /v1/webhooks/{id}`로 다시 활성화합니다.",
                "type": "boolean"
              },
              "created_at": {
                "format": "date-time",
                "type": "string"
              },
              "events": {
                "description": "비어 있으면 모두 수신합니다.",
                "items": {
                  "enum": [
                    "order.completed",
                    "order.failed",
                    "esim.delivered",
                    "esim.activated",
                    "esim.usage_threshold",
                    "esim.expiring",
                    "wallet.low_balance",
                    "catalog.updated"
                  ],
                  "type": "string"
                },
                "type": "array"
              },
              "id": {
                "description": "`/v1/webhooks/{id}`에 넣는 엔드포인트 ID입니다. 생성할 때마다 새로 발급되므로 삭제 후 재생성은 기존 복구가 아닌 새 엔드포인트입니다.",
                "format": "uuid",
                "type": "string"
              },
              "last_delivery_at": {
                "description": "이 엔드포인트로 마지막 전송한 시각입니다. `null`은 전송 실패가 아닌 전송한 적 없음을 뜻하며, 파트너가 웹훅을 못 받았다고 할 때 먼저 확인할 값입니다.",
                "format": "date-time",
                "nullable": true,
                "type": "string"
              },
              "mode": {
                "$ref": "#/components/schemas/ModeEcho"
              },
              "secret_last4": {
                "description": "웹훅 비밀키의 마지막 네 글자입니다. 비밀키 전체를 다시 노출하지 않고 보유한 키가 서명에 쓰이는 키인지 확인합니다. 전체 비밀키는 생성 시 한 번만 표시됩니다.",
                "type": "string"
              },
              "url": {
                "type": "string"
              }
            },
            "type": "object"
          },
          "ok": {
            "enum": [
              true
            ],
            "type": "boolean"
          }
        },
        "required": [
          "ok",
          "data"
        ],
        "type": "object"
      },
      "WebhookEndpoint": {
        "properties": {
          "active": {
            "description": "`false`이면 새 이벤트를 받지 않습니다. 대시보드에서 중지하거나 API 키를 폐기하면 같은 트랜잭션에서 채널이 종료됩니다. CHECK_HEALTH를 통과한 `PUT /v1/webhooks/{id}`로 다시 활성화합니다.",
            "type": "boolean"
          },
          "created_at": {
            "format": "date-time",
            "type": "string"
          },
          "events": {
            "description": "비어 있으면 모두 수신합니다.",
            "items": {
              "enum": [
                "order.completed",
                "order.failed",
                "esim.delivered",
                "esim.activated",
                "esim.usage_threshold",
                "esim.expiring",
                "wallet.low_balance",
                "catalog.updated"
              ],
              "type": "string"
            },
            "type": "array"
          },
          "id": {
            "description": "`/v1/webhooks/{id}`에 넣는 엔드포인트 ID입니다. 생성할 때마다 새로 발급되므로 삭제 후 재생성은 기존 복구가 아닌 새 엔드포인트입니다.",
            "format": "uuid",
            "type": "string"
          },
          "last_delivery_at": {
            "description": "이 엔드포인트로 마지막 전송한 시각입니다. `null`은 전송 실패가 아닌 전송한 적 없음을 뜻하며, 파트너가 웹훅을 못 받았다고 할 때 먼저 확인할 값입니다.",
            "format": "date-time",
            "nullable": true,
            "type": "string"
          },
          "secret_last4": {
            "description": "웹훅 비밀키의 마지막 네 글자입니다. 비밀키 전체를 다시 노출하지 않고 보유한 키가 서명에 쓰이는 키인지 확인합니다. 전체 비밀키는 생성 시 한 번만 표시됩니다.",
            "type": "string"
          },
          "url": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "WebhookListResponse": {
        "properties": {
          "data": {
            "properties": {
              "items": {
                "items": {
                  "$ref": "#/components/schemas/WebhookEndpoint"
                },
                "type": "array"
              },
              "mode": {
                "$ref": "#/components/schemas/ModeEcho"
              },
              "next_cursor": {
                "description": "다음 페이지를 조회할 때 값을 그대로 전달하세요. `null`만이 종료 신호이며, `page_size`보다 적게 반환되어도 다음 페이지가 있을 수 있습니다.",
                "nullable": true,
                "type": "string"
              },
              "page_size": {
                "description": "서버가 이 페이지에 적용한 최대 레코드 수이며 상한이 반영된 값입니다. 실제 `items` 항목 수가 아닙니다.",
                "nullable": true,
                "type": "integer"
              },
              "total": {
                "description": "필터에 맞는 레코드 수입니다. 집계 비용이 너무 높으면 `null`입니다. 마지막 페이지 판단에는 이 값이 아닌 `next_cursor`를 사용하세요.",
                "format": "int64",
                "nullable": true,
                "type": "integer"
              },
              "warnings": {
                "description": "목록에 대한 설명이며 특이사항이 없으면 비어 있습니다. 고정 코드: `filtered_by_key_package_filters`, `filtered_by_provider_scope`, `no_price_for_org`, `price_filter_removed_rows`, `provider_disabled`, `capability_missing`. 각각 키 제한, 조직 공급원 범위, 미설정 가격, 가격 필터, 공급원 비활성, 기능 미선언을 뜻합니다. `count`는 해당 행 수이며 수치화할 수 없으면 `null`입니다.",
                "example": [],
                "items": {
                  "$ref": "#/components/schemas/ListWarning"
                },
                "type": "array"
              }
            },
            "type": "object"
          },
          "ok": {
            "enum": [
              true
            ],
            "type": "boolean"
          }
        },
        "required": [
          "ok",
          "data"
        ],
        "type": "object"
      },
      "WebhookRequest": {
        "properties": {
          "events": {
            "description": "비어 있으면 모두 수신합니다. 알 수 없는 값은 400 `internal.validation_failed`(필드 `events`)입니다.",
            "items": {
              "enum": [
                "order.completed",
                "order.failed",
                "esim.delivered",
                "esim.activated",
                "esim.usage_threshold",
                "esim.expiring",
                "wallet.low_balance",
                "catalog.updated"
              ],
              "type": "string"
            },
            "type": "array"
          },
          "url": {
            "example": "https://partner.example.com/hooks/tke",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "url"
        ],
        "type": "object"
      }
    },
    "securitySchemes": {
      "TkeHmac": {
        "description": "HMAC-SHA256 인증(§4)입니다. `X-TKE-Key`(공개 key_id), `X-TKE-Timestamp`(epoch 밀리초), `X-TKE-Nonce`(요청별 UUID), `X-TKE-Signature`(소문자 16진수) 네 헤더를 전송합니다. signing_string = method\npath\ntimestamp\nnonce\nbody_hash이며 body_hash = SHA256(raw_body)의 16진수입니다. 상수 시간 비교를 사용하며 path에는 쿼리 문자열이 포함됩니다.",
        "in": "header",
        "name": "X-TKE-Signature",
        "type": "apiKey"
      }
    }
  },
  "info": {
    "description": "eSIM 판매를 연동하는 파트너용 Open API입니다(파트너는 단일 단계). 모든 `/v1/*` 엔드포인트는 네 개의 `X-TKE-*` 헤더로 **HMAC-SHA256** 인증을 요구하며 서명 없는 모드는 없습니다. 금액 또는 주문 관련 POST에는 `Idempotency-Key`가 필수입니다. `tke_test_` 키는 테스트 호스트에서 가상 지갑·재고·개통을 사용합니다. REST가 기준이며 `updated_since`와 커서로 대사하고 웹훅은 보조 수단입니다. 리소스 기본 키는 항상 `id`이고 외래 키는 `order_id`처럼 접두사가 붙습니다.",
    "title": "Tổng Kho eSIM — Open API đối tác",
    "version": "2.4.0"
  },
  "openapi": "3.0.3",
  "paths": {
    "/v1/catalog/packages": {
      "get": {
        "description": "필요한 권한 범위: `catalog:read`.\n\n조직의 요금제 카탈로그로, 두 공급 시스템을 하나의 화면에서 제공하고 `?market=`으로 필터링합니다.\n\n실제로 구매 가능한 요금제만 반환합니다. 게시 상태이고 공급업체가 계속 판매하며 키의 제한 범위 안에 있고 조직 가격까지 설정되어야 합니다. 미정가 요금제는 주문할 수 없으므로 표시하지 않습니다.\n\n커서 페이지 처리: 처음에는 `cursor` 없이 호출하고 이후 `next_cursor`를 그대로 보내 `null`이 될 때까지 반복합니다. `page_size`보다 짧은 페이지도 끝을 의미하지 않습니다.\n\n`capabilities`는 실제 요금제 선언만 따르며 추측하지 않습니다. 미명시 요금제는 모든 플래그가 `false`입니다. 반드시 `422`를 반환할 기능을 약속하는 것보다 가능한 버튼을 생략하는 편을 선택합니다.\n\n카탈로그에는 수량이나 재고 있음/없음 등 재고 개념이 없습니다. 공급업체가 주문을 이행할 수 없으면 `POST /v1/orders`에서 `esim.out_of_stock` 등의 명확한 오류를 반환하므로 사전 표시 필드로 추측할 필요가 없습니다.",
        "operationId": "get_catalog_packages",
        "parameters": [
          {
            "description": "페이지당 레코드 수입니다. 기본 50, 최대 100이며 더 큰 값을 보내면 오류 없이 100으로 제한됩니다.",
            "in": "query",
            "name": "page_size",
            "required": false,
            "schema": {
              "default": 50,
              "maximum": 100,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "공급 시스템은 `domestic` | `international`입니다. 목록에 없는 값은 전체 카탈로그가 아닌 `internal.invalid_filter`(400)를 반환하여 오타가 필터 없음으로 오해되지 않게 합니다.",
            "in": "query",
            "name": "market",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "ISO-3166 alpha-2 국가 코드입니다(예: `VN`). 해당 국가를 포함하는 패키지만 반환합니다.",
            "in": "query",
            "name": "country",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "지역 슬러그입니다(예: `chau-a`). 해당 지역의 국가를 하나 이상 지원하는 요금제와 모든 글로벌 요금제를 포함합니다.",
            "in": "query",
            "name": "region",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "공개 코드와 요금제 이름을 부분 검색합니다(대소문자 구분 없음).",
            "in": "query",
            "name": "q",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "하나의 상품 태그로 필터링합니다. 저장 시와 동일하게 공백을 정리하고 소문자와 하이픈으로 정규화하므로 `Ban Le`와 `ban-le`는 같은 태그입니다.",
            "in": "query",
            "name": "tag",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "데이터 유형: `daily` | `fixed` | `unlimited`. 기존 `supports_topup`을 대체합니다. 알 수 없는 값은 `internal.invalid_filter`(400)입니다.",
            "in": "query",
            "name": "data_model",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "최소 데이터 용량(**바이트**)입니다. 일일 요금제는 일일 용량으로 비교하며, 무제한 요금제는 하한 조건을 항상 충족합니다.",
            "in": "query",
            "name": "data_min_bytes",
            "required": false,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "최대 데이터 용량(**바이트**)입니다. 무제한 요금제는 제외됩니다. 무제한에 상한을 적용할 수 없으며, 포함하면 작은 요금제를 찾는 사용자에게 무제한 요금제가 제시됩니다.",
            "in": "query",
            "name": "data_max_bytes",
            "required": false,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "최소 유효기간(일)입니다.",
            "in": "query",
            "name": "days_min",
            "required": false,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "최대 유효기간(일)입니다.",
            "in": "query",
            "name": "days_max",
            "required": false,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "소속 조직의 가격과 비교하는 최소 가격(VND)입니다. 서버에서 페이지를 나눈 후 적용되므로 결과가 적더라도 마지막 페이지라는 뜻은 아닙니다.",
            "in": "query",
            "name": "price_min",
            "required": false,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "최대 가격(VND)이며 `price_min`과 같은 규칙을 따릅니다.",
            "in": "query",
            "name": "price_max",
            "required": false,
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "해당 네트워크 세대(`2g` | `3g` | `4g` | `5g`)에서 사용할 수 있는 요금제만 조회합니다. 알 수 없는 값은 `internal.invalid_filter`(400)를 반환합니다.",
            "in": "query",
            "name": "network_gen",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "`true`는 Wi-Fi 공유 지원 명시, `false`는 미지원 명시 패키지입니다. 미선언(`features.hotspot = null`)은 어느 쪽에도 해당하지 않습니다. 문자열 `true`/`false`만 허용합니다.",
            "in": "query",
            "name": "hotspot",
            "required": false,
            "schema": {
              "enum": [
                "true",
                "false"
              ],
              "type": "string"
            }
          },
          {
            "description": "최소 하나의 운영체제에서 해당 앱을 지원한다고 명시한 요금제만 조회합니다(`app=tiktok`). 미명시 요금제는 일치하지 않으며, 정보가 없다고 지원을 보장하는 것은 아닙니다. 현재 `tiktok`만 허용하고 그 외 코드는 `internal.invalid_filter`(400)를 반환합니다.",
            "in": "query",
            "name": "app",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "`true`는 음성 지원 명시, `false`는 미지원 명시 패키지입니다. 미선언은 어느 쪽에도 해당하지 않습니다. 문자열 `true`/`false`만 허용합니다.",
            "in": "query",
            "name": "voice",
            "required": false,
            "schema": {
              "enum": [
                "true",
                "false"
              ],
              "type": "string"
            }
          },
          {
            "description": "이전 `next_cursor`를 그대로 보내세요. **페이지가 짧아도 계속하고 `null`일 때만 종료하세요.** 키 제한, 조직 가격, 가격 필터는 페이지를 나눈 후 적용됩니다. 커서에는 필터 지문이 있어 다른 필터나 손상된 커서를 보내면 `catalog.cursor_mismatch`(400)를 반환해 서로 다른 조회 결과의 혼합을 막습니다.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PackageListResponse"
                }
              }
            },
            "description": "성공"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.validation_failed`, `internal.invalid_filter`, `catalog.cursor_mismatch`"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.invalid_key`, `partner.invalid_signature`, `partner.timestamp_expired`, `partner.nonce_reused`"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.ip_not_allowed`, `partner.scope_denied`, `partner.key_suspended`, `partner.key_revoked`, `org.suspended`"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.rate_limited`"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.endpoint_disabled`, `internal.service_unavailable`"
          }
        },
        "summary": "요금제 목록 조회",
        "tags": [
          "catalog"
        ],
        "x-tke-modes": [
          "live",
          "test"
        ],
        "x-tke-owner-types": [
          "organization",
          "member"
        ]
      }
    },
    "/v1/catalog/packages/{code}": {
      "get": {
        "description": "필요한 권한 범위: `catalog:read`.\n\n공개 코드로 정확히 하나의 요금제 상세를 조회합니다. `data`는 `GET /v1/catalog/packages`의 항목과 같은 필드에 `mode`만 추가됩니다. 상세 전용 필드가 없으므로 `Package` 타입 하나로 처리할 수 있습니다.\n\n보이지 않는 코드는 원인과 관계없이 `partner.package_not_visible`(404)를 반환합니다. 코드 없음, 키의 카탈로그 제한, 조직 가격 없음, 공급 연결 끊김을 구분하면 외부인이 전체 카탈로그를 추측할 수 있기 때문입니다.",
        "operationId": "get_catalog_packages__code_",
        "parameters": [
          {
            "description": "카탈로그의 `code`인 요금제 코드(`public_sku`)입니다. 공급업체가 바뀌어도 불변이므로 대사 키로 저장할 수 있습니다. 키 제한 범위 밖이거나 조직 가격이 없는 코드는 존재하지 않는 코드와 같은 `404 partner.package_not_visible`을 반환합니다.",
            "in": "path",
            "name": "code",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PackageDetail"
                }
              }
            },
            "description": "성공"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.validation_failed`"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.invalid_key`, `partner.invalid_signature`, `partner.timestamp_expired`, `partner.nonce_reused`"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.ip_not_allowed`, `partner.scope_denied`, `partner.key_suspended`, `partner.key_revoked`, `org.suspended`"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.package_not_visible`"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.rate_limited`"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.endpoint_disabled`, `internal.service_unavailable`"
          }
        },
        "summary": "요금제 한 건 조회",
        "tags": [
          "catalog"
        ],
        "x-tke-modes": [
          "live",
          "test"
        ],
        "x-tke-owner-types": [
          "organization",
          "member"
        ]
      }
    },
    "/v1/esims": {
      "get": {
        "description": "필요한 권한 범위: `esims:read`.",
        "operationId": "get_esims",
        "parameters": [
          {
            "description": "페이지당 레코드 수입니다. 기본 50, 최대 200이며 더 큰 값을 보내면 오류 없이 200으로 제한됩니다.",
            "in": "query",
            "name": "page_size",
            "required": false,
            "schema": {
              "default": 50,
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "`esim_status`로 필터링합니다. 허용 목록에 없는 값은 빈 목록 대신 `internal.invalid_filter`(400)를 반환합니다. `cancelled`에서 `l`을 빠뜨린 `canceled` 같은 오타를 해당 상태의 eSIM이 없다는 뜻으로 오해하지 않도록 합니다.",
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "enum": [
                "pending",
                "available",
                "reserved",
                "sold",
                "delivered",
                "in_use",
                "used_up",
                "expired",
                "suspended",
                "cancelled",
                "provider_failed"
              ],
              "type": "string"
            }
          },
          {
            "description": "하나의 주문에 속한 eSIM만 조회합니다.",
            "in": "query",
            "name": "order_id",
            "required": false,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "description": "ICCID로 필터링합니다(문자열, 정확히 일치).",
            "in": "query",
            "name": "iccid",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "주문 시 보낸 `external_ref`와 정확히 일치하는 주문의 모든 eSIM입니다.",
            "in": "query",
            "name": "external_ref",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "ISO-8601 UTC 형식입니다. `updated_at >= updated_since`인 레코드를 오름차순으로 반환하는 표준 조회 기반 대사 경로(§8.5)입니다. 웹훅을 놓쳐도 상태를 복원할 수 있습니다. 형식이 틀리면 `internal.invalid_filter`(400)입니다.",
            "in": "query",
            "name": "updated_since",
            "required": false,
            "schema": {
              "format": "date-time",
              "type": "string"
            }
          },
          {
            "description": "다음 페이지 커서로 이전 `next_cursor`를 그대로 보내세요. 잘못된 커서는 오류 없이 목록 처음부터 다시 읽습니다. 이는 인코딩 변경 시 호환성을 유지하기 위한 동작입니다. 첫 페이지 무한 반복을 막으려면 다음 커서가 보낸 값과 다른지 확인하세요.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "쉼표로 추가 블록을 요청합니다. `lpa`는 `install`, `qr`는 상세 조회에서만 `install.qr_code_base64`를 추가합니다. **반환된 코드는 공개된 것으로 간주**하여 해당 eSIM의 취소가 영구 차단됩니다(`cancellable.allowed = false`, `reason = code_disclosed`). 즉시 전달할 때만 요청하고 사전 주문에서는 생략해 취소 권리를 유지하세요. 알 수 없는 값은 `internal.invalid_filter`(400, `field: \"include\"`)입니다.",
            "in": "query",
            "name": "include",
            "required": false,
            "schema": {
              "example": "lpa",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EsimListResponse"
                }
              }
            },
            "description": "성공"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.validation_failed`, `internal.invalid_filter`"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.invalid_key`, `partner.invalid_signature`, `partner.timestamp_expired`, `partner.nonce_reused`"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.ip_not_allowed`, `partner.scope_denied`, `partner.key_suspended`, `partner.key_revoked`, `org.suspended`"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.rate_limited`"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.endpoint_disabled`, `internal.service_unavailable`"
          }
        },
        "summary": "eSIM 목록 조회(조회 기반 대사)",
        "tags": [
          "esims"
        ],
        "x-tke-modes": [
          "live",
          "test"
        ],
        "x-tke-owner-types": [
          "organization",
          "member"
        ]
      }
    },
    "/v1/esims/{id}": {
      "get": {
        "description": "필요한 권한 범위: `esims:read`.",
        "operationId": "get_esims__id_",
        "parameters": [
          {
            "description": "판매된 eSIM의 고정 ID입니다. 재사용될 수 있는 ICCID가 아닙니다.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "쉼표로 추가 블록을 요청합니다. `lpa`는 `install`, `qr`는 상세 조회에서만 `install.qr_code_base64`를 추가합니다. **반환된 코드는 공개된 것으로 간주**하여 해당 eSIM의 취소가 영구 차단됩니다(`cancellable.allowed = false`, `reason = code_disclosed`). 즉시 전달할 때만 요청하고 사전 주문에서는 생략해 취소 권리를 유지하세요. 알 수 없는 값은 `internal.invalid_filter`(400, `field: \"include\"`)입니다.",
            "in": "query",
            "name": "include",
            "required": false,
            "schema": {
              "example": "lpa",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Esim"
                }
              }
            },
            "description": "성공"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.validation_failed`, `internal.invalid_filter`"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.invalid_key`, `partner.invalid_signature`, `partner.timestamp_expired`, `partner.nonce_reused`"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.ip_not_allowed`, `partner.scope_denied`, `partner.key_suspended`, `partner.key_revoked`, `org.suspended`"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.not_found`"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.rate_limited`"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.endpoint_disabled`, `internal.service_unavailable`"
          }
        },
        "summary": "eSIM 한 건 조회",
        "tags": [
          "esims"
        ],
        "x-tke-modes": [
          "live",
          "test"
        ],
        "x-tke-owner-types": [
          "organization",
          "member"
        ]
      }
    },
    "/v1/esims/{id}/cancel": {
      "post": {
        "description": "필요한 권한 범위: `esims:write`.",
        "operationId": "post_esims__id__cancel",
        "parameters": [
          {
            "description": "판매된 eSIM의 고정 ID입니다. 재사용될 수 있는 ICCID가 아닙니다.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "클라이언트 생성 문자열입니다. 같은 키와 본문은 한 번만 실행되며 재시도는 원래 결과를 반환합니다. `api_key_id` 단위(§11)이므로 다른 키는 별개 명령입니다.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CancelResponse"
                }
              }
            },
            "description": "성공"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.validation_failed`"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.invalid_key`, `partner.invalid_signature`, `partner.timestamp_expired`, `partner.nonce_reused`"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.ip_not_allowed`, `partner.scope_denied`, `partner.key_suspended`, `partner.key_revoked`, `org.suspended`"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `esim.not_cancellable`, `idempotency.conflict`"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `capability.not_supported`"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.rate_limited`"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.endpoint_disabled`, `internal.service_unavailable`"
          }
        },
        "summary": "미사용 eSIM 취소",
        "tags": [
          "esims"
        ],
        "x-tke-modes": [
          "live",
          "test"
        ],
        "x-tke-owner-types": [
          "organization",
          "member"
        ]
      }
    },
    "/v1/esims/{id}/change-plan": {
      "post": {
        "description": "필요한 권한 범위: `esims:write`.",
        "operationId": "post_esims__id__change-plan",
        "parameters": [
          {
            "description": "판매된 eSIM의 고정 ID입니다. 재사용될 수 있는 ICCID가 아닙니다.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "클라이언트 생성 문자열입니다. 같은 키와 본문은 한 번만 실행되며 재시도는 원래 결과를 반환합니다. `api_key_id` 단위(§11)이므로 다른 키는 별개 명령입니다.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChangePlanRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChangePlanResponse"
                }
              }
            },
            "description": "성공"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.validation_failed`"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.invalid_key`, `partner.invalid_signature`, `partner.timestamp_expired`, `partner.nonce_reused`"
          },
          "402": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `wallet.insufficient_balance`"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.ip_not_allowed`, `partner.scope_denied`, `partner.key_suspended`, `partner.key_revoked`, `org.suspended`"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.package_not_visible`"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `esim.topup_not_supported`, `esim.topup_provider_mismatch`, `esim.not_eligible`, `idempotency.conflict`"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `capability.not_supported`"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.rate_limited`"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.endpoint_disabled`, `internal.service_unavailable`"
          }
        },
        "summary": "eSIM 충전",
        "tags": [
          "esims"
        ],
        "x-tke-modes": [
          "live",
          "test"
        ],
        "x-tke-owner-types": [
          "organization",
          "member"
        ]
      }
    },
    "/v1/esims/{id}/plan-options": {
      "get": {
        "description": "필요한 권한 범위: `esims:read`.\n\n이 eSIM에 유효한 충전 요금제만 반환합니다. 서버가 `id`로 공급업체를 확인하고 해당 공급업체의 요금제만 필터링합니다. `/v1`에는 `provider_id`가 노출되지 않으므로 서버가 대신 필터링하여 다른 공급업체 요금제를 잘못 선택할 수 없게 합니다. 목록에 없는 코드로 `POST /v1/esims/{id}/change-plan`을 호출하면 `409 esim.topup_provider_mismatch`입니다.\n\n공급업체가 연결된 적 없는 eSIM(단순 가져오기 또는 원본 정보 없음)은 빈 목록(`total: 0`)을 반환하며 오류가 아닙니다.",
        "operationId": "get_esims__id__plan-options",
        "parameters": [
          {
            "description": "판매된 eSIM의 고정 ID입니다. 재사용될 수 있는 ICCID가 아닙니다.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "페이지당 레코드 수입니다. 기본 50, 최대 200이며 더 큰 값을 보내면 오류 없이 200으로 제한됩니다.",
            "in": "query",
            "name": "page_size",
            "required": false,
            "schema": {
              "default": 50,
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "다음 페이지 커서로 이전 `next_cursor`를 그대로 보내세요. 잘못된 커서는 오류 없이 목록 처음부터 다시 읽습니다. 이는 인코딩 변경 시 호환성을 유지하기 위한 동작입니다. 첫 페이지 무한 반복을 막으려면 다음 커서가 보낸 값과 다른지 확인하세요.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlanOptionsResponse"
                }
              }
            },
            "description": "성공"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.validation_failed`"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.invalid_key`, `partner.invalid_signature`, `partner.timestamp_expired`, `partner.nonce_reused`"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.ip_not_allowed`, `partner.scope_denied`, `partner.key_suspended`, `partner.key_revoked`, `org.suspended`"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.not_found`"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.rate_limited`"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.endpoint_disabled`, `internal.service_unavailable`"
          }
        },
        "summary": "이 eSIM에 유효한 충전 패키지",
        "tags": [
          "esims"
        ],
        "x-tke-modes": [
          "live",
          "test"
        ],
        "x-tke-owner-types": [
          "organization",
          "member"
        ]
      }
    },
    "/v1/esims/{id}/refund-requests": {
      "get": {
        "description": "필요한 권한 범위: `esims:read`.\n\n승인된 실제 회원 키만 가능합니다. 회원 소유 eSIM의 최근 환불 요청을 최신순으로 최대 50개 반환하며 next_cursor와 total은 null입니다. has_open_request는 검토 대기를 나타냅니다. 조직 및 테스트 키는 capability.not_supported입니다.",
        "operationId": "get_esims__id__refund-requests",
        "parameters": [
          {
            "description": "판매된 eSIM의 고정 ID입니다. 재사용될 수 있는 ICCID가 아닙니다.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MemberRefundRequestListResponse"
                }
              }
            },
            "description": "성공"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.validation_failed`"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.invalid_key`, `partner.invalid_signature`, `partner.timestamp_expired`, `partner.nonce_reused`"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.ip_not_allowed`, `partner.scope_denied`, `partner.key_suspended`, `partner.key_revoked`, `org.suspended`"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.not_found`"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `capability.not_supported`"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.rate_limited`"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.endpoint_disabled`, `internal.service_unavailable`"
          }
        },
        "summary": "eSIM 환불 요청 기록(회원 전용)",
        "tags": [
          "esims"
        ],
        "x-tke-modes": [
          "live"
        ],
        "x-tke-owner-types": [
          "member"
        ]
      },
      "post": {
        "description": "필요한 권한 범위: `esims:write`.\n\n승인된 실제 회원 키만 가능합니다. Idempotency-Key로 회원 eSIM의 환불을 신청하며 관리자 승인 전에는 자금이 이동하지 않습니다. 조직 및 테스트 키는 capability.not_supported입니다. 테스트 모드에서는 eSIM 취소로 가상 지갑 환불을 시험하세요.",
        "operationId": "post_esims__id__refund-requests",
        "parameters": [
          {
            "description": "판매된 eSIM의 고정 ID입니다. 재사용될 수 있는 ICCID가 아닙니다.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "클라이언트 생성 문자열입니다. 같은 키와 본문은 한 번만 실행되며 재시도는 원래 결과를 반환합니다. `api_key_id` 단위(§11)이므로 다른 키는 별개 명령입니다.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MemberRefundRequestInput"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MemberRefundRequestResponse"
                }
              }
            },
            "description": "성공"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.validation_failed`, `internal.validation_failed`"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.invalid_key`, `partner.invalid_signature`, `partner.timestamp_expired`, `partner.nonce_reused`"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.ip_not_allowed`, `partner.scope_denied`, `partner.key_suspended`, `partner.key_revoked`, `org.suspended`"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.not_found`"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `esim.refund_not_eligible`, `esim.refund_request_pending`, `idempotency.conflict`"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `capability.not_supported`"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.rate_limited`"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.endpoint_disabled`, `internal.service_unavailable`"
          }
        },
        "summary": "eSIM 환불 요청 생성(회원 전용)",
        "tags": [
          "esims"
        ],
        "x-tke-modes": [
          "live"
        ],
        "x-tke-owner-types": [
          "member"
        ]
      }
    },
    "/v1/esims/{id}/usage": {
      "get": {
        "description": "필요한 권한 범위: `esims:read`.\n\neSIM의 사용량과 잔여 데이터를 값의 기준 시각 `updated_at`(실제 최신성)과 함께 조회합니다. 요청이 있을 때만 조회하는 공급사(현재 SkyFi)의 eSIM이면 이 호출은 스캔을 대기열에 넣고 결과를 최대 약 15초 기다리므로 응답에 최대 ~15초가 걸릴 수 있으며, 반환 값은 방금 끝난 스캔의 결과입니다. 스캔 실패, 같은 eSIM의 15초 간격 제한 이내, 또는 대기 시간 초과 시에는 오류를 반환하지 않고 마지막으로 저장된 값을 반환하므로 `updated_at`을 확인하세요. 다른 공급사는 주기적으로 갱신되는 저장 값을 반환합니다.",
        "operationId": "get_esims__id__usage",
        "parameters": [
          {
            "description": "판매된 eSIM의 고정 ID입니다. 재사용될 수 있는 ICCID가 아닙니다.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EsimUsage"
                }
              }
            },
            "description": "성공"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.validation_failed`"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.invalid_key`, `partner.invalid_signature`, `partner.timestamp_expired`, `partner.nonce_reused`"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.ip_not_allowed`, `partner.scope_denied`, `partner.key_suspended`, `partner.key_revoked`, `org.suspended`"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `capability.not_supported`"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.rate_limited`"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.endpoint_disabled`, `internal.service_unavailable`"
          }
        },
        "summary": "사용한 데이터",
        "tags": [
          "esims"
        ],
        "x-tke-modes": [
          "live",
          "test"
        ],
        "x-tke-owner-types": [
          "organization",
          "member"
        ]
      }
    },
    "/v1/orders": {
      "get": {
        "description": "필요한 권한 범위: `orders:read`.",
        "operationId": "get_orders",
        "parameters": [
          {
            "description": "페이지당 레코드 수입니다. 기본 50, 최대 200이며 더 큰 값을 보내면 오류 없이 200으로 제한됩니다.",
            "in": "query",
            "name": "page_size",
            "required": false,
            "schema": {
              "default": 50,
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "주문 상태로 필터링합니다. 목록에 없는 값은 `internal.invalid_filter`(400)를 반환합니다.",
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "enum": [
                "completed",
                "pending_provider",
                "provider_failed",
                "cancelled"
              ],
              "type": "string"
            }
          },
          {
            "description": "주문 확정 시 보낸 참조 코드로 필터링합니다(정확히 일치).",
            "in": "query",
            "name": "external_ref",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "ISO-8601 UTC 형식입니다. `updated_at >= updated_since`인 레코드를 오름차순으로 반환하는 표준 조회 기반 대사 경로(§8.5)입니다. 웹훅을 놓쳐도 상태를 복원할 수 있습니다. 형식이 틀리면 `internal.invalid_filter`(400)입니다.",
            "in": "query",
            "name": "updated_since",
            "required": false,
            "schema": {
              "format": "date-time",
              "type": "string"
            }
          },
          {
            "description": "다음 페이지 커서로 이전 `next_cursor`를 그대로 보내세요. 잘못된 커서는 오류 없이 목록 처음부터 다시 읽습니다. 이는 인코딩 변경 시 호환성을 유지하기 위한 동작입니다. 첫 페이지 무한 반복을 막으려면 다음 커서가 보낸 값과 다른지 확인하세요.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderListResponse"
                }
              }
            },
            "description": "성공"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.validation_failed`, `internal.invalid_filter`"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.invalid_key`, `partner.invalid_signature`, `partner.timestamp_expired`, `partner.nonce_reused`"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.ip_not_allowed`, `partner.scope_denied`, `partner.key_suspended`, `partner.key_revoked`, `org.suspended`"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.rate_limited`"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.endpoint_disabled`, `internal.service_unavailable`"
          }
        },
        "summary": "주문 목록 조회(조회 기반 대사)",
        "tags": [
          "orders"
        ],
        "x-tke-modes": [
          "live",
          "test"
        ],
        "x-tke-owner-types": [
          "organization",
          "member"
        ]
      },
      "post": {
        "description": "필요한 권한 범위: `orders:write`.",
        "operationId": "post_orders",
        "parameters": [
          {
            "description": "클라이언트 생성 문자열입니다. 같은 키와 본문은 한 번만 실행되며 재시도는 원래 결과를 반환합니다. `api_key_id` 단위(§11)이므로 다른 키는 별개 명령입니다.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateOrderRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderResponse"
                }
              }
            },
            "description": "24시간 내 같은 `Idempotency-Key`와 본문으로 재실행하면 원래 본문을 그대로 반환하고 중복 결제하지 않으며 `Idempotent-Replayed: true`를 추가합니다. 새 확정은 `201`이므로 상태 코드만으로 성공을 구분하지 마세요."
          },
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderResponse"
                }
              }
            },
            "description": "성공"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.validation_failed`, `internal.invalid_filter`"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.invalid_key`, `partner.invalid_signature`, `partner.timestamp_expired`, `partner.nonce_reused`"
          },
          "402": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `wallet.insufficient_balance`"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.ip_not_allowed`, `partner.scope_denied`, `partner.key_suspended`, `partner.key_revoked`, `org.suspended`"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.package_not_visible`"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `esim.out_of_stock`, `idempotency.conflict`"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `invoice.buyer_invalid`"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.rate_limited`"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.endpoint_disabled`, `internal.service_unavailable`"
          }
        },
        "summary": "주문 생성(직접 구매)",
        "tags": [
          "orders"
        ],
        "x-tke-modes": [
          "live",
          "test"
        ],
        "x-tke-owner-types": [
          "organization",
          "member"
        ]
      }
    },
    "/v1/orders/bulk": {
      "post": {
        "description": "필요한 권한 범위: `orders:write`.\n\n여러 줄을 일괄 주문합니다. 각 줄은 `POST /v1/orders`처럼 quote→commit을 거치는 독립 주문 한 건을 생성합니다.\n\n부분 성공 방식으로 실패한 줄은 다른 줄을 막지 않으며 성공한 줄의 금액만 차감합니다. 품절, 잔액 부족, 판매 불가, 남용 방지 제한 등은 `lines[].error`에 기록하고 배치의 HTTP 상태는 유지합니다. 도중에 잔액이 부족해도 더 저렴한 줄은 구매 가능하므로 이후 줄도 시도합니다.\n\n상태는 항상 `200`입니다. 단일 신규 리소스가 아닌 줄별 혼합 결과이므로 `201`이 아니며 요청 안에서 완료되므로 `202` 및 폴링도 없습니다.\n\n동일 `Idempotency-Key`와 동일 본문으로 재호출하면 기존 배치를 불러와 완료 결과를 그대로 반환하고 `pending` 줄만 이어서 처리하며 중복 차감하지 않습니다. 실행한 줄이 없으면 `Idempotent-Replayed: true`입니다. 같은 키에 다른 본문은 `idempotency.conflict`입니다.\n\n같은 조직이 10분 내 동일 내용으로 두 배치를 보내면 키가 달라도 실수로 중복 클릭한 것으로 간주하여 이전 배치와 `Idempotent-Replayed: true`를 반환하고 추가 차감하지 않습니다. 실제로 같은 상품을 다시 구매하려면 서명 본문에 포함된 `external_ref`를 변경하세요. 배치 구분과 이후 대사에도 사용됩니다. 모든 줄이 실패해 주문이 하나도 생성되지 않은 배치는 차단하지 않으며 10분이 지나면 다시 정상 주문할 수 있습니다.\n\n줄별 참조는 `lines[].external_ref`, 배치 참조는 응답 상단에 그대로 반환합니다.\n\n응답에는 LPA/QR이 없으며 각 `order_id`로 `GET /v1/orders/{order_id}`를 조회하세요.",
        "operationId": "post_orders_bulk",
        "parameters": [
          {
            "description": "클라이언트 생성 문자열입니다. 같은 키와 본문은 한 번만 실행되며 재시도는 원래 결과를 반환합니다. `api_key_id` 단위(§11)이므로 다른 키는 별개 명령입니다.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BulkRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkBatchResponse"
                }
              }
            },
            "description": "성공"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.validation_failed`"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.invalid_key`, `partner.invalid_signature`, `partner.timestamp_expired`, `partner.nonce_reused`"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.ip_not_allowed`, `partner.scope_denied`, `partner.key_suspended`, `partner.key_revoked`, `org.suspended`"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.package_not_visible`"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `idempotency.conflict`"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.limit_exceeded`"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.rate_limited`"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.endpoint_disabled`, `internal.service_unavailable`"
          }
        },
        "summary": "여러 줄 일괄 주문(줄마다 주문 한 건)",
        "tags": [
          "orders"
        ],
        "x-tke-modes": [
          "live",
          "test"
        ],
        "x-tke-owner-types": [
          "organization"
        ]
      }
    },
    "/v1/orders/bulk/{id}": {
      "get": {
        "description": "필요한 권한 범위: `orders:read`.\n\n제출한 일괄 주문의 줄별 결과를 다시 조회합니다. 원래 응답을 잃어도 본문을 재전송하지 않고 복구할 수 있습니다. 다른 조직 또는 다른 환경(실운영/테스트)의 배치는 `404`입니다.",
        "operationId": "get_orders_bulk__id_",
        "parameters": [
          {
            "description": "POST /v1/orders/bulk가 반환한 배치 ID(UUID)입니다。",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkBatchResponse"
                }
              }
            },
            "description": "성공"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.validation_failed`"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.invalid_key`, `partner.invalid_signature`, `partner.timestamp_expired`, `partner.nonce_reused`"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.ip_not_allowed`, `partner.scope_denied`, `partner.key_suspended`, `partner.key_revoked`, `org.suspended`"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.not_found`"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.rate_limited`"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.endpoint_disabled`, `internal.service_unavailable`"
          }
        },
        "summary": "일괄 주문 결과",
        "tags": [
          "orders"
        ],
        "x-tke-modes": [
          "live",
          "test"
        ],
        "x-tke-owner-types": [
          "organization"
        ]
      }
    },
    "/v1/orders/{id}": {
      "get": {
        "description": "필요한 권한 범위: `orders:read`.",
        "operationId": "get_orders__id_",
        "parameters": [
          {
            "description": "주문 ID(UUID)입니다.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "쉼표로 추가 블록을 요청합니다. `lpa`는 `install`, `qr`는 상세 조회에서만 `install.qr_code_base64`를 추가합니다. **반환된 코드는 공개된 것으로 간주**하여 해당 eSIM의 취소가 영구 차단됩니다(`cancellable.allowed = false`, `reason = code_disclosed`). 즉시 전달할 때만 요청하고 사전 주문에서는 생략해 취소 권리를 유지하세요. 알 수 없는 값은 `internal.invalid_filter`(400, `field: \"include\"`)입니다.",
            "in": "query",
            "name": "include",
            "required": false,
            "schema": {
              "example": "lpa",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderResponse"
                }
              }
            },
            "description": "성공"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.validation_failed`, `internal.invalid_filter`"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.invalid_key`, `partner.invalid_signature`, `partner.timestamp_expired`, `partner.nonce_reused`"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.ip_not_allowed`, `partner.scope_denied`, `partner.key_suspended`, `partner.key_revoked`, `org.suspended`"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.not_found`"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.rate_limited`"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.endpoint_disabled`, `internal.service_unavailable`"
          }
        },
        "summary": "주문 상세 및 eSIM",
        "tags": [
          "orders"
        ],
        "x-tke-modes": [
          "live",
          "test"
        ],
        "x-tke-owner-types": [
          "organization",
          "member"
        ]
      }
    },
    "/v1/orders/{id}/resend": {
      "post": {
        "description": "필요한 권한 범위: `orders:write`.",
        "operationId": "post_orders__id__resend",
        "parameters": [
          {
            "description": "주문 ID(UUID)입니다.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResendResponse"
                }
              }
            },
            "description": "성공"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.validation_failed`"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.invalid_key`, `partner.invalid_signature`, `partner.timestamp_expired`, `partner.nonce_reused`"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.ip_not_allowed`, `partner.scope_denied`, `partner.key_suspended`, `partner.key_revoked`, `org.suspended`"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `order.not_deliverable`"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.rate_limited`"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.endpoint_disabled`, `internal.service_unavailable`"
          }
        },
        "summary": "주문의 이메일/QR 재전송",
        "tags": [
          "orders"
        ],
        "x-tke-modes": [
          "live",
          "test"
        ],
        "x-tke-owner-types": [
          "organization",
          "member"
        ]
      }
    },
    "/v1/testmode/esims/{id}/simulate": {
      "post": {
        "description": "필요한 권한 범위: `esims:write`.\n\ntke_test_ 또는 tke_member_test_ 테스트 키 전용입니다. 소유자의 테스트 eSIM에 사용량, 설치 상태, 만료, 속도 제한 또는 다음 작업의 공급자 거부를 모의합니다. 본문은 최소 한 필드가 필요하며 비어 있으면 422 testmode.invalid_scenario를 반환합니다. 실제 모드와 같이 GET /v1/esims/{id}와 /usage로 결과를 읽습니다. 요금제 변경 및 취소 정책은 같으며 실제 공급자를 호출하지 않습니다.",
        "operationId": "post_testmode_esims__id__simulate",
        "parameters": [
          {
            "description": "판매된 eSIM의 고정 ID입니다. 재사용될 수 있는 ICCID가 아닙니다.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TestModeSimulateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TestModeEsimState"
                }
              }
            },
            "description": "성공"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.validation_failed`"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.invalid_key`, `partner.invalid_signature`, `partner.timestamp_expired`, `partner.nonce_reused`"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.ip_not_allowed`, `partner.scope_denied`, `partner.key_suspended`, `partner.key_revoked`, `org.suspended`, `testmode.live_key_forbidden`"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.not_found`"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `testmode.invalid_scenario`"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.rate_limited`"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.endpoint_disabled`, `internal.service_unavailable`"
          }
        },
        "summary": "테스트 eSIM 수명주기 시뮬레이션(테스트 키 전용)",
        "tags": [
          "testmode"
        ],
        "x-tke-modes": [
          "test"
        ],
        "x-tke-owner-types": [
          "organization",
          "member"
        ]
      }
    },
    "/v1/testmode/reset": {
      "post": {
        "description": "필요한 권한 범위: `orders:write`.",
        "operationId": "post_testmode_reset",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TestModeResetInput"
              }
            }
          },
          "required": false
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TestModeReset"
                }
              }
            },
            "description": "성공"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.validation_failed`"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.invalid_key`, `partner.invalid_signature`, `partner.timestamp_expired`, `partner.nonce_reused`"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.ip_not_allowed`, `partner.scope_denied`, `partner.key_suspended`, `partner.key_revoked`, `org.suspended`, `testmode.live_key_forbidden`"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.rate_limited`"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.endpoint_disabled`, `internal.service_unavailable`"
          }
        },
        "summary": "테스트 데이터 초기화(테스트 키 전용)",
        "tags": [
          "testmode"
        ],
        "x-tke-idempotency-owner-types": [
          "member"
        ],
        "x-tke-modes": [
          "test"
        ],
        "x-tke-owner-types": [
          "organization",
          "member"
        ],
        "x-tke-required-body-owner-types": [
          "member"
        ]
      }
    },
    "/v1/testmode/seed": {
      "post": {
        "description": "필요한 권한 범위: `orders:write`.",
        "operationId": "post_testmode_seed",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TestModeSeed"
                }
              }
            },
            "description": "성공"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.validation_failed`"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.invalid_key`, `partner.invalid_signature`, `partner.timestamp_expired`, `partner.nonce_reused`"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.ip_not_allowed`, `partner.scope_denied`, `partner.key_suspended`, `partner.key_revoked`, `org.suspended`, `testmode.live_key_forbidden`"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `testmode.no_sellable_package`"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.rate_limited`"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.endpoint_disabled`, `internal.service_unavailable`"
          }
        },
        "summary": "테스트 모드 샘플 데이터 생성(테스트 키 전용)",
        "tags": [
          "testmode"
        ],
        "x-tke-idempotency-owner-types": [
          "member"
        ],
        "x-tke-modes": [
          "test"
        ],
        "x-tke-owner-types": [
          "organization",
          "member"
        ]
      }
    },
    "/v1/testmode/status": {
      "get": {
        "description": "필요한 권한 범위: `esims:read`.",
        "operationId": "get_testmode_status",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TestModeStatus"
                }
              }
            },
            "description": "성공"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.validation_failed`"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.invalid_key`, `partner.invalid_signature`, `partner.timestamp_expired`, `partner.nonce_reused`"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.ip_not_allowed`, `partner.scope_denied`, `partner.key_suspended`, `partner.key_revoked`, `org.suspended`, `testmode.live_key_forbidden`"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.rate_limited`"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.endpoint_disabled`, `internal.service_unavailable`"
          }
        },
        "summary": "테스트 모드 개요(테스트 키 전용)",
        "tags": [
          "testmode"
        ],
        "x-tke-modes": [
          "test"
        ],
        "x-tke-owner-types": [
          "organization",
          "member"
        ]
      }
    },
    "/v1/testmode/webhooks/fail-next": {
      "post": {
        "description": "필요한 권한 범위: `webhook:manage`.",
        "operationId": "post_testmode_webhooks_fail-next",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TestModeFailNextRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TestModeFailNextResponse"
                }
              }
            },
            "description": "성공"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.validation_failed`, `internal.validation_failed`"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.invalid_key`, `partner.invalid_signature`, `partner.timestamp_expired`, `partner.nonce_reused`"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.ip_not_allowed`, `partner.scope_denied`, `partner.key_suspended`, `partner.key_revoked`, `org.suspended`, `testmode.live_key_forbidden`"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.not_found`"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.rate_limited`"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.endpoint_disabled`, `internal.service_unavailable`"
          }
        },
        "summary": "다음 웹훅 실패 시뮬레이션(테스트 키 전용)",
        "tags": [
          "webhook"
        ],
        "x-tke-modes": [
          "test"
        ],
        "x-tke-owner-types": [
          "organization"
        ]
      }
    },
    "/v1/testmode/webhooks/fire": {
      "post": {
        "description": "필요한 권한 범위: `webhook:manage`.",
        "operationId": "post_testmode_webhooks_fire",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TestModeWebhookFireRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimulateResponse"
                }
              }
            },
            "description": "성공"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.validation_failed`"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.invalid_key`, `partner.invalid_signature`, `partner.timestamp_expired`, `partner.nonce_reused`"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.ip_not_allowed`, `partner.scope_denied`, `partner.key_suspended`, `partner.key_revoked`, `org.suspended`, `testmode.live_key_forbidden`"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `webhook.not_configured`, `internal.not_found`"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.rate_limited`"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.endpoint_disabled`, `internal.service_unavailable`"
          }
        },
        "summary": "테스트 웹훅 이벤트 전송(테스트 키 전용)",
        "tags": [
          "webhook"
        ],
        "x-tke-modes": [
          "test"
        ],
        "x-tke-owner-types": [
          "organization"
        ]
      }
    },
    "/v1/wallet/balance": {
      "get": {
        "description": "필요한 권한 범위: `wallet:read`.",
        "operationId": "get_wallet_balance",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WalletBalance"
                }
              }
            },
            "description": "성공"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.validation_failed`"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.invalid_key`, `partner.invalid_signature`, `partner.timestamp_expired`, `partner.nonce_reused`"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.ip_not_allowed`, `partner.scope_denied`, `partner.key_suspended`, `partner.key_revoked`, `org.suspended`"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.rate_limited`"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.endpoint_disabled`, `internal.service_unavailable`"
          }
        },
        "summary": "지갑 잔액",
        "tags": [
          "wallet"
        ],
        "x-tke-modes": [
          "live",
          "test"
        ],
        "x-tke-owner-types": [
          "organization",
          "member"
        ]
      }
    },
    "/v1/webhooks": {
      "get": {
        "description": "필요한 권한 범위: `webhook:manage`.\n\n호출한 API 키의 웹훅 엔드포인트만 반환합니다. 같은 조직의 두 키라도 다른 키의 엔드포인트를 볼 수 없습니다(§5.11: `api_key_id`에 연결되며 테스트와 실운영은 공유하지 않음).\n\n아직 설정하지 않았으면 `404`가 아닌 빈 배열과 `200`을 반환합니다. 컬렉션은 항상 존재하며 항목만 없을 수 있습니다.",
        "operationId": "get_webhooks",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookListResponse"
                }
              }
            },
            "description": "성공"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.validation_failed`"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.invalid_key`, `partner.invalid_signature`, `partner.timestamp_expired`, `partner.nonce_reused`"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.ip_not_allowed`, `partner.scope_denied`, `partner.key_suspended`, `partner.key_revoked`, `org.suspended`"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.rate_limited`"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.endpoint_disabled`, `internal.service_unavailable`"
          }
        },
        "summary": "웹훅 엔드포인트 목록 조회",
        "tags": [
          "webhook"
        ],
        "x-tke-modes": [
          "live",
          "test"
        ],
        "x-tke-owner-types": [
          "organization"
        ]
      },
      "post": {
        "description": "필요한 권한 범위: `webhook:manage`.\n\n호출한 키의 웹훅 엔드포인트를 생성합니다. 저장 전에 서버가 URL로 서명한 `ping` POST를 보냅니다(CHECK_HEALTH). 2xx가 아니면 저장하지 않고 `422 webhook.health_check_failed`입니다. 공개 `https` URL만 허용하며 내부/메타데이터 IP는 `422 webhook.url_not_allowed`입니다.\n\n`webhook_secret`는 생성 시 한 번만 표시하며 다시 읽을 수 없습니다. 분실하면 대시보드에서 교체해야 하며 이전 비밀키도 24시간 함께 유효합니다(§8.4).\n\n이미 엔드포인트가 있으면 일시 중지(`is_active: false`) 상태여도 `409 webhook.already_configured`입니다. 중지는 URL·비밀키·로그를 보존합니다. 새로 시작하려면 `DELETE /v1/webhooks/{id}` 후 생성하세요.",
        "operationId": "post_webhooks",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateWebhookResponse"
                }
              }
            },
            "description": "성공"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.validation_failed`"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.invalid_key`, `partner.invalid_signature`, `partner.timestamp_expired`, `partner.nonce_reused`"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.ip_not_allowed`, `partner.scope_denied`, `partner.key_suspended`, `partner.key_revoked`, `org.suspended`"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `webhook.already_configured`"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `webhook.health_check_failed`, `webhook.url_not_allowed`"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.rate_limited`"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.endpoint_disabled`, `internal.service_unavailable`"
          }
        },
        "summary": "웹훅 엔드포인트 생성",
        "tags": [
          "webhook"
        ],
        "x-tke-modes": [
          "live",
          "test"
        ],
        "x-tke-owner-types": [
          "organization"
        ]
      }
    },
    "/v1/webhooks/deliveries": {
      "get": {
        "description": "필요한 권한 범위: `webhook:manage`.",
        "operationId": "get_webhooks_deliveries",
        "parameters": [
          {
            "description": "1부터 시작하는 페이지 번호입니다. 마지막 페이지를 넘으면 `items: []`와 실제 `total`을 반환합니다(200, 404 아님).",
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "default": 1,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "페이지당 레코드 수입니다. 기본 50, 최대 200이며 더 큰 값을 보내면 오류 없이 200으로 제한됩니다.",
            "in": "query",
            "name": "page_size",
            "required": false,
            "schema": {
              "default": 50,
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "이벤트 유형으로 필터링합니다(웹훅 이벤트 목록 참조).",
            "in": "query",
            "name": "event_type",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "전송 상태로 필터링합니다. `?status=failed`는 조회 기반 웹훅 대사(§13)에 사용합니다. 알 수 없는 값은 오류 없이 무시하며 전체 로그를 반환합니다.",
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "enum": [
                "pending",
                "delivered",
                "failed"
              ],
              "type": "string"
            }
          },
          {
            "description": "한 이벤트의 모든 전송 시도이며 재전송도 포함합니다.",
            "in": "query",
            "name": "event_id",
            "required": false,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeliveryListResponse"
                }
              }
            },
            "description": "성공"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.validation_failed`"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.invalid_key`, `partner.invalid_signature`, `partner.timestamp_expired`, `partner.nonce_reused`"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.ip_not_allowed`, `partner.scope_denied`, `partner.key_suspended`, `partner.key_revoked`, `org.suspended`"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `webhook.not_configured`"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.rate_limited`"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.endpoint_disabled`, `internal.service_unavailable`"
          }
        },
        "summary": "웹훅 전송 기록",
        "tags": [
          "webhook"
        ],
        "x-tke-modes": [
          "live",
          "test"
        ],
        "x-tke-owner-types": [
          "organization"
        ]
      }
    },
    "/v1/webhooks/deliveries/{id}/replay": {
      "post": {
        "description": "필요한 권한 범위: `webhook:manage`.",
        "operationId": "post_webhooks_deliveries__id__replay",
        "parameters": [
          {
            "description": "웹훅 전송 한 건의 ID입니다(`GET /v1/webhooks/deliveries`의 `items[].id`).",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeliveryReplayResponse"
                }
              }
            },
            "description": "성공"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.validation_failed`"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.invalid_key`, `partner.invalid_signature`, `partner.timestamp_expired`, `partner.nonce_reused`"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.ip_not_allowed`, `partner.scope_denied`, `partner.key_suspended`, `partner.key_revoked`, `org.suspended`"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `webhook.delivery_not_found`, `webhook.not_configured`"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.rate_limited`"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.endpoint_disabled`, `internal.service_unavailable`"
          }
        },
        "summary": "웹훅 재전송",
        "tags": [
          "webhook"
        ],
        "x-tke-modes": [
          "live",
          "test"
        ],
        "x-tke-owner-types": [
          "organization"
        ]
      }
    },
    "/v1/webhooks/{id}": {
      "delete": {
        "description": "필요한 권한 범위: `webhook:manage`.\n\n엔드포인트를 제거하면 호출 키의 새 이벤트 수신이 중지됩니다.\n\n`webhook_secret`도 함께 사라집니다. `POST /v1/webhooks`로 재생성하면 새 `id`와 새 비밀키가 발급되므로 검증 함수를 수정해야 합니다. 비밀키를 유지하는 일시 중지는 대시보드의 중지 버튼을 사용하세요.\n\n전체 전송 로그는 대사용으로 유지되지만 삭제한 엔드포인트의 전송은 재시도할 수 없습니다.\n\n재시도 대기 중인 `pending` 전송은 `endpoint_disabled`로 중지되고 로그에는 남습니다(§8.5).\n\n다른 키의 `id` 또는 이미 삭제한 `id`는 조용히 200을 반환하지 않고 `404 webhook.not_found`입니다.",
        "operationId": "delete_webhooks__id_",
        "parameters": [
          {
            "description": "웹훅 엔드포인트 ID입니다(`POST /v1/webhooks` 또는 `GET /v1/webhooks`의 `id`).",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteWebhookResponse"
                }
              }
            },
            "description": "성공"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.validation_failed`"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.invalid_key`, `partner.invalid_signature`, `partner.timestamp_expired`, `partner.nonce_reused`"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.ip_not_allowed`, `partner.scope_denied`, `partner.key_suspended`, `partner.key_revoked`, `org.suspended`"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `webhook.not_found`"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.rate_limited`"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.endpoint_disabled`, `internal.service_unavailable`"
          }
        },
        "summary": "웹훅 엔드포인트 제거(새 이벤트 수신 중지)",
        "tags": [
          "webhook"
        ],
        "x-tke-modes": [
          "live",
          "test"
        ],
        "x-tke-owner-types": [
          "organization"
        ]
      },
      "get": {
        "description": "필요한 권한 범위: `webhook:manage`.",
        "operationId": "get_webhooks__id_",
        "parameters": [
          {
            "description": "웹훅 엔드포인트 ID입니다(`POST /v1/webhooks` 또는 `GET /v1/webhooks`의 `id`).",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookConfig"
                }
              }
            },
            "description": "성공"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.validation_failed`"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.invalid_key`, `partner.invalid_signature`, `partner.timestamp_expired`, `partner.nonce_reused`"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.ip_not_allowed`, `partner.scope_denied`, `partner.key_suspended`, `partner.key_revoked`, `org.suspended`"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `webhook.not_found`"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.rate_limited`"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.endpoint_disabled`, `internal.service_unavailable`"
          }
        },
        "summary": "웹훅 엔드포인트 한 건 조회",
        "tags": [
          "webhook"
        ],
        "x-tke-modes": [
          "live",
          "test"
        ],
        "x-tke-owner-types": [
          "organization"
        ]
      },
      "put": {
        "description": "필요한 권한 범위: `webhook:manage`.",
        "operationId": "put_webhooks__id_",
        "parameters": [
          {
            "description": "웹훅 엔드포인트 ID입니다(`POST /v1/webhooks` 또는 `GET /v1/webhooks`의 `id`).",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookConfig"
                }
              }
            },
            "description": "성공"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `internal.validation_failed`"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.invalid_key`, `partner.invalid_signature`, `partner.timestamp_expired`, `partner.nonce_reused`"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.ip_not_allowed`, `partner.scope_denied`, `partner.key_suspended`, `partner.key_revoked`, `org.suspended`"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `webhook.not_found`"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `webhook.health_check_failed`, `webhook.url_not_allowed`"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.rate_limited`"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "오류: `partner.endpoint_disabled`, `internal.service_unavailable`"
          }
        },
        "summary": "웹훅 엔드포인트 수정",
        "tags": [
          "webhook"
        ],
        "x-tke-modes": [
          "live",
          "test"
        ],
        "x-tke-owner-types": [
          "organization"
        ]
      }
    }
  },
  "security": [
    {
      "TkeHmac": []
    }
  ],
  "servers": [
    {
      "description": "Live",
      "url": "https://api.tongkhoesim.com"
    },
    {
      "description": "테스트 모드",
      "url": "https://api-testing.tongkhoesim.com"
    }
  ],
  "tags": [
    {
      "description": "두 공급 시스템을 통합한 하나의 요금제 카탈로그입니다. 시스템은 별도 경로가 아닌 `market` 필드(`domestic` | `international`)와 `?market=` 필터로 구분합니다.\n\n수량이나 `available`/`low`/`out_of_stock` 같은 재고 개념은 없습니다. 요금제를 표시하고 공급업체가 제공할 수 없는 주문은 `POST /v1/orders`에서 `esim.out_of_stock` 등의 명확한 오류를 반환합니다.\n\n통일된 커서 페이지 처리를 사용합니다. `total`은 집계 비용이 적을 때(국내 시스템 필터)에만 제공하며 그 외에는 `null`입니다.",
      "name": "catalog"
    },
    {
      "description": "주문 생성 및 대사",
      "name": "orders"
    },
    {
      "description": "eSIM 기록, 사용량, 충전 및 취소",
      "name": "esims"
    },
    {
      "description": "지갑 잔액",
      "name": "wallet"
    },
    {
      "description": "웹훅 설정, 전송 기록 및 시뮬레이터",
      "name": "webhook"
    },
    {
      "description": "api-testing 호스트에서 tke_test_ 또는 tke_member_test_ 테스트 키만 사용하세요. 실제 잔액이나 공급자 없이 소유자의 테스트 eSIM과 데이터를 모의합니다. 회원 테스트 모드는 웹훅, 대량 주문, 검토용 환불 요청을 지원하지 않습니다.",
      "name": "testmode"
    }
  ]
}
