{
  "openapi": "3.0.3",
  "info": {
    "title": "OOLIN Wallet API",
    "version": "1.0.0",
    "description": "지갑(Wallet) API 서버 - 계정, 입금 주소, 잔액, 출금/내부이체, 자산/네트워크 정보 등을 제공한다.\n\n### 공통 응답\n모든 API는 `{ success, data, error }` envelope를 사용한다. 금액은 정밀도 손실을 피하기 위해 문자열로 전달하며, `*_raw`는 자산 최소 단위의 정수 문자열이다. 모든 일시는 UTC ISO 8601 형식이다.\n\n### 인증 (HMAC API Key)\n보호된 API 호출 시 다음 헤더가 필수다:\n- `X-API-KEY`: 클라이언트 API 키\n- `X-TIMESTAMP`: 요청 시간 (Unix Epoch milliseconds 권장, ISO 8601도 허용)\n- `X-NONCE`: 5분 안에 재사용하지 않는 고유 난수 (UUID v4 권장)\n- `X-SIGNATURE`: HMAC-SHA256 서명 (Base64)\n\n**StringToSign 생성 규칙:** 각 항목은 줄바꿈 2개(`\\n\\n`)로 연결한다.\n```text\n{HTTP_METHOD}\\n\\n{REQUEST_PATH_WITH_QUERY}\\n\\n{TIMESTAMP_EPOCH_MS}\\n\\n{X-NONCE}\\n\\n{REQUEST_BODY_JSON}\n```\n- `REQUEST_PATH_WITH_QUERY`는 호스트를 제외한 실제 요청 경로와 쿼리 문자열 전체다. 파라미터 순서와 percent-encoding도 전송값과 같아야 한다.\n- `X-TIMESTAMP`가 ISO 8601이면 epoch milliseconds로 변환한 문자열을 `TIMESTAMP_EPOCH_MS`에 사용한다. 헤더와 서명 모두 epoch milliseconds 사용을 권장한다. 서버 허용 오차는 ±5분이다.\n- GET/DELETE 요청 시 `REQUEST_BODY_JSON`은 빈 문자열이다.\n- POST/PUT/PATCH 요청은 실제 전송되는 `JSON.stringify(body)` 결과를 그대로 사용한다. 공백·키 순서가 달라지면 서명이 달라진다.\n- `signature = BASE64(HMAC-SHA256(hmac_key, stringToSign))`\n- 재시도할 때는 timestamp와 nonce를 새로 만들고 서명을 다시 계산한다.\n\n**Node.js 서명 예제:**\n```js\nimport { createHmac, randomUUID } from 'node:crypto';\n\nconst method = 'POST';\nconst pathQuery = '/withdrawals';\nconst timestamp = String(Date.now());\nconst nonce = randomUUID();\nconst bodyJson = JSON.stringify({\n  account_id: 1, asset_type_id: 18, amount: '25',\n  to_address: '0x1111111111111111111111111111111111111111', network_id: 31,\n  client_request_id: 'wd-20260819-000001'\n});\nconst stringToSign = [method, pathQuery, timestamp, nonce, bodyJson].join('\\n\\n');\nconst signature = createHmac('sha256', hmacKey).update(stringToSign).digest('base64');\nconst headers = {\n  'Content-Type': 'application/json',\n  'X-API-KEY': apiKey, 'X-TIMESTAMP': timestamp,\n  'X-NONCE': nonce, 'X-SIGNATURE': signature\n};\n```\n\n### 공개 API\n`/time`, `/health`, `/version`, `/prices`, `/docs`, `/openapi.json`은 인증 헤더 없이 호출할 수 있다. `/health`는 현재 프로세스 생존 확인용 정적 응답이며 실제 의존성 연결 상태를 검사하지 않는다."
  },
  "servers": [
    {
      "url": "https://{environmentApiHost}",
      "description": "Use the environment Base URL assigned by BPMG during onboarding",
      "variables": {
        "environmentApiHost": {
          "default": "api-host-provided-by-bpmg.invalid",
          "description": "Replace this placeholder with the host assigned for your environment"
        }
      }
    }
  ],
  "security": [
    {
      "ApiKeyAuth": [],
      "ApiTimestamp": [],
      "ApiNonce": [],
      "ApiSignature": []
    }
  ],
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-KEY",
        "description": "클라이언트 API 키.",
        "x-example": "ak_test_key_12345"
      },
      "ApiTimestamp": {
        "type": "apiKey",
        "in": "header",
        "name": "X-TIMESTAMP",
        "description": "요청 생성 시간 (Unix Epoch Milliseconds 또는 ISO8601). ISO8601을 보내더라도 StringToSign에는 서버가 변환하는 epoch milliseconds 문자열을 사용한다.",
        "x-example": "1722668280000"
      },
      "ApiNonce": {
        "type": "apiKey",
        "in": "header",
        "name": "X-NONCE",
        "description": "요청 중복 방지를 위한 고유값 (UUID v4 권장).",
        "x-example": "b7e28325-2e69-4f7d-8e6f-1234567890ab"
      },
      "ApiSignature": {
        "type": "apiKey",
        "in": "header",
        "name": "X-SIGNATURE",
        "description": "HMAC-SHA256 서명값. 생성 방법은 상세 설명 참조.",
        "x-example": "base64-encoded-hmac-signature"
      }
    },
    "schemas": {
      "ApiSuccess": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              true
            ],
            "example": true,
            "description": "항상 true"
          },
          "data": {
            "type": "object",
            "nullable": true
          },
          "error": {
            "type": "object",
            "nullable": true,
            "example": null
          }
        },
        "required": [
          "success",
          "data",
          "error"
        ]
      },
      "ApiError": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              false
            ],
            "example": false,
            "description": "항상 false"
          },
          "data": {
            "type": "object",
            "nullable": true,
            "example": null
          },
          "error": {
            "type": "object",
            "nullable": false,
            "properties": {
              "code": {
                "type": "string",
                "description": "프로그램 분기에 사용하는 안정적인 오류 코드. 인증: MISSING_AUTH_HEADER=인증 헤더 누락, INVALID_API_KEY=API Key 오류, INVALID_TIMESTAMP=시각 오류, NONCE_REPLAYED=nonce 재사용, INVALID_SIGNATURE=서명 오류. 요청: MISSING_REQUIRED_FIELD=필수값 누락, INVALID_FIELD_VALUE=형식·범위 오류, INVALID_AMOUNT=금액 오류, INVALID_TO_ADDRESS=주소 오류. 상태: *_NOT_ACTIVE=사용자·계정 비활성. 리소스: *_NOT_FOUND=해당 리소스 없음. 출금: SAME_ACCOUNT_TRANSFER_NOT_ALLOWED=동일 계정 이체 금지, AMOUNT_BELOW_MINIMUM/AMOUNT_ABOVE_MAXIMUM=출금 한도 위반, INSUFFICIENT_BALANCE=잔액 부족, WITHDRAWAL_NOT_CANCELLABLE=취소 불가. 가용성: SERVICE_MAINTENANCE=점검, *_UNAVAILABLE=일시 이용 불가, ADDRESS_POOL_EXHAUSTED=입금 주소 부족. 충돌: ADDRESS_POOL_CLAIM_CONFLICT=주소 선점 충돌, CONFLICT=일반 충돌. RATE_LIMITED=호출 제한, INTERNAL_ERROR=내부 오류. message 문자열로 분기하지 않는다.",
                "enum": [
                  "UNAUTHORIZED",
                  "MISSING_AUTH_HEADER",
                  "INVALID_API_KEY",
                  "INVALID_TIMESTAMP",
                  "NONCE_REPLAYED",
                  "INVALID_SIGNATURE",
                  "FORBIDDEN",
                  "INVALID_REQUEST",
                  "MISSING_REQUIRED_FIELD",
                  "INVALID_FIELD_VALUE",
                  "INVALID_AMOUNT",
                  "INVALID_TO_ADDRESS",
                  "SAME_ACCOUNT_TRANSFER_NOT_ALLOWED",
                  "AMOUNT_BELOW_MINIMUM",
                  "AMOUNT_ABOVE_MAXIMUM",
                  "USER_NOT_ACTIVE",
                  "ACCOUNT_NOT_ACTIVE",
                  "RECIPIENT_USER_NOT_ACTIVE",
                  "RECIPIENT_ACCOUNT_NOT_ACTIVE",
                  "NOT_FOUND",
                  "ACCOUNT_NOT_FOUND",
                  "BALANCE_NOT_FOUND",
                  "DEPOSIT_NOT_FOUND",
                  "LEDGER_NOT_FOUND",
                  "WITHDRAWAL_NOT_FOUND",
                  "WITHDRAWAL_NOT_CANCELLABLE",
                  "NETWORK_NOT_FOUND",
                  "ASSET_TYPE_NOT_FOUND",
                  "ASSET_NOT_FOUND",
                  "MAINTENANCE_NOT_FOUND",
                  "MAINTENANCE_ALREADY_ENDED",
                  "ADDRESS_POOL_EXHAUSTED",
                  "ADDRESS_POOL_CLAIM_CONFLICT",
                  "CONFLICT",
                  "RATE_LIMITED",
                  "INSUFFICIENT_BALANCE",
                  "SERVICE_MAINTENANCE",
                  "NETWORK_UNAVAILABLE",
                  "ASSET_UNAVAILABLE",
                  "SERVICE_UNAVAILABLE",
                  "INTERNAL_ERROR"
                ],
                "example": "MISSING_REQUIRED_FIELD"
              },
              "message": {
                "type": "string",
                "example": "uid is required"
              },
              "request_id": {
                "type": "string",
                "description": "장애 문의 및 서버 로그 추적용 요청 ID. 응답 헤더 x-request-id와 동일하다.",
                "example": "V1StGXR8_Z5jdHi6B-myT"
              },
              "action": {
                "type": "string",
                "description": "고객사 백엔드의 권장 후속 조치. PROVIDE_REQUIRED_FIELDS=누락값 제공, CORRECT_FIELD_VALUE=입력값 수정, REPLACE_API_KEY=API Key 교체, REGENERATE_SIGNATURE=서명 재생성, SYNC_SYSTEM_TIME=시각 동기화, GENERATE_NEW_NONCE=nonce 재생성, REQUEST_ACCESS=권한 요청, CHECK_RESOURCE_ID=리소스 ID 확인, ADJUST_AMOUNT=금액 조정, USE_DIFFERENT_ADDRESS=다른 주소 사용, ACTIVATE_USER=사용자 활성화, ACTIVATE_ACCOUNT=계정 활성화, USE_DIFFERENT_ACCOUNT=다른 계정 사용, INCREASE_BALANCE=잔액 확보, RESOLVE_CONFLICT=충돌 상태 확인·해소, RETRY_LATER=나중에 제한적으로 재시도, CONTACT_SUPPORT=request_id로 문의",
                "enum": [
                  "PROVIDE_REQUIRED_FIELDS",
                  "CORRECT_FIELD_VALUE",
                  "REPLACE_API_KEY",
                  "REGENERATE_SIGNATURE",
                  "SYNC_SYSTEM_TIME",
                  "GENERATE_NEW_NONCE",
                  "REQUEST_ACCESS",
                  "CHECK_RESOURCE_ID",
                  "ADJUST_AMOUNT",
                  "USE_DIFFERENT_ADDRESS",
                  "ACTIVATE_USER",
                  "ACTIVATE_ACCOUNT",
                  "USE_DIFFERENT_ACCOUNT",
                  "INCREASE_BALANCE",
                  "RESOLVE_CONFLICT",
                  "RETRY_LATER",
                  "CONTACT_SUPPORT"
                ],
                "example": "CORRECT_FIELD_VALUE"
              },
              "details": {
                "type": "object",
                "nullable": true,
                "additionalProperties": true,
                "description": "action 수행에 필요한 구조화된 추가 정보. 오류 코드별로 필드가 다르며 확장될 수 있다.",
                "example": {
                  "fields": [
                    "uid"
                  ]
                }
              }
            },
            "required": [
              "code",
              "message",
              "request_id",
              "action"
            ]
          }
        },
        "required": [
          "success",
          "data",
          "error"
        ]
      },
      "Account": {
        "type": "object",
        "example": {
          "account_id": 1,
          "uid": "user-001",
          "account_type": "USER",
          "status": "ACTIVE",
          "created_at": "2026-08-19T05:00:00.000Z",
          "updated_at": "2026-08-19T05:30:00.000Z",
          "metadata": {
            "ok": true,
            "data": {
              "customer_grade": "GOLD"
            }
          }
        },
        "properties": {
          "account_id": {
            "type": "integer",
            "format": "int64",
            "example": 1
          },
          "uid": {
            "type": "string",
            "example": "user-001"
          },
          "account_type": {
            "type": "string",
            "enum": [
              "USER",
              "BUSINESS"
            ],
            "example": "USER",
            "description": "USER=개인 사용자 계정, BUSINESS=법인·사업자 계정"
          },
          "status": {
            "type": "string",
            "enum": [
              "ACTIVE",
              "LOCKED",
              "DISABLED"
            ],
            "example": "ACTIVE",
            "description": "ACTIVE=정상 이용 가능, LOCKED=잠금 상태, DISABLED=비활성 상태"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "example": "2026-08-19T05:00:00.000Z"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "example": "2026-08-19T05:30:00.000Z"
          },
          "metadata": {
            "allOf": [
              {
                "$ref": "#/components/schemas/JsonSerdeResult"
              }
            ],
            "description": "metadata JSON (역)직렬화 결과"
          }
        },
        "required": [
          "account_id",
          "uid",
          "account_type",
          "status",
          "created_at",
          "updated_at",
          "metadata"
        ]
      },
      "LockAccountResult": {
        "type": "object",
        "example": {
          "account_id": 1,
          "status": "LOCKED",
          "locked_at": "2026-08-19T05:30:00.000Z"
        },
        "properties": {
          "account_id": {
            "type": "integer",
            "format": "int64",
            "example": 1
          },
          "status": {
            "type": "string",
            "example": "LOCKED"
          },
          "locked_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "account_id",
          "status",
          "locked_at"
        ]
      },
      "UnlockAccountResult": {
        "type": "object",
        "example": {
          "account_id": 1,
          "status": "ACTIVE",
          "unlocked_at": "2026-08-19T05:35:00.000Z"
        },
        "properties": {
          "account_id": {
            "type": "integer",
            "format": "int64",
            "example": 1
          },
          "status": {
            "type": "string",
            "example": "ACTIVE"
          },
          "unlocked_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "account_id",
          "status",
          "unlocked_at"
        ]
      },
      "CreateDepositAddressResult": {
        "type": "object",
        "example": {
          "address_id": 901,
          "account_id": 1,
          "asset_type_id": "18",
          "network_id": "31",
          "network_name": "Ethereum Sepolia",
          "address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F",
          "tag_or_memo": null,
          "created_at": "2026-08-19T05:30:00.000Z"
        },
        "properties": {
          "address_id": {
            "type": "integer",
            "format": "int64",
            "example": 1
          },
          "account_id": {
            "type": "integer",
            "format": "int64",
            "example": 1
          },
          "asset_type_id": {
            "type": "string"
          },
          "network_id": {
            "type": "string"
          },
          "network_name": {
            "type": "string",
            "description": "네트워크 표시 이름"
          },
          "address": {
            "type": "string"
          },
          "tag_or_memo": {
            "type": "string",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "address_id",
          "account_id",
          "asset_type_id",
          "network_id",
          "network_name",
          "address",
          "tag_or_memo",
          "created_at"
        ]
      },
      "DepositAddressListItem": {
        "type": "object",
        "example": {
          "address_id": 901,
          "account_id": 1,
          "asset_type_id": "18",
          "network_id": "31",
          "network_name": "Ethereum Sepolia",
          "address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F",
          "tag_or_memo": null,
          "created_at": "2026-08-19T05:30:00.000Z"
        },
        "properties": {
          "address_id": {
            "type": "integer",
            "format": "int64",
            "example": 1
          },
          "account_id": {
            "type": "integer",
            "format": "int64",
            "example": 1
          },
          "asset_type_id": {
            "type": "string",
            "nullable": true,
            "example": "18"
          },
          "network_id": {
            "type": "string",
            "example": "31"
          },
          "network_name": {
            "type": "string",
            "example": "Ethereum Sepolia",
            "description": "네트워크 표시 이름"
          },
          "address": {
            "type": "string",
            "example": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F"
          },
          "tag_or_memo": {
            "type": "string",
            "nullable": true,
            "example": null,
            "description": "주소 태그 또는 메모. EVM 입금 주소에서는 null"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "example": "2026-08-19T05:30:00.000Z"
          }
        },
        "required": [
          "address_id",
          "account_id",
          "asset_type_id",
          "network_id",
          "network_name",
          "address",
          "tag_or_memo",
          "created_at"
        ]
      },
      "BalanceItem": {
        "type": "object",
        "description": "원시 잔액은 최소 단위 정수 문자열이다. 표시 금액은 raw / 10^decimals로 계산한다.",
        "example": {
          "account_id": 1,
          "asset_type_id": 18,
          "asset_type_name": "USD Coin",
          "symbol": "USDC",
          "decimals": 6,
          "available_amount_raw": "125000000",
          "pending_withdraw_amount_raw": "5000000",
          "total_amount_raw": "130000000",
          "valuation_krw": "178100",
          "valuation_usd": "130",
          "updated_at": "2026-08-19T05:30:00.000Z"
        },
        "properties": {
          "account_id": {
            "type": "integer",
            "format": "int64",
            "description": "잔액 소유 계정 ID"
          },
          "asset_type_id": {
            "type": "integer"
          },
          "asset_type_name": {
            "type": "string"
          },
          "symbol": {
            "type": "string"
          },
          "decimals": {
            "type": "integer"
          },
          "available_amount_raw": {
            "type": "string"
          },
          "pending_withdraw_amount_raw": {
            "type": "string"
          },
          "total_amount_raw": {
            "type": "string"
          },
          "valuation_krw": {
            "type": "string",
            "nullable": true
          },
          "valuation_usd": {
            "type": "string",
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        },
        "required": [
          "account_id",
          "asset_type_id",
          "asset_type_name",
          "symbol",
          "decimals",
          "available_amount_raw",
          "pending_withdraw_amount_raw",
          "total_amount_raw",
          "valuation_krw",
          "valuation_usd",
          "updated_at"
        ]
      },
      "GetAllBalancesResult": {
        "type": "object",
        "example": {
          "account_id": 1,
          "total_balance_krw": "178100",
          "total_balance_usd": "130",
          "items": [
            {
              "account_id": 1,
              "asset_type_id": 18,
              "asset_type_name": "USD Coin",
              "symbol": "USDC",
              "decimals": 6,
              "available_amount_raw": "125000000",
              "pending_withdraw_amount_raw": "5000000",
              "total_amount_raw": "130000000",
              "valuation_krw": "178100",
              "valuation_usd": "130",
              "updated_at": "2026-08-19T05:30:00.000Z"
            }
          ]
        },
        "properties": {
          "account_id": {
            "type": "integer",
            "format": "int64",
            "example": 1
          },
          "total_balance_krw": {
            "type": "string",
            "nullable": true
          },
          "total_balance_usd": {
            "type": "string",
            "nullable": true
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BalanceItem"
            }
          }
        },
        "required": [
          "account_id",
          "total_balance_krw",
          "total_balance_usd",
          "items"
        ]
      },
      "GetSingleBalanceResult": {
        "type": "object",
        "example": {
          "account_id": 1,
          "asset_type_id": 18,
          "asset_type_name": "USD Coin",
          "symbol": "USDC",
          "decimals": 6,
          "available_amount_raw": "125000000",
          "pending_withdraw_amount_raw": "5000000",
          "total_amount_raw": "130000000",
          "valuation_krw": "178100",
          "valuation_usd": "130",
          "updated_at": "2026-08-19T05:30:00.000Z"
        },
        "properties": {
          "account_id": {
            "type": "integer",
            "format": "int64",
            "example": 1
          },
          "asset_type_id": {
            "type": "integer"
          },
          "asset_type_name": {
            "type": "string"
          },
          "symbol": {
            "type": "string"
          },
          "decimals": {
            "type": "integer"
          },
          "available_amount_raw": {
            "type": "string"
          },
          "pending_withdraw_amount_raw": {
            "type": "string"
          },
          "total_amount_raw": {
            "type": "string"
          },
          "valuation_krw": {
            "type": "string",
            "nullable": true
          },
          "valuation_usd": {
            "type": "string",
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        },
        "required": [
          "account_id",
          "asset_type_id",
          "asset_type_name",
          "symbol",
          "decimals",
          "available_amount_raw",
          "pending_withdraw_amount_raw",
          "total_amount_raw",
          "valuation_krw",
          "valuation_usd",
          "updated_at"
        ]
      },
      "JsonSerdeResult": {
        "example": {
          "ok": true,
          "data": {
            "customer_grade": "GOLD"
          }
        },
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "ok": {
                "type": "boolean",
                "enum": [
                  true
                ],
                "example": true,
                "description": "직렬화 또는 역직렬화 성공"
              },
              "data": {
                "type": "object",
                "nullable": true,
                "example": {
                  "customer_grade": "GOLD"
                }
              }
            },
            "required": [
              "ok",
              "data"
            ]
          },
          {
            "type": "object",
            "properties": {
              "ok": {
                "type": "boolean",
                "enum": [
                  false
                ],
                "description": "직렬화 또는 역직렬화 실패"
              },
              "error": {
                "type": "string",
                "enum": [
                  "JSON_PARSE_ERROR",
                  "JSON_STRINGIFY_ERROR"
                ],
                "description": "JSON_PARSE_ERROR=저장값 역직렬화 실패, JSON_STRINGIFY_ERROR=요청 metadata 직렬화 실패"
              },
              "raw": {
                "type": "string",
                "nullable": true
              }
            },
            "required": [
              "ok",
              "error"
            ]
          }
        ]
      },
      "DepositListItem": {
        "type": "object",
        "description": "외부 입금과 내부이체 입금을 동일한 표시 모델로 반환한다. 금액 비교·정산에는 `amount_raw`와 `decimals`를 사용한다.",
        "example": {
          "deposit_id": 551,
          "account_id": 1,
          "asset_type_id": "18",
          "asset_type_code": "USDC",
          "asset_type_name": "USD Coin",
          "asset_id": "36",
          "network_id": "31",
          "network_code": "sepolia",
          "network_display_name": "Ethereum Sepolia",
          "decimals": 6,
          "tx_hash": "0x7f3d9d8c4a12",
          "from_address": "0x1111111111111111111111111111111111111111",
          "to_address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F",
          "amount": "125.5",
          "amount_raw": "125500000",
          "status": "COMPLETED",
          "type": "EXTERNAL",
          "market_price_krw": "1370.25",
          "market_price_usd": "1",
          "created_at": "2026-08-19T05:20:00.000Z",
          "confirmed_at": "2026-08-19T05:22:30.000Z",
          "refund_withdrawal_id": null
        },
        "properties": {
          "deposit_id": {
            "type": "integer",
            "format": "int64",
            "example": 1
          },
          "account_id": {
            "type": "integer",
            "format": "int64",
            "example": 1
          },
          "asset_type_id": {
            "type": "string",
            "example": "1"
          },
          "asset_type_code": {
            "type": "string",
            "example": "BTC"
          },
          "asset_type_name": {
            "type": "string",
            "example": "Bitcoin"
          },
          "asset_id": {
            "type": "string",
            "example": "1"
          },
          "network_id": {
            "type": "string",
            "example": "1"
          },
          "network_code": {
            "type": "string",
            "example": "BTC"
          },
          "network_display_name": {
            "type": "string",
            "example": "Bitcoin"
          },
          "decimals": {
            "type": "integer",
            "example": 8
          },
          "tx_hash": {
            "type": "string",
            "nullable": true,
            "example": "0x..."
          },
          "from_address": {
            "type": "string",
            "nullable": true
          },
          "to_address": {
            "type": "string",
            "nullable": true
          },
          "amount": {
            "type": "string",
            "example": "0.1"
          },
          "amount_raw": {
            "type": "string",
            "example": "10000000"
          },
          "status": {
            "type": "string",
            "enum": [
              "PENDING",
              "INSPECTED",
              "APPROVE_PENDING",
              "APPROVED",
              "VERIFIED",
              "REFUND_REQUIRED",
              "REFUND_REQUESTED",
              "REFUND_PENDING",
              "COMPLETED",
              "REFUNDED",
              "FAILED"
            ],
            "example": "COMPLETED",
            "description": "외부 입금은 컨펌·승인·환불 등을 포함한 상세 처리 상태를 반환한다. 내부 입금은 이체 완료 시 COMPLETED이며 그 외에는 PENDING으로 반환한다."
          },
          "type": {
            "type": "string",
            "enum": [
              "EXTERNAL",
              "INTERNAL"
            ],
            "description": "EXTERNAL=온체인 외부 입금, INTERNAL=플랫폼 내부이체 입금"
          },
          "market_price_krw": {
            "type": "string",
            "nullable": true,
            "example": "50000000"
          },
          "market_price_usd": {
            "type": "string",
            "nullable": true,
            "example": "40000"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "confirmed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "example": "2026-08-19T05:22:30.000Z",
            "description": "입금 완료 시각. 상태가 COMPLETED일 때 반환하며 그 외에는 null이다."
          },
          "refund_withdrawal_id": {
            "type": "integer",
            "format": "int64",
            "nullable": true,
            "example": null,
            "description": "환불 출금 연계 ID. 현재 API에서는 항상 null"
          }
        },
        "required": [
          "deposit_id",
          "account_id",
          "asset_type_id",
          "asset_type_code",
          "asset_type_name",
          "asset_id",
          "network_id",
          "network_code",
          "network_display_name",
          "decimals",
          "tx_hash",
          "from_address",
          "to_address",
          "amount",
          "amount_raw",
          "status",
          "type",
          "market_price_krw",
          "market_price_usd",
          "created_at",
          "confirmed_at",
          "refund_withdrawal_id"
        ]
      },
      "DepositDetail": {
        "$ref": "#/components/schemas/DepositListItem"
      },
      "LedgerItem": {
        "type": "object",
        "description": "계정 잔액 증감의 원장 분개. `amount_raw`는 항상 절댓값이며 증감 방향은 `entry_type`으로 판별한다.",
        "example": {
          "ledger_id": 120001,
          "ref_type": 1000,
          "ref_id": "551",
          "transaction_type": 1000,
          "transaction_hash": "0x7f3d9d8c4a12",
          "transfer_type": "EXTERNAL",
          "from_account_id": null,
          "to_account_id": 1,
          "from_address": "0x1111111111111111111111111111111111111111",
          "to_address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F",
          "from_user_id": null,
          "to_user_id": "user-001",
          "account_id": 1,
          "asset_type_id": 18,
          "asset_type_code": "USDC",
          "asset_id": "36",
          "network_id": "31",
          "network_code": "sepolia",
          "entry_type": "CREDIT",
          "entry_code": 1000,
          "entry_seq": 1,
          "amount": "125.5",
          "amount_raw": "125500000",
          "decimals": 6,
          "balance_after": "130",
          "balance_after_raw": "130000000",
          "market_price_krw": "1370.25",
          "market_price_usd": "1",
          "metadata": null,
          "created_at": "2026-08-19T05:22:30.000Z"
        },
        "properties": {
          "ledger_id": {
            "type": "integer",
            "format": "int64",
            "example": 1
          },
          "ref_type": {
            "type": "integer",
            "enum": [
              1000,
              2000
            ],
            "example": 1000,
            "description": "참조 원천 코드. 1000=입금 이벤트, 2000=출금 요청",
            "x-enumDescriptions": {
              "1000": "입금 이벤트",
              "2000": "출금 요청"
            }
          },
          "ref_id": {
            "type": "string",
            "example": "1"
          },
          "transaction_type": {
            "type": "integer",
            "enum": [
              1000,
              2000,
              3000,
              4000,
              5000
            ],
            "example": 1000,
            "description": "거래 유형 코드. 1000=외부 입금, 2000=외부 출금, 3000=내부이체 출금, 4000=내부이체 입금, 5000=관리자 조정",
            "x-enumDescriptions": {
              "1000": "외부 입금",
              "2000": "외부 출금",
              "3000": "내부이체 출금",
              "4000": "내부이체 입금",
              "5000": "관리자 조정"
            }
          },
          "transaction_hash": {
            "type": "string",
            "nullable": true,
            "example": "0x..."
          },
          "transfer_type": {
            "type": "string",
            "enum": [
              "EXTERNAL",
              "INTERNAL"
            ],
            "example": "EXTERNAL",
            "description": "EXTERNAL=외부 체인 전송, INTERNAL=플랫폼 내부 계정 이체"
          },
          "from_account_id": {
            "type": "integer",
            "format": "int64",
            "nullable": true,
            "example": 1
          },
          "to_account_id": {
            "type": "integer",
            "format": "int64",
            "nullable": true,
            "example": 2
          },
          "from_address": {
            "type": "string",
            "nullable": true,
            "example": "0xSender"
          },
          "to_address": {
            "type": "string",
            "nullable": true,
            "example": "0xRecipient"
          },
          "from_user_id": {
            "type": "string",
            "nullable": true,
            "example": "user-001"
          },
          "to_user_id": {
            "type": "string",
            "nullable": true,
            "example": "user-002"
          },
          "account_id": {
            "type": "integer",
            "format": "int64",
            "example": 1
          },
          "asset_type_id": {
            "type": "integer",
            "example": 1
          },
          "asset_type_code": {
            "type": "string",
            "example": "BTC"
          },
          "asset_id": {
            "type": "string",
            "example": "1"
          },
          "network_id": {
            "type": "string",
            "example": "1"
          },
          "network_code": {
            "type": "string",
            "example": "BTC"
          },
          "entry_type": {
            "type": "string",
            "enum": [
              "CREDIT",
              "DEBIT"
            ],
            "example": "CREDIT",
            "description": "CREDIT=잔액 증가 분개, DEBIT=잔액 감소 분개"
          },
          "amount": {
            "type": "string",
            "example": "1.5"
          },
          "amount_raw": {
            "type": "string",
            "example": "150000000"
          },
          "decimals": {
            "type": "integer",
            "example": 8
          },
          "balance_after": {
            "type": "string",
            "nullable": true,
            "example": "10.5"
          },
          "balance_after_raw": {
            "type": "string",
            "nullable": true,
            "example": "1050000000"
          },
          "market_price_krw": {
            "type": "string",
            "nullable": true,
            "example": "50000000"
          },
          "market_price_usd": {
            "type": "string",
            "nullable": true,
            "example": "40000"
          },
          "entry_code": {
            "type": "integer",
            "enum": [
              1000,
              2100,
              2200,
              3000,
              4000
            ],
            "example": 1000,
            "description": "분개 성격 코드. 1000=원금, 2100=서비스 수수료, 2200=네트워크 수수료, 3000=환불, 4000=관리자 조정",
            "x-enumDescriptions": {
              "1000": "원금",
              "2100": "서비스 수수료",
              "2200": "네트워크 수수료",
              "3000": "환불",
              "4000": "관리자 조정"
            }
          },
          "entry_seq": {
            "type": "integer",
            "example": 1
          },
          "metadata": {
            "type": "object",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "ledger_id",
          "ref_type",
          "ref_id",
          "transaction_type",
          "transaction_hash",
          "transfer_type",
          "from_account_id",
          "to_account_id",
          "from_address",
          "to_address",
          "from_user_id",
          "to_user_id",
          "account_id",
          "asset_type_id",
          "asset_type_code",
          "asset_id",
          "network_id",
          "network_code",
          "entry_type",
          "entry_code",
          "entry_seq",
          "amount",
          "amount_raw",
          "decimals",
          "balance_after",
          "balance_after_raw",
          "market_price_krw",
          "market_price_usd",
          "metadata",
          "created_at"
        ]
      },
      "PriceItem": {
        "type": "object",
        "example": {
          "asset_type_id": 18,
          "fiat": "KRW",
          "price": "1370.25",
          "updated_at": "2026-08-19T05:30:00.000Z"
        },
        "properties": {
          "asset_type_id": {
            "type": "integer",
            "example": 1
          },
          "fiat": {
            "type": "string",
            "example": "KRW"
          },
          "price": {
            "type": "string",
            "example": "50000000"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "asset_type_id",
          "fiat",
          "price",
          "updated_at"
        ]
      },
      "PriceList": {
        "type": "object",
        "example": {
          "items": [
            {
              "asset_type_id": 18,
              "fiat": "KRW",
              "price": "1370.25",
              "updated_at": "2026-08-19T05:30:00.000Z"
            }
          ]
        },
        "properties": {
          "items": {
            "type": "array",
            "example": [
              {
                "asset_type_id": 18,
                "fiat": "KRW",
                "price": "1370.25",
                "updated_at": "2026-08-19T05:30:00.000Z"
              }
            ],
            "items": {
              "$ref": "#/components/schemas/PriceItem"
            }
          }
        },
        "required": [
          "items"
        ]
      },
      "ReconLedgerEntry": {
        "type": "object",
        "example": {
          "ledger_id": 120001,
          "ref_type": 1000,
          "ref_id": 551,
          "transaction_type": 1000,
          "account_id": 1,
          "asset_type_id": 18,
          "network_id": 31,
          "entry_type": 1000,
          "entry_code": 1000,
          "entry_seq": 1,
          "amount_raw": "125500000",
          "balance_after_raw": "130000000",
          "created_at": "2026-08-19T05:22:30.000Z"
        },
        "properties": {
          "ledger_id": {
            "type": "integer",
            "format": "int64",
            "example": 120001
          },
          "ref_type": {
            "type": "integer",
            "enum": [
              1000,
              2000
            ],
            "example": 1000,
            "description": "참조 원천 코드. 1000=입금 이벤트, 2000=출금 요청",
            "x-enumDescriptions": {
              "1000": "입금 이벤트",
              "2000": "출금 요청"
            }
          },
          "ref_id": {
            "type": "integer",
            "example": 551
          },
          "transaction_type": {
            "type": "integer",
            "enum": [
              1000,
              2000,
              3000,
              4000,
              5000
            ],
            "example": 1000,
            "description": "거래 유형 코드. 1000=외부 입금, 2000=외부 출금, 3000=내부이체 출금, 4000=내부이체 입금, 5000=관리자 조정",
            "x-enumDescriptions": {
              "1000": "외부 입금",
              "2000": "외부 출금",
              "3000": "내부이체 출금",
              "4000": "내부이체 입금",
              "5000": "관리자 조정"
            }
          },
          "account_id": {
            "type": "integer",
            "example": 501
          },
          "asset_type_id": {
            "type": "integer",
            "example": 10
          },
          "network_id": {
            "type": "integer",
            "nullable": true,
            "example": 1,
            "description": "참조 원천(입금 또는 출금·내부이체)의 네트워크 ID. 연결된 원천이나 네트워크 값이 없으면 null"
          },
          "entry_type": {
            "type": "integer",
            "enum": [
              1000,
              2000
            ],
            "example": 1000,
            "description": "분개 방향 코드. 1000=잔액 증가(CREDIT), 2000=잔액 감소(DEBIT)",
            "x-enumDescriptions": {
              "1000": "잔액 증가(CREDIT)",
              "2000": "잔액 감소(DEBIT)"
            }
          },
          "entry_code": {
            "type": "integer",
            "enum": [
              1000,
              2100,
              2200,
              3000,
              4000
            ],
            "example": 1000,
            "description": "분개 성격 코드. 1000=원금(PRINCIPAL), 2100=서비스 수수료(SERVICE_FEE), 2200=네트워크 수수료(NETWORK_FEE), 3000=환불(REFUND), 4000=정정(ADJUSTMENT)",
            "x-enumDescriptions": {
              "1000": "원금(PRINCIPAL)",
              "2100": "서비스 수수료(SERVICE_FEE)",
              "2200": "네트워크 수수료(NETWORK_FEE)",
              "3000": "환불(REFUND)",
              "4000": "정정(ADJUSTMENT)"
            }
          },
          "entry_seq": {
            "type": "integer",
            "example": 1
          },
          "amount_raw": {
            "type": "string",
            "example": "1000000",
            "description": "자산 최소 단위의 절댓값 정수 문자열. 증감 방향은 entry_type으로 판별"
          },
          "balance_after_raw": {
            "type": "string",
            "nullable": true,
            "example": "9500000",
            "description": "분개 반영 직후 총잔액의 최소 단위 정수 문자열. 과거 데이터는 null일 수 있음"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "원장 분개 생성 시각(UTC ISO-8601)"
          }
        },
        "required": [
          "ledger_id",
          "ref_type",
          "ref_id",
          "transaction_type",
          "account_id",
          "asset_type_id",
          "network_id",
          "entry_type",
          "entry_code",
          "entry_seq",
          "amount_raw",
          "balance_after_raw",
          "created_at"
        ]
      },
      "ReconTransaction": {
        "type": "object",
        "example": {
          "reference_id": 8001,
          "transaction_type": 2000,
          "account_id": 1,
          "asset_type_id": 18,
          "network_id": 31,
          "amount_raw": "125500000",
          "fee_raw": "1000000",
          "transfer_type": 1000,
          "counterparty_account_id": null,
          "is_refund": false,
          "status": 9000,
          "tx_hash": "0x7f3d9d8c4a12",
          "requested_at": "2026-08-19T05:30:00.000Z",
          "completed_at": "2026-08-19T05:35:00.000Z",
          "updated_at": "2026-08-19T05:35:00.000Z"
        },
        "properties": {
          "reference_id": {
            "type": "integer",
            "example": 551,
            "description": "거래 ID. 증분 조회의 커서로 사용한다."
          },
          "transaction_type": {
            "type": "integer",
            "enum": [
              1000,
              2000
            ],
            "example": 1000,
            "description": "원천 거래 유형 코드. 1000=입금 이벤트, 2000=출금·내부이체 요청",
            "x-enumDescriptions": {
              "1000": "입금 이벤트",
              "2000": "출금·내부이체 요청"
            }
          },
          "account_id": {
            "type": "integer",
            "nullable": true,
            "example": 100,
            "description": "입금은 입금 계정 ID이며 아직 계정에 매핑되지 않은 입금은 null. 출금은 from_account_id이며 항상 숫자"
          },
          "asset_type_id": {
            "type": "integer",
            "example": 3
          },
          "network_id": {
            "type": "integer",
            "nullable": true,
            "example": 1,
            "description": "온체인 네트워크 ID. 내부이체 등에서는 null일 수 있음"
          },
          "amount_raw": {
            "type": "string",
            "example": "5000000",
            "description": "수수료 미포함 원금"
          },
          "fee_raw": {
            "type": "string",
            "nullable": true,
            "example": "10000",
            "description": "DEPOSIT은 null. 외부 출금 금액 대사는 amount + fee로 비교"
          },
          "transfer_type": {
            "type": "integer",
            "nullable": true,
            "enum": [
              1000,
              2000,
              null
            ],
            "description": "이체 유형 코드. 1000=외부 체인 출금, 2000=플랫폼 내부이체, null=입금 거래",
            "x-enumDescriptions": {
              "1000": "외부 체인 출금",
              "2000": "플랫폼 내부이체",
              "null": "입금 거래로 이체 유형 없음"
            }
          },
          "counterparty_account_id": {
            "type": "integer",
            "nullable": true,
            "description": "내부이체 수취 계정(to_account_id). 입금과 외부 출금은 null"
          },
          "is_refund": {
            "type": "boolean",
            "nullable": true,
            "description": "출금의 환불 목적 여부. 출금은 항상 boolean, 입금은 null"
          },
          "status": {
            "type": "integer",
            "example": 3000,
            "description": "transaction_type에 따른 상태 코드. 입금/출금 상태별 의미는 이 엔드포인트의 status 파라미터 설명과 동일"
          },
          "tx_hash": {
            "type": "string",
            "nullable": true
          },
          "requested_at": {
            "type": "string",
            "format": "date-time"
          },
          "completed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "입금은 COMPLETED일 때 입금 완료 시각을 반환하며 그 외에는 null. 출금은 출금 완료 시각을 반환한다."
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "reference_id",
          "transaction_type",
          "account_id",
          "asset_type_id",
          "network_id",
          "amount_raw",
          "fee_raw",
          "transfer_type",
          "counterparty_account_id",
          "is_refund",
          "status",
          "tx_hash",
          "requested_at",
          "completed_at",
          "updated_at"
        ]
      },
      "ReconBalance": {
        "type": "object",
        "example": {
          "account_id": 1,
          "asset_type_id": 18,
          "total_balance_raw": "130000000",
          "available_balance_raw": "125000000",
          "locked_balance_raw": "5000000"
        },
        "properties": {
          "account_id": {
            "type": "integer",
            "example": 500
          },
          "asset_type_id": {
            "type": "integer",
            "example": 10
          },
          "total_balance_raw": {
            "type": "string",
            "example": "10000000"
          },
          "available_balance_raw": {
            "type": "string",
            "example": "9000000"
          },
          "locked_balance_raw": {
            "type": "string",
            "example": "1000000"
          }
        },
        "required": [
          "account_id",
          "asset_type_id",
          "total_balance_raw",
          "available_balance_raw",
          "locked_balance_raw"
        ]
      },
      "ReconLedgerSummaryItem": {
        "type": "object",
        "example": {
          "account_id": 1,
          "asset_type_id": 18,
          "credit_amount_raw": "500000000",
          "debit_amount_raw": "300000000",
          "net_amount_raw": "200000000",
          "entry_count": 12
        },
        "properties": {
          "account_id": {
            "type": "integer",
            "description": "group_by=account일 때만 포함"
          },
          "asset_type_id": {
            "type": "integer",
            "example": 3
          },
          "credit_amount_raw": {
            "type": "string",
            "example": "500000000"
          },
          "debit_amount_raw": {
            "type": "string",
            "example": "300000000"
          },
          "net_amount_raw": {
            "type": "string",
            "example": "200000000",
            "description": "credit - debit"
          },
          "entry_count": {
            "type": "integer",
            "example": 1200
          }
        },
        "required": [
          "asset_type_id",
          "credit_amount_raw",
          "debit_amount_raw",
          "net_amount_raw",
          "entry_count"
        ]
      },
      "CoinType": {
        "type": "object",
        "example": {
          "id": 60,
          "slip44": 60,
          "symbol": "ETH",
          "name": "Ethereum",
          "key_algo": "secp256k1",
          "address_format": "hex",
          "purpose": 44,
          "created_at": "2026-01-01T00:00:00.000Z",
          "updated_at": "2026-08-19T05:30:00.000Z"
        },
        "properties": {
          "id": {
            "type": "integer",
            "example": 60
          },
          "slip44": {
            "type": "integer",
            "example": 60
          },
          "symbol": {
            "type": "string",
            "example": "ETH"
          },
          "name": {
            "type": "string",
            "example": "Ethereum"
          },
          "key_algo": {
            "type": "string",
            "example": "secp256k1"
          },
          "address_format": {
            "type": "string",
            "example": "hex"
          },
          "purpose": {
            "type": "integer",
            "example": 44
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "slip44",
          "symbol",
          "name",
          "key_algo",
          "address_format",
          "purpose",
          "created_at",
          "updated_at"
        ]
      },
      "Network": {
        "type": "object",
        "example": {
          "network_id": 31,
          "chain_family_id": 1,
          "network_name": "Ethereum Sepolia",
          "network_display_name": "Ethereum Sepolia",
          "network_code": "sepolia",
          "chain_id": 11155111,
          "coin_type_id": 60,
          "slip44": 60,
          "native_symbol": "ETH",
          "explorer_url": "https://sepolia.etherscan.io",
          "is_active": true,
          "created_at": "2026-01-01T00:00:00.000Z",
          "updated_at": "2026-08-19T05:30:00.000Z"
        },
        "properties": {
          "network_id": {
            "type": "integer",
            "example": 1
          },
          "chain_family_id": {
            "type": "integer",
            "nullable": true,
            "example": 1
          },
          "network_name": {
            "type": "string",
            "example": "Ethereum Mainnet"
          },
          "network_display_name": {
            "type": "string",
            "example": "Ethereum"
          },
          "network_code": {
            "type": "string",
            "example": "ethereum"
          },
          "chain_id": {
            "type": "integer",
            "nullable": true,
            "example": 1
          },
          "coin_type_id": {
            "type": "integer",
            "nullable": true,
            "example": 60
          },
          "slip44": {
            "type": "integer",
            "example": 60
          },
          "native_symbol": {
            "type": "string",
            "example": "ETH"
          },
          "explorer_url": {
            "type": "string",
            "nullable": true,
            "example": "https://etherscan.io"
          },
          "is_active": {
            "type": "boolean",
            "example": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "network_id",
          "chain_family_id",
          "network_name",
          "network_display_name",
          "network_code",
          "chain_id",
          "coin_type_id",
          "slip44",
          "native_symbol",
          "explorer_url",
          "is_active",
          "created_at",
          "updated_at"
        ]
      },
      "AssetType": {
        "type": "object",
        "example": {
          "id": 18,
          "code": "USDC",
          "name": "USD Coin",
          "symbol": "USDC",
          "decimals": 6,
          "symbol_image_url": "https://assets.example.com/usdc.png",
          "description": "USD 연동 스테이블코인",
          "is_stablecoin": true,
          "created_at": "2026-01-01T00:00:00.000Z",
          "updated_at": "2026-08-19T05:30:00.000Z"
        },
        "properties": {
          "id": {
            "type": "integer",
            "example": 1
          },
          "code": {
            "type": "string",
            "example": "ETH"
          },
          "name": {
            "type": "string",
            "example": "Ethereum"
          },
          "symbol": {
            "type": "string",
            "example": "ETH"
          },
          "decimals": {
            "type": "integer",
            "example": 18
          },
          "symbol_image_url": {
            "type": "string",
            "nullable": true
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "is_stablecoin": {
            "type": "boolean",
            "example": false
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "code",
          "name",
          "symbol",
          "decimals",
          "symbol_image_url",
          "is_stablecoin",
          "created_at",
          "updated_at"
        ]
      },
      "Asset": {
        "type": "object",
        "example": {
          "asset_id": 36,
          "asset_type_id": 18,
          "asset_type_name": "USD Coin",
          "network_id": 31,
          "network_code": "sepolia",
          "network_display_name": "Ethereum Sepolia",
          "network_name": "Ethereum Sepolia",
          "chain_family_id": 1,
          "chain_family_name": "EVM",
          "symbol": "USDC",
          "contract_address": "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
          "decimals": 6,
          "is_native": false,
          "is_active": true,
          "created_at": "2026-01-01T00:00:00.000Z",
          "updated_at": "2026-08-19T05:30:00.000Z"
        },
        "properties": {
          "asset_id": {
            "type": "integer",
            "example": 1
          },
          "asset_type_id": {
            "type": "integer",
            "example": 1
          },
          "asset_type_name": {
            "type": "string",
            "example": "Ethereum"
          },
          "network_id": {
            "type": "integer",
            "example": 1
          },
          "network_code": {
            "type": "string",
            "example": "ethereum"
          },
          "network_display_name": {
            "type": "string",
            "example": "Ethereum"
          },
          "network_name": {
            "type": "string",
            "example": "Ethereum Mainnet"
          },
          "chain_family_id": {
            "type": "integer",
            "example": 1
          },
          "chain_family_name": {
            "type": "string",
            "example": "EVM"
          },
          "symbol": {
            "type": "string",
            "example": "ETH"
          },
          "contract_address": {
            "type": "string",
            "nullable": true,
            "example": null
          },
          "decimals": {
            "type": "integer",
            "example": 18
          },
          "is_native": {
            "type": "boolean",
            "example": true
          },
          "is_active": {
            "type": "boolean",
            "example": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "asset_id",
          "asset_type_id",
          "asset_type_name",
          "network_id",
          "network_code",
          "network_display_name",
          "network_name",
          "chain_family_id",
          "chain_family_name",
          "symbol",
          "contract_address",
          "decimals",
          "is_native",
          "is_active",
          "created_at",
          "updated_at"
        ]
      },
      "ValidateAddressResult": {
        "type": "object",
        "description": "주소 검사 자체가 수행되면 유효하지 않은 주소도 HTTP 200과 `is_valid=false`로 반환된다.",
        "example": {
          "is_valid": true,
          "is_contract_address": false,
          "needs_tag_or_memo": false,
          "normalized_address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F"
        },
        "properties": {
          "is_valid": {
            "type": "boolean",
            "example": true
          },
          "is_contract_address": {
            "type": "boolean",
            "nullable": true,
            "example": false
          },
          "needs_tag_or_memo": {
            "type": "boolean",
            "example": false
          },
          "normalized_address": {
            "type": "string",
            "nullable": true,
            "example": "0xabc...def"
          }
        },
        "required": [
          "is_valid",
          "is_contract_address",
          "needs_tag_or_memo",
          "normalized_address"
        ]
      },
      "SystemTime": {
        "type": "object",
        "example": {
          "server_time": "2026-08-19T05:30:00.000Z",
          "server_time_epoch_ms": 1787117400000
        },
        "properties": {
          "server_time": {
            "type": "string",
            "format": "date-time",
            "example": "2024-03-21T10:00:00.000Z",
            "description": "ISO 8601 형식의 서버 시간"
          },
          "server_time_epoch_ms": {
            "type": "integer",
            "example": 1711015200000,
            "description": "Unix 타임스탬프 (ms)"
          }
        },
        "required": [
          "server_time",
          "server_time_epoch_ms"
        ]
      },
      "SystemHealth": {
        "type": "object",
        "example": {
          "status": "UP",
          "dependencies": {
            "db": "UP",
            "redis": "UP",
            "ethereum_node": "UP",
            "tron_node": "UP"
          }
        },
        "properties": {
          "status": {
            "type": "string",
            "example": "UP",
            "description": "전체 상태"
          },
          "dependencies": {
            "type": "object",
            "description": "현재는 실제 probe 결과가 아니라 호환성을 위한 정적 UP 값이다.",
            "properties": {
              "db": {
                "type": "string",
                "example": "UP"
              },
              "redis": {
                "type": "string",
                "example": "UP"
              },
              "ethereum_node": {
                "type": "string",
                "example": "UP"
              },
              "tron_node": {
                "type": "string",
                "example": "UP"
              }
            }
          }
        },
        "required": [
          "status",
          "dependencies"
        ]
      },
      "SystemVersion": {
        "type": "object",
        "example": {
          "version": "1.0.0",
          "build": "20260819.1",
          "git_commit": "a1b2c3d4e5f6"
        },
        "properties": {
          "version": {
            "type": "string",
            "example": "1.0.0",
            "description": "버전"
          },
          "build": {
            "type": "string",
            "example": "123",
            "description": "빌드 ID"
          },
          "git_commit": {
            "type": "string",
            "example": "abcdef123456",
            "description": "Git 커밋 해시"
          }
        },
        "required": [
          "version",
          "build",
          "git_commit"
        ]
      },
      "UserAccount": {
        "type": "object",
        "example": {
          "account_id": 1,
          "uid": "user-001",
          "account_type": "USER",
          "status": "ACTIVE",
          "created_at": "2026-08-19T05:00:00.000Z",
          "updated_at": "2026-08-19T05:30:00.000Z",
          "metadata": {
            "ok": true,
            "data": {
              "customer_grade": "GOLD"
            }
          }
        },
        "properties": {
          "account_id": {
            "type": "integer",
            "format": "int64",
            "example": 1
          },
          "uid": {
            "type": "string",
            "example": "user-001"
          },
          "account_type": {
            "type": "string",
            "enum": [
              "USER",
              "BUSINESS"
            ],
            "example": "USER",
            "description": "USER=개인 사용자 계정, BUSINESS=법인·사업자 계정"
          },
          "status": {
            "type": "string",
            "enum": [
              "ACTIVE",
              "LOCKED",
              "DISABLED"
            ],
            "example": "ACTIVE",
            "description": "ACTIVE=정상 이용 가능, LOCKED=잠금 상태, DISABLED=비활성 상태"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "metadata": {
            "allOf": [
              {
                "$ref": "#/components/schemas/JsonSerdeResult"
              }
            ],
            "description": "metadata JSON 역직렬화 결과"
          }
        },
        "required": [
          "account_id",
          "uid",
          "account_type",
          "status",
          "created_at",
          "updated_at",
          "metadata"
        ]
      },
      "QuoteWithdrawalReq": {
        "type": "object",
        "example": {
          "account_id": 1,
          "asset_type_id": 18,
          "amount": "125.5",
          "to_address": "0x1111111111111111111111111111111111111111",
          "network_id": 31
        },
        "required": [
          "account_id",
          "asset_type_id",
          "amount",
          "to_address",
          "network_id"
        ],
        "properties": {
          "account_id": {
            "type": "integer",
            "minimum": 1,
            "description": "1 이상의 정수 ID",
            "example": 1
          },
          "asset_type_id": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              }
            ],
            "example": 1
          },
          "amount": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "number"
              }
            ],
            "example": "10.5",
            "description": "사람이 읽는 소수 단위 금액. 부동소수점 오차 방지를 위해 문자열 사용 권장"
          },
          "to_address": {
            "type": "string",
            "example": "0x1111111111111111111111111111111111111111",
            "description": "수취 주소. 플랫폼이 관리하는 입금 주소이면 내부이체로 판별될 수 있음"
          },
          "network_id": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              }
            ],
            "example": 1
          }
        }
      },
      "CreateWithdrawalReq": {
        "type": "object",
        "example": {
          "account_id": 1,
          "asset_type_id": 18,
          "amount": "125.5",
          "to_address": "0x1111111111111111111111111111111111111111",
          "network_id": 31,
          "client_request_id": "wd-20260819-000001"
        },
        "required": [
          "account_id",
          "asset_type_id",
          "amount",
          "to_address",
          "network_id"
        ],
        "properties": {
          "account_id": {
            "type": "integer",
            "minimum": 1,
            "description": "1 이상의 정수 ID",
            "example": 1
          },
          "asset_type_id": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              }
            ],
            "example": 1
          },
          "amount": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "number"
              }
            ],
            "example": "10.5",
            "description": "사람이 읽는 소수 단위 금액. 문자열 사용 권장"
          },
          "to_address": {
            "type": "string",
            "example": "0x1111111111111111111111111111111111111111"
          },
          "network_id": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              }
            ],
            "example": 1
          },
          "client_request_id": {
            "type": "string",
            "nullable": true,
            "example": "wd-20260819-000001",
            "description": "고객사 생성 요청 고유 ID. 응답 유실 복구 및 멱등성 확인에 사용"
          }
        }
      },
      "CreateInternalTransferReq": {
        "type": "object",
        "example": {
          "from_account_id": 1,
          "to_account_id": 2,
          "asset_type_id": 18,
          "amount": "25",
          "client_request_id": "it-20260819-000001"
        },
        "required": [
          "from_account_id",
          "to_account_id",
          "asset_type_id",
          "amount"
        ],
        "properties": {
          "from_account_id": {
            "type": "integer",
            "minimum": 1,
            "description": "1 이상의 정수 ID",
            "example": 1
          },
          "to_account_id": {
            "type": "integer",
            "minimum": 1,
            "description": "1 이상의 정수 ID",
            "example": 2
          },
          "asset_type_id": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              }
            ],
            "example": 1
          },
          "amount": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "number"
              }
            ],
            "example": "10.5"
          },
          "client_request_id": {
            "type": "string",
            "nullable": true,
            "example": "it-20260819-000001",
            "description": "고객사 생성 요청 고유 ID"
          }
        }
      },
      "WithdrawalQuote": {
        "type": "object",
        "example": {
          "asset_id": 36,
          "asset_type_id": 18,
          "asset_type_code": "USDC",
          "asset_type_name": "USD Coin",
          "network_id": 31,
          "network_code": "sepolia",
          "network_display_name": "Ethereum Sepolia",
          "decimals": 6,
          "amount": "125.5",
          "fee_amount": "1",
          "receive_amount": "125.5",
          "min_amount": "10",
          "max_amount": "10000",
          "estimated_block_time_sec": 15,
          "transfer_type": "EXTERNAL",
          "can_withdraw": true,
          "reason": null
        },
        "properties": {
          "asset_id": {
            "type": "integer"
          },
          "asset_type_id": {
            "type": "integer"
          },
          "asset_type_code": {
            "type": "string"
          },
          "asset_type_name": {
            "type": "string"
          },
          "network_id": {
            "type": "integer"
          },
          "network_code": {
            "type": "string"
          },
          "network_display_name": {
            "type": "string"
          },
          "decimals": {
            "type": "integer"
          },
          "amount": {
            "type": "string"
          },
          "fee_amount": {
            "type": "string"
          },
          "receive_amount": {
            "type": "string",
            "description": "수취인에게 전달되는 금액. 수수료는 출금 금액에 별도로 더해져 차감된다."
          },
          "min_amount": {
            "type": "string",
            "example": "0",
            "description": "최소 출금 수량. 최소 제한이 비활성화된 경우 0"
          },
          "max_amount": {
            "type": "string"
          },
          "estimated_block_time_sec": {
            "type": "integer"
          },
          "transfer_type": {
            "type": "string",
            "enum": [
              "EXTERNAL",
              "INTERNAL"
            ],
            "description": "EXTERNAL=외부 체인 출금, INTERNAL=플랫폼 내부 계정 이체"
          },
          "can_withdraw": {
            "type": "boolean"
          },
          "reason": {
            "type": "string",
            "nullable": true,
            "enum": [
              "USER_NOT_ACTIVE",
              "ACCOUNT_NOT_ACTIVE",
              "RECIPIENT_USER_NOT_ACTIVE",
              "RECIPIENT_ACCOUNT_NOT_ACTIVE",
              "SAME_ACCOUNT_TRANSFER_NOT_ALLOWED",
              "AMOUNT_BELOW_MINIMUM",
              "AMOUNT_ABOVE_MAXIMUM",
              "INSUFFICIENT_BALANCE",
              null
            ],
            "description": "can_withdraw=false일 때의 사유. USER_NOT_ACTIVE=사용자 비활성, ACCOUNT_NOT_ACTIVE=송신 계정 비활성, RECIPIENT_USER_NOT_ACTIVE/RECIPIENT_ACCOUNT_NOT_ACTIVE=수취 주체 비활성, SAME_ACCOUNT_TRANSFER_NOT_ALLOWED=동일 계정 이체, AMOUNT_BELOW_MINIMUM/AMOUNT_ABOVE_MAXIMUM=한도 위반, INSUFFICIENT_BALANCE=잔액 부족. 출금 가능하면 null"
          }
        },
        "required": [
          "asset_id",
          "asset_type_id",
          "asset_type_code",
          "asset_type_name",
          "network_id",
          "network_code",
          "network_display_name",
          "decimals",
          "amount",
          "fee_amount",
          "receive_amount",
          "min_amount",
          "max_amount",
          "estimated_block_time_sec",
          "transfer_type",
          "can_withdraw",
          "reason"
        ]
      },
      "Withdrawal": {
        "type": "object",
        "description": "외부 출금과 내부이체의 공통 응답. `account_id`는 하위 호환용이며 `from_account_id`와 동일하다.",
        "example": {
          "withdrawal_id": 8001,
          "transfer_type": 1000,
          "from_account_id": 1,
          "to_account_id": null,
          "from_user_id": "user-001",
          "to_user_id": null,
          "account_id": 1,
          "asset_id": "36",
          "asset_type_id": "18",
          "asset_type_code": "USDC",
          "asset_type_name": "USD Coin",
          "network_id": "31",
          "network_code": "sepolia",
          "network_display_name": "Ethereum Sepolia",
          "decimals": 6,
          "amount": "125.5",
          "fee_amount": "1",
          "amount_raw": "125500000",
          "fee_amount_raw": "1000000",
          "to_address": "0x1111111111111111111111111111111111111111",
          "request_type": "EXTERNAL",
          "status": "REQUESTED",
          "user_status": "PENDING",
          "client_request_id": "wd-20260819-000001",
          "tx_hash": null,
          "created_at": "2026-08-19T05:30:00.000Z",
          "updated_at": "2026-08-19T05:30:00.000Z",
          "completed_at": null
        },
        "properties": {
          "withdrawal_id": {
            "type": "integer",
            "format": "int64",
            "example": 1
          },
          "transfer_type": {
            "type": "integer",
            "enum": [
              1000,
              2000
            ],
            "description": "이체 유형 코드. 1000=외부 체인 출금, 2000=플랫폼 내부 계정 이체",
            "x-enumDescriptions": {
              "1000": "외부 체인 출금",
              "2000": "플랫폼 내부 계정 이체"
            }
          },
          "from_account_id": {
            "type": "integer",
            "format": "int64",
            "example": 1
          },
          "to_account_id": {
            "type": "integer",
            "format": "int64",
            "example": 2,
            "nullable": true
          },
          "from_user_id": {
            "type": "string",
            "example": "user-001"
          },
          "to_user_id": {
            "type": "string",
            "nullable": true,
            "example": "user-002"
          },
          "account_id": {
            "type": "integer",
            "format": "int64",
            "example": 1
          },
          "asset_id": {
            "type": "string"
          },
          "asset_type_id": {
            "type": "string"
          },
          "asset_type_code": {
            "type": "string"
          },
          "asset_type_name": {
            "type": "string"
          },
          "network_id": {
            "type": "string",
            "nullable": true,
            "description": "내부이체이면 null"
          },
          "network_code": {
            "type": "string",
            "nullable": true,
            "description": "내부이체이면 null"
          },
          "network_display_name": {
            "type": "string",
            "nullable": true,
            "description": "내부이체이면 null"
          },
          "decimals": {
            "type": "integer"
          },
          "amount": {
            "type": "string"
          },
          "fee_amount": {
            "type": "string"
          },
          "amount_raw": {
            "type": "string"
          },
          "fee_amount_raw": {
            "type": "string"
          },
          "to_address": {
            "type": "string",
            "nullable": true
          },
          "request_type": {
            "type": "string",
            "enum": [
              "EXTERNAL",
              "INTERNAL"
            ],
            "description": "EXTERNAL=외부 체인 출금, INTERNAL=플랫폼 내부 계정 이체"
          },
          "status": {
            "type": "string",
            "enum": [
              "REQUESTED",
              "INSPECTED",
              "APPROVE_PENDING",
              "APPROVED",
              "VERIFIED",
              "AGENT_SIGNED",
              "HOT_STAGE",
              "COMPLETED",
              "HOT_FAILED",
              "HOT_REJECTED",
              "REJECTED",
              "CANCELLED"
            ],
            "description": "REQUESTED=접수, INSPECTED=검사 완료, APPROVE_PENDING=승인 대기, APPROVED=승인, VERIFIED=최종 검증, AGENT_SIGNED=서명 완료, HOT_STAGE=체인 전파 단계, COMPLETED=완료, HOT_FAILED=체인 처리 실패, HOT_REJECTED=체인 처리 거절, REJECTED=업무 거절, CANCELLED=취소"
          },
          "user_status": {
            "type": "string",
            "enum": [
              "PENDING",
              "PROCESSING",
              "COMPLETED",
              "FAILED",
              "REJECTED",
              "CANCELLED"
            ],
            "description": "PENDING=대기, PROCESSING=처리 중, COMPLETED=완료, FAILED=실패, REJECTED=거절, CANCELLED=취소"
          },
          "client_request_id": {
            "type": "string",
            "nullable": true
          },
          "tx_hash": {
            "type": "string",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "completed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "최종 완료 시각. 진행 중이면 null"
          }
        },
        "required": [
          "withdrawal_id",
          "transfer_type",
          "from_account_id",
          "to_account_id",
          "from_user_id",
          "to_user_id",
          "account_id",
          "asset_id",
          "asset_type_id",
          "asset_type_code",
          "asset_type_name",
          "network_id",
          "network_code",
          "network_display_name",
          "decimals",
          "amount",
          "fee_amount",
          "amount_raw",
          "fee_amount_raw",
          "to_address",
          "request_type",
          "status",
          "user_status",
          "client_request_id",
          "tx_hash",
          "created_at",
          "updated_at",
          "completed_at"
        ]
      },
      "WithdrawalListItem": {
        "type": "object",
        "example": {
          "withdrawal_id": 8001,
          "transfer_type": 1000,
          "from_account_id": 1,
          "to_account_id": null,
          "from_user_id": "user-001",
          "to_user_id": null,
          "account_id": 1,
          "asset_id": "36",
          "asset_type_id": "18",
          "asset_type_code": "USDC",
          "asset_type_name": "USD Coin",
          "network_id": "31",
          "network_code": "sepolia",
          "network_display_name": "Ethereum Sepolia",
          "decimals": 6,
          "amount": "125.5",
          "fee_amount": "1",
          "amount_raw": "125500000",
          "fee_amount_raw": "1000000",
          "to_address": "0x1111111111111111111111111111111111111111",
          "request_type": "EXTERNAL",
          "status": "COMPLETED",
          "user_status": "COMPLETED",
          "client_request_id": "wd-20260819-000001",
          "tx_hash": "0x7f3d9d8c4a12",
          "created_at": "2026-08-19T05:30:00.000Z",
          "updated_at": "2026-08-19T05:35:00.000Z",
          "completed_at": "2026-08-19T05:35:00.000Z"
        },
        "properties": {
          "withdrawal_id": {
            "type": "integer",
            "format": "int64",
            "example": 1
          },
          "transfer_type": {
            "type": "integer",
            "enum": [
              1000,
              2000
            ],
            "description": "이체 유형 코드. 1000=외부 체인 출금, 2000=플랫폼 내부 계정 이체",
            "x-enumDescriptions": {
              "1000": "외부 체인 출금",
              "2000": "플랫폼 내부 계정 이체"
            }
          },
          "from_account_id": {
            "type": "integer",
            "format": "int64",
            "example": 1
          },
          "to_account_id": {
            "type": "integer",
            "format": "int64",
            "example": 2,
            "nullable": true
          },
          "from_user_id": {
            "type": "string",
            "example": "user-001"
          },
          "to_user_id": {
            "type": "string",
            "nullable": true,
            "example": "user-002"
          },
          "account_id": {
            "type": "integer",
            "format": "int64",
            "example": 1
          },
          "asset_id": {
            "type": "string"
          },
          "asset_type_id": {
            "type": "string"
          },
          "asset_type_code": {
            "type": "string"
          },
          "asset_type_name": {
            "type": "string"
          },
          "network_id": {
            "type": "string",
            "nullable": true,
            "description": "내부이체이면 null"
          },
          "network_code": {
            "type": "string",
            "nullable": true,
            "description": "내부이체이면 null"
          },
          "network_display_name": {
            "type": "string",
            "nullable": true,
            "description": "내부이체이면 null"
          },
          "decimals": {
            "type": "integer"
          },
          "amount": {
            "type": "string"
          },
          "fee_amount": {
            "type": "string"
          },
          "amount_raw": {
            "type": "string"
          },
          "fee_amount_raw": {
            "type": "string"
          },
          "to_address": {
            "type": "string",
            "nullable": true
          },
          "request_type": {
            "type": "string",
            "enum": [
              "EXTERNAL",
              "INTERNAL"
            ],
            "description": "EXTERNAL=외부 체인 출금, INTERNAL=플랫폼 내부 계정 이체"
          },
          "status": {
            "type": "string",
            "enum": [
              "REQUESTED",
              "INSPECTED",
              "APPROVE_PENDING",
              "APPROVED",
              "VERIFIED",
              "AGENT_SIGNED",
              "HOT_STAGE",
              "COMPLETED",
              "HOT_FAILED",
              "HOT_REJECTED",
              "REJECTED",
              "CANCELLED"
            ],
            "description": "REQUESTED=접수, INSPECTED=검사 완료, APPROVE_PENDING=승인 대기, APPROVED=승인, VERIFIED=최종 검증, AGENT_SIGNED=서명 완료, HOT_STAGE=체인 전파 단계, COMPLETED=완료, HOT_FAILED=체인 처리 실패, HOT_REJECTED=체인 처리 거절, REJECTED=업무 거절, CANCELLED=취소"
          },
          "user_status": {
            "type": "string",
            "enum": [
              "PENDING",
              "PROCESSING",
              "COMPLETED",
              "FAILED",
              "REJECTED",
              "CANCELLED"
            ],
            "description": "PENDING=대기, PROCESSING=처리 중, COMPLETED=완료, FAILED=실패, REJECTED=거절, CANCELLED=취소"
          },
          "client_request_id": {
            "type": "string",
            "nullable": true
          },
          "tx_hash": {
            "type": "string",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "completed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "최종 완료 시각. 진행 중이면 null"
          }
        },
        "required": [
          "withdrawal_id",
          "transfer_type",
          "from_account_id",
          "to_account_id",
          "from_user_id",
          "to_user_id",
          "account_id",
          "asset_id",
          "asset_type_id",
          "asset_type_code",
          "asset_type_name",
          "network_id",
          "network_code",
          "network_display_name",
          "decimals",
          "amount",
          "fee_amount",
          "amount_raw",
          "fee_amount_raw",
          "to_address",
          "request_type",
          "status",
          "user_status",
          "client_request_id",
          "tx_hash",
          "created_at",
          "updated_at",
          "completed_at"
        ]
      },
      "WithdrawalDetail": {
        "$ref": "#/components/schemas/WithdrawalListItem"
      },
      "CancelWithdrawalResult": {
        "type": "object",
        "example": {
          "withdrawal_id": 8001,
          "status": "CANCELLED",
          "user_status": "CANCELLED",
          "updated_at": "2026-08-19T05:32:00.000Z"
        },
        "properties": {
          "withdrawal_id": {
            "type": "integer",
            "format": "int64",
            "example": 1
          },
          "status": {
            "type": "string",
            "enum": [
              "CANCELLED"
            ],
            "example": "CANCELLED",
            "description": "출금 처리가 취소됨"
          },
          "user_status": {
            "type": "string",
            "enum": [
              "CANCELLED"
            ],
            "example": "CANCELLED",
            "description": "고객에게 표시할 취소 완료 상태"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "withdrawal_id",
          "status",
          "user_status",
          "updated_at"
        ]
      }
    },
    "responses": {
      "InvalidRequest": {
        "description": "잘못된 요청",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            },
            "example": {
              "success": false,
              "data": null,
              "error": {
                "code": "MISSING_REQUIRED_FIELD",
                "message": "필수 필드가 누락되었습니다.",
                "request_id": "V1StGXR8_Z5jdHi6B-myT",
                "action": "PROVIDE_REQUIRED_FIELDS",
                "details": {
                  "fields": [
                    "account_id"
                  ]
                }
              }
            }
          }
        }
      },
      "Unauthorized": {
        "description": "인증 실패",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            },
            "example": {
              "success": false,
              "data": null,
              "error": {
                "code": "INVALID_SIGNATURE",
                "message": "요청 서명이 유효하지 않습니다.",
                "request_id": "V1StGXR8_Z5jdHi6B-myT",
                "action": "REGENERATE_SIGNATURE"
              }
            }
          }
        }
      },
      "Forbidden": {
        "description": "사용자 또는 계정 상태로 인해 요청이 거부됨",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            },
            "example": {
              "success": false,
              "data": null,
              "error": {
                "code": "ACCOUNT_NOT_ACTIVE",
                "message": "출금 계정이 활성 상태가 아닙니다.",
                "request_id": "V1StGXR8_Z5jdHi6B-myT",
                "action": "ACTIVATE_ACCOUNT"
              }
            }
          }
        }
      },
      "NotFound": {
        "description": "리소스를 찾을 수 없음",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            },
            "example": {
              "success": false,
              "data": null,
              "error": {
                "code": "ACCOUNT_NOT_FOUND",
                "message": "계정을 찾을 수 없습니다.",
                "request_id": "V1StGXR8_Z5jdHi6B-myT",
                "action": "CHECK_RESOURCE_ID"
              }
            }
          }
        }
      },
      "Conflict": {
        "description": "멱등성 또는 리소스 상태 충돌",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            },
            "example": {
              "success": false,
              "data": null,
              "error": {
                "code": "CONFLICT",
                "message": "리소스 충돌 (중복 요청 등)",
                "request_id": "V1StGXR8_Z5jdHi6B-myT",
                "action": "RESOLVE_CONFLICT"
              }
            }
          }
        }
      },
      "InsufficientBalance": {
        "description": "출금에 사용할 수 있는 잔액이 부족함",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            },
            "example": {
              "success": false,
              "data": null,
              "error": {
                "code": "INSUFFICIENT_BALANCE",
                "message": "출금 요청 시 잔액 부족",
                "request_id": "V1StGXR8_Z5jdHi6B-myT",
                "action": "INCREASE_BALANCE",
                "details": {
                  "required_raw": "126500000",
                  "available_raw": "100000000"
                }
              }
            }
          }
        }
      },
      "ServiceUnavailable": {
        "description": "서비스, 네트워크 또는 자산이 점검·비활성 상태이거나 입금 주소 풀이 소진됨",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            },
            "example": {
              "success": false,
              "data": null,
              "error": {
                "code": "SERVICE_MAINTENANCE",
                "message": "서비스 점검 중 (Maintenance 스케줄에 의한 차단)",
                "request_id": "V1StGXR8_Z5jdHi6B-myT",
                "action": "RETRY_LATER"
              }
            }
          }
        }
      },
      "InternalError": {
        "description": "서버 내부 오류",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            },
            "example": {
              "success": false,
              "data": null,
              "error": {
                "code": "INTERNAL_ERROR",
                "message": "서버 내부 오류가 발생했습니다.",
                "request_id": "V1StGXR8_Z5jdHi6B-myT",
                "action": "CONTACT_SUPPORT"
              }
            }
          }
        }
      }
    }
  },
  "paths": {
    "/accounts": {
      "post": {
        "tags": [
          "Accounts"
        ],
        "summary": "계정 생성",
        "operationId": "createAccount",
        "description": "고객사 사용자 식별자 `uid`로 신규 지갑 계정을 생성한다. `account_type`을 생략하면 USER로 생성된다. BUSINESS 외의 알 수 없는 값도 현재 API에서는 USER로 처리되므로, 연동 클라이언트는 문서화된 enum만 전송해야 한다.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": {
                "uid": "user-001",
                "account_type": "USER",
                "metadata": {
                  "customer_grade": "GOLD"
                }
              },
              "schema": {
                "type": "object",
                "required": [
                  "uid"
                ],
                "properties": {
                  "uid": {
                    "type": "string",
                    "example": "user-001"
                  },
                  "account_type": {
                    "type": "string",
                    "enum": [
                      "USER",
                      "BUSINESS"
                    ],
                    "default": "USER",
                    "description": "USER=개인 사용자 계정, BUSINESS=법인·사업자 계정"
                  },
                  "metadata": {
                    "type": "object",
                    "nullable": true,
                    "description": "임의의 부가 정보"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "생성된 계정",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/Account"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/accounts/{account_id}": {
      "get": {
        "tags": [
          "Accounts"
        ],
        "summary": "계정 상세 조회",
        "operationId": "getAccount",
        "description": "계정 ID로 상태, 계정 유형 및 생성 시 저장한 metadata를 조회한다. 계정이 없으면 `ACCOUNT_NOT_FOUND`를 반환한다.",
        "parameters": [
          {
            "in": "path",
            "name": "account_id",
            "required": true,
            "description": "1 이상의 정수 ID",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "example": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "계정 상세",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/Account"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/accounts/{account_id}/lock": {
      "post": {
        "tags": [
          "Accounts"
        ],
        "summary": "계정 잠금",
        "operationId": "lockAccount",
        "description": "계정을 LOCKED 상태로 전환한다. 잠긴 계정은 출금 검증에서 거부된다.",
        "parameters": [
          {
            "in": "path",
            "name": "account_id",
            "required": true,
            "description": "1 이상의 정수 ID",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "example": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "잠금 결과",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/LockAccountResult"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/accounts/{account_id}/unlock": {
      "post": {
        "tags": [
          "Accounts"
        ],
        "summary": "계정 잠금 해제",
        "operationId": "unlockAccount",
        "description": "잠긴 계정을 ACTIVE 상태로 전환하고 변경 시각을 반환한다.",
        "parameters": [
          {
            "in": "path",
            "name": "account_id",
            "required": true,
            "description": "1 이상의 정수 ID",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "example": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "잠금 해제 결과",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/UnlockAccountResult"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/accounts/{account_id}/deposit-addresses": {
      "post": {
        "tags": [
          "Accounts"
        ],
        "summary": "입금 주소 생성",
        "operationId": "createDepositAddress",
        "description": "계정에 자산 유형·네트워크 조합의 입금 주소를 할당한다. 계정·기준정보가 없거나 비활성 상태이면 오류를 반환하며, 주소 풀 소진 시 `ADDRESS_POOL_EXHAUSTED`가 발생할 수 있다.",
        "parameters": [
          {
            "in": "path",
            "name": "account_id",
            "required": true,
            "description": "1 이상의 정수 ID",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "example": 1
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": {
                "asset_type_id": 18,
                "network_id": 31
              },
              "schema": {
                "type": "object",
                "required": [
                  "asset_type_id",
                  "network_id"
                ],
                "properties": {
                  "asset_type_id": {
                    "type": "integer",
                    "minimum": 1,
                    "example": 18
                  },
                  "network_id": {
                    "type": "integer",
                    "minimum": 1,
                    "example": 31
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "생성된 입금 주소",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/CreateDepositAddressResult"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "get": {
        "tags": [
          "Accounts"
        ],
        "summary": "입금 주소 목록 조회",
        "operationId": "listDepositAddresses",
        "description": "계정에 할당된 입금 주소를 최신 생성 순으로 페이지 조회한다. `page`와 `page_size`는 각각 최소 1로 보정되고 page_size는 최대 100으로 제한된다.",
        "parameters": [
          {
            "in": "path",
            "name": "account_id",
            "required": true,
            "description": "1 이상의 정수 ID",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "example": 1
            }
          },
          {
            "in": "query",
            "name": "page",
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "in": "query",
            "name": "page_size",
            "schema": {
              "type": "integer",
              "default": 20,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "입금 주소 목록(페이지네이션)",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "items": {
                              "type": "array",
                              "items": {
                                "$ref": "#/components/schemas/DepositAddressListItem"
                              }
                            },
                            "page": {
                              "type": "integer"
                            },
                            "page_size": {
                              "type": "integer"
                            },
                            "total": {
                              "type": "integer"
                            }
                          },
                          "required": [
                            "items",
                            "page",
                            "page_size",
                            "total"
                          ]
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/accounts/{account_id}/balances": {
      "get": {
        "tags": [
          "Accounts"
        ],
        "summary": "전체 잔액 조회",
        "operationId": "listAccountBalances",
        "description": "계정의 자산 유형별 잔액과 KRW/USD 평가액을 조회한다. `available_amount_raw`, `pending_withdraw_amount_raw`, `total_amount_raw`는 자산 최소 단위의 정수 문자열이며 표시 금액 변환에는 `decimals`를 사용한다.",
        "parameters": [
          {
            "in": "path",
            "name": "account_id",
            "required": true,
            "description": "1 이상의 정수 ID",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "example": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "계정의 전체 자산 잔액",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/GetAllBalancesResult"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/accounts/{account_id}/balances/{asset_type_id}": {
      "get": {
        "tags": [
          "Accounts"
        ],
        "summary": "단일 자산 잔액 조회",
        "operationId": "getAccountBalance",
        "description": "계정의 특정 자산 유형 잔액을 조회한다. 잔액 행이 없으면 `BALANCE_NOT_FOUND`를 반환한다.",
        "parameters": [
          {
            "in": "path",
            "name": "account_id",
            "required": true,
            "description": "1 이상의 정수 ID",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "example": 1
            }
          },
          {
            "in": "path",
            "name": "asset_type_id",
            "required": true,
            "description": "자산 유형의 숫자 ID",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "example": 2
            }
          }
        ],
        "responses": {
          "200": {
            "description": "단일 자산 잔액",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/GetSingleBalanceResult"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/deposits": {
      "get": {
        "tags": [
          "Deposits"
        ],
        "summary": "입금 내역 목록 조회",
        "operationId": "listDeposits",
        "description": "계정의 입금 내역을 조회한다. 기본은 page/page_size 기반 조회이며, after_id를 지정하면 커서(id ASC) 기반 증분 조회로 동작한다(외부 백엔드 동기화 용도). 커서 조회는 type=EXTERNAL 또는 INTERNAL을 명시해야 하며(unified 조회는 PK 시퀀스가 달라 지원하지 않음), 응답은 page/page_size/total 대신 next_cursor/has_more를 반환한다.",
        "parameters": [
          {
            "in": "query",
            "name": "account_id",
            "required": true,
            "description": "1 이상의 정수 ID",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "example": 1
            }
          },
          {
            "in": "query",
            "name": "asset_type_id",
            "description": "조회할 자산 유형의 숫자 ID",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "example": 2
            }
          },
          {
            "in": "query",
            "name": "type",
            "description": "입금 유형 (ALL: 전체, EXTERNAL: 외부 입금, INTERNAL: 내부 이체 입금). after_id 기반 커서 조회 시에는 EXTERNAL 또는 INTERNAL을 명시해야 한다.",
            "schema": {
              "type": "string",
              "enum": [
                "ALL",
                "EXTERNAL",
                "INTERNAL"
              ],
              "default": "ALL",
              "description": "ALL=전체, EXTERNAL=온체인 외부 입금, INTERNAL=플랫폼 내부이체 입금"
            }
          },
          {
            "in": "query",
            "name": "status",
            "description": "입금 처리 상태 필터",
            "schema": {
              "type": "string",
              "enum": [
                "PENDING",
                "COMPLETED",
                "REFUNDED"
              ],
              "description": "PENDING=처리 중, COMPLETED=입금 완료, REFUNDED=환불 완료"
            }
          },
          {
            "in": "query",
            "name": "page",
            "description": "페이지 번호 (after_id 지정 시 무시됨)",
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "in": "query",
            "name": "page_size",
            "description": "페이지 크기 (after_id 지정 시 무시됨)",
            "schema": {
              "type": "integer",
              "default": 20,
              "maximum": 100
            }
          },
          {
            "in": "query",
            "name": "from",
            "description": "조회 시작일(포함). YYYY-MM-DD 형식. 예: 2026-08-01이면 2026-08-01 00:00:00부터 조회",
            "schema": {
              "type": "string",
              "format": "date",
              "example": "2026-08-01"
            }
          },
          {
            "in": "query",
            "name": "to",
            "description": "조회 종료일(포함). YYYY-MM-DD 형식. 예: 2026-08-10이면 2026-08-11 00:00:00 미만까지 조회하여 8월 10일 전체를 포함",
            "schema": {
              "type": "string",
              "format": "date",
              "example": "2026-08-10"
            }
          },
          {
            "in": "query",
            "name": "after_id",
            "description": "커서(after_id) 기반 동기화 조회용. 마지막으로 조회한 deposit_id (exclusive). 지정 시 page/page_size는 무시되며 type을 명시해야 한다.",
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          },
          {
            "in": "query",
            "name": "limit",
            "description": "커서 조회 시 조회 건수 (기본 100, 최대 1000)",
            "schema": {
              "type": "integer",
              "default": 100,
              "maximum": 1000
            }
          }
        ],
        "responses": {
          "200": {
            "description": "입금 내역 목록. page/page_size 지정 시 페이지네이션 응답(page/page_size/total), after_id 지정 시 커서 응답(next_cursor/has_more)을 반환한다.",
            "content": {
              "application/json": {
                "examples": {
                  "pageMode": {
                    "summary": "페이지 조회",
                    "value": {
                      "success": true,
                      "data": {
                        "items": [
                          {
                            "deposit_id": 551,
                            "account_id": 1,
                            "asset_type_id": "18",
                            "asset_type_code": "USDC",
                            "asset_type_name": "USD Coin",
                            "asset_id": "36",
                            "network_id": "31",
                            "network_code": "sepolia",
                            "network_display_name": "Ethereum Sepolia",
                            "decimals": 6,
                            "tx_hash": "0x7f3d9d8c4a12",
                            "from_address": "0x1111111111111111111111111111111111111111",
                            "to_address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F",
                            "amount": "125.5",
                            "amount_raw": "125500000",
                            "status": "COMPLETED",
                            "type": "EXTERNAL",
                            "market_price_krw": "1370.25",
                            "market_price_usd": "1",
                            "created_at": "2026-08-19T05:20:00.000Z",
                            "confirmed_at": "2026-08-19T05:22:30.000Z",
                            "refund_withdrawal_id": null
                          }
                        ],
                        "page": 1,
                        "page_size": 20,
                        "total": 1
                      },
                      "error": null
                    }
                  },
                  "cursorMode": {
                    "summary": "커서 조회",
                    "value": {
                      "success": true,
                      "data": {
                        "items": [
                          {
                            "deposit_id": 551,
                            "account_id": 1,
                            "asset_type_id": "18",
                            "asset_type_code": "USDC",
                            "asset_type_name": "USD Coin",
                            "asset_id": "36",
                            "network_id": "31",
                            "network_code": "sepolia",
                            "network_display_name": "Ethereum Sepolia",
                            "decimals": 6,
                            "tx_hash": "0x7f3d9d8c4a12",
                            "from_address": "0x1111111111111111111111111111111111111111",
                            "to_address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F",
                            "amount": "125.5",
                            "amount_raw": "125500000",
                            "status": "COMPLETED",
                            "type": "EXTERNAL",
                            "market_price_krw": "1370.25",
                            "market_price_usd": "1",
                            "created_at": "2026-08-19T05:20:00.000Z",
                            "confirmed_at": "2026-08-19T05:22:30.000Z",
                            "refund_withdrawal_id": null
                          }
                        ],
                        "next_cursor": 551,
                        "has_more": false
                      },
                      "error": null
                    }
                  }
                },
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "items": {
                              "type": "array",
                              "items": {
                                "$ref": "#/components/schemas/DepositListItem"
                              }
                            },
                            "page": {
                              "type": "integer",
                              "description": "page 기반 조회일 때만 포함"
                            },
                            "page_size": {
                              "type": "integer",
                              "description": "page 기반 조회일 때만 포함"
                            },
                            "total": {
                              "type": "integer",
                              "description": "page 기반 조회일 때만 포함"
                            },
                            "next_cursor": {
                              "type": "integer",
                              "description": "after_id 기반 조회일 때만 포함. 마지막 item의 deposit_id"
                            },
                            "has_more": {
                              "type": "boolean",
                              "description": "after_id 기반 조회일 때만 포함. items.length == limit이면 true"
                            }
                          },
                          "required": [
                            "items"
                          ],
                          "oneOf": [
                            {
                              "required": [
                                "page",
                                "page_size",
                                "total"
                              ]
                            },
                            {
                              "required": [
                                "next_cursor",
                                "has_more"
                              ]
                            }
                          ]
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/deposits/{deposit_id}": {
      "get": {
        "tags": [
          "Deposits"
        ],
        "summary": "입금 상세 조회",
        "operationId": "getDeposit",
        "description": "특정 입금 내역의 상세 정보를 조회한다. 내부이체 입금을 조회하려면 `type=INTERNAL`을 함께 전달해야 한다.",
        "parameters": [
          {
            "in": "path",
            "name": "deposit_id",
            "required": true,
            "description": "1 이상의 정수 ID",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "example": 1
            }
          },
          {
            "in": "query",
            "name": "type",
            "description": "내부이체 입금(내부 송금으로 들어온 입금) 상세를 조회할 때 INTERNAL 지정",
            "schema": {
              "type": "string",
              "enum": [
                "EXTERNAL",
                "INTERNAL"
              ],
              "default": "EXTERNAL",
              "description": "EXTERNAL=온체인 외부 입금, INTERNAL=플랫폼 내부이체 입금"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "입금 상세 정보",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/DepositDetail"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/accounts/{account_id}/ledger": {
      "get": {
        "tags": [
          "Ledger"
        ],
        "summary": "계정 원장 내역 조회",
        "operationId": "listAccountLedger",
        "description": "특정 계정의 입출금 및 이체 내역(원장)을 조회한다. 기본은 page/page_size 기반 조회이며, after_id를 지정하면 커서(ledger.id ASC) 기반 증분 조회로 동작한다(외부 백엔드 동기화 용도). 커서 조회 응답은 page/page_size/total 대신 next_cursor/has_more를 반환한다.",
        "parameters": [
          {
            "in": "path",
            "name": "account_id",
            "required": true,
            "description": "1 이상의 정수 ID",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "example": 1
            }
          },
          {
            "in": "query",
            "name": "asset_type_id",
            "schema": {
              "type": "integer"
            },
            "description": "자산 타입 ID 필터"
          },
          {
            "in": "query",
            "name": "transaction_type",
            "schema": {
              "type": "string",
              "enum": [
                "DEPOSIT",
                "WITHDRAW",
                "INTERNAL_OUT",
                "INTERNAL_IN",
                "ADJUSTMENT"
              ],
              "description": "DEPOSIT=외부 입금, WITHDRAW=외부 출금, INTERNAL_OUT=내부이체 출금, INTERNAL_IN=내부이체 입금, ADJUSTMENT=관리자 조정"
            },
            "description": "거래 유형 필터"
          },
          {
            "in": "query",
            "name": "entry_type",
            "schema": {
              "type": "string",
              "enum": [
                "CREDIT",
                "DEBIT"
              ],
              "description": "CREDIT=잔액 증가 분개, DEBIT=잔액 감소 분개"
            },
            "description": "분개 방향 필터"
          },
          {
            "in": "query",
            "name": "from",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "시작 날짜 (YYYY-MM-DD)"
          },
          {
            "in": "query",
            "name": "to",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "종료 날짜 (YYYY-MM-DD)"
          },
          {
            "in": "query",
            "name": "page",
            "schema": {
              "type": "integer",
              "default": 1
            },
            "description": "페이지 번호 (after_id 지정 시 무시됨)"
          },
          {
            "in": "query",
            "name": "page_size",
            "schema": {
              "type": "integer",
              "default": 20,
              "maximum": 100
            },
            "description": "페이지당 항목 수 (after_id 지정 시 무시됨)"
          },
          {
            "in": "query",
            "name": "after_id",
            "schema": {
              "type": "integer",
              "minimum": 0
            },
            "description": "커서(after_id) 기반 동기화 조회용. 마지막으로 조회한 ledger_id (exclusive). 지정 시 page/page_size는 무시된다."
          },
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "type": "integer",
              "default": 100,
              "maximum": 1000
            },
            "description": "커서 조회 시 조회 건수 (기본 100, 최대 1000)"
          }
        ],
        "responses": {
          "200": {
            "description": "원장 내역 목록. page/page_size 지정 시 페이지네이션 응답(page/page_size/total), after_id 지정 시 커서 응답(next_cursor/has_more)을 반환한다.",
            "content": {
              "application/json": {
                "examples": {
                  "pageMode": {
                    "summary": "페이지 조회",
                    "value": {
                      "success": true,
                      "data": {
                        "items": [
                          {
                            "ledger_id": 120001,
                            "ref_type": 1000,
                            "ref_id": "551",
                            "transaction_type": 1000,
                            "transaction_hash": "0x7f3d9d8c4a12",
                            "transfer_type": "EXTERNAL",
                            "from_account_id": null,
                            "to_account_id": 1,
                            "from_address": "0x1111111111111111111111111111111111111111",
                            "to_address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F",
                            "from_user_id": null,
                            "to_user_id": "user-001",
                            "account_id": 1,
                            "asset_type_id": 18,
                            "asset_type_code": "USDC",
                            "asset_id": "36",
                            "network_id": "31",
                            "network_code": "sepolia",
                            "entry_type": "CREDIT",
                            "entry_code": 1000,
                            "entry_seq": 1,
                            "amount": "125.5",
                            "amount_raw": "125500000",
                            "decimals": 6,
                            "balance_after": "130",
                            "balance_after_raw": "130000000",
                            "market_price_krw": "1370.25",
                            "market_price_usd": "1",
                            "metadata": null,
                            "created_at": "2026-08-19T05:22:30.000Z"
                          }
                        ],
                        "page": 1,
                        "page_size": 20,
                        "total": 1
                      },
                      "error": null
                    }
                  },
                  "cursorMode": {
                    "summary": "커서 조회",
                    "value": {
                      "success": true,
                      "data": {
                        "items": [
                          {
                            "ledger_id": 120001,
                            "ref_type": 1000,
                            "ref_id": "551",
                            "transaction_type": 1000,
                            "transaction_hash": "0x7f3d9d8c4a12",
                            "transfer_type": "EXTERNAL",
                            "from_account_id": null,
                            "to_account_id": 1,
                            "from_address": "0x1111111111111111111111111111111111111111",
                            "to_address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F",
                            "from_user_id": null,
                            "to_user_id": "user-001",
                            "account_id": 1,
                            "asset_type_id": 18,
                            "asset_type_code": "USDC",
                            "asset_id": "36",
                            "network_id": "31",
                            "network_code": "sepolia",
                            "entry_type": "CREDIT",
                            "entry_code": 1000,
                            "entry_seq": 1,
                            "amount": "125.5",
                            "amount_raw": "125500000",
                            "decimals": 6,
                            "balance_after": "130",
                            "balance_after_raw": "130000000",
                            "market_price_krw": "1370.25",
                            "market_price_usd": "1",
                            "metadata": null,
                            "created_at": "2026-08-19T05:22:30.000Z"
                          }
                        ],
                        "next_cursor": 120001,
                        "has_more": false
                      },
                      "error": null
                    }
                  }
                },
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "items": {
                              "type": "array",
                              "items": {
                                "$ref": "#/components/schemas/LedgerItem"
                              }
                            },
                            "page": {
                              "type": "integer",
                              "description": "page 기반 조회일 때만 포함"
                            },
                            "page_size": {
                              "type": "integer",
                              "description": "page 기반 조회일 때만 포함"
                            },
                            "total": {
                              "type": "integer",
                              "description": "page 기반 조회일 때만 포함"
                            },
                            "next_cursor": {
                              "type": "integer",
                              "description": "after_id 기반 조회일 때만 포함. 마지막 item의 ledger_id"
                            },
                            "has_more": {
                              "type": "boolean",
                              "description": "after_id 기반 조회일 때만 포함. items.length == limit이면 true"
                            }
                          },
                          "required": [
                            "items"
                          ],
                          "oneOf": [
                            {
                              "required": [
                                "page",
                                "page_size",
                                "total"
                              ]
                            },
                            {
                              "required": [
                                "next_cursor",
                                "has_more"
                              ]
                            }
                          ]
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/accounts/{account_id}/ledger/{ledger_id}": {
      "get": {
        "tags": [
          "Ledger"
        ],
        "summary": "계정 원장 단건 조회",
        "operationId": "getAccountLedgerEntry",
        "description": "account_id와 ledger_id가 모두 일치하는 원장 분개를 조회한다. 다른 계정에 속한 ledger_id도 LEDGER_NOT_FOUND로 처리한다.",
        "parameters": [
          {
            "in": "path",
            "name": "account_id",
            "required": true,
            "description": "원장 분개 소유 계정의 1 이상 정수 ID",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "example": 1
            }
          },
          {
            "in": "path",
            "name": "ledger_id",
            "required": true,
            "description": "조회할 원장 분개의 1 이상 정수 ID",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "example": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "원장 분개 단건",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/LedgerItem"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/prices": {
      "get": {
        "tags": [
          "Prices"
        ],
        "summary": "자산별 시세 조회",
        "operationId": "getPrices",
        "description": "지정한 자산 유형과 법정화폐 조합의 최신 시세를 조회한다. 이 엔드포인트는 인증 없이 호출할 수 있다. `asset_type_ids`를 생략하면 전체 자산 유형, `fiat`을 생략하면 KRW를 조회한다.",
        "security": [],
        "parameters": [
          {
            "in": "query",
            "name": "asset_type_ids",
            "description": "자산 타입 ID 목록 (콤마구분)",
            "schema": {
              "type": "string",
              "example": "1,2,3"
            }
          },
          {
            "in": "query",
            "name": "fiat",
            "description": "법정화폐 목록 (콤마구분, 기본 KRW)",
            "schema": {
              "type": "string",
              "example": "KRW,USD",
              "default": "KRW"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "시세 정보 목록",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/PriceList"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/reconciliation/ledger-entries": {
      "get": {
        "tags": [
          "Reconciliation"
        ],
        "summary": "원장 증분 조회 (커서 기반)",
        "operationId": "listReconciliationLedgerEntries",
        "description": "ledger.id 커서(after_id) 기반으로 원장 분개를 PK 오름차순으로 증분 조회한다. 대사 클라이언트는 next_cursor를 저장해 이어서 조회한다.",
        "parameters": [
          {
            "in": "query",
            "name": "after_id",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            },
            "description": "마지막으로 조회한 ledger.id (exclusive)"
          },
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 10000,
              "default": 1000
            },
            "description": "조회 건수 (기본 1000, 최대 10000)"
          },
          {
            "in": "query",
            "name": "account_id",
            "schema": {
              "type": "integer",
              "minimum": 1
            },
            "description": "계정 필터 (숫자 PK)"
          },
          {
            "in": "query",
            "name": "asset_type_id",
            "schema": {
              "type": "integer",
              "minimum": 1
            },
            "description": "자산 필터"
          },
          {
            "in": "query",
            "name": "transaction_type",
            "schema": {
              "type": "integer",
              "enum": [
                1000,
                2000,
                3000,
                4000,
                5000
              ],
              "x-enumDescriptions": {
                "1000": "외부 입금",
                "2000": "외부 출금",
                "3000": "내부이체 출금",
                "4000": "내부이체 입금",
                "5000": "관리자 조정"
              }
            },
            "description": "거래 유형 코드 필터\n\n| 값 | 의미 |\n|---:|---|\n| `1000` | 외부 입금 |\n| `2000` | 외부 출금 |\n| `3000` | 내부이체 출금 |\n| `4000` | 내부이체 입금 |\n| `5000` | 관리자 조정 |"
          },
          {
            "in": "query",
            "name": "entry_type",
            "schema": {
              "type": "integer",
              "enum": [
                1000,
                2000
              ],
              "x-enumDescriptions": {
                "1000": "잔액 증가(CREDIT)",
                "2000": "잔액 감소(DEBIT)"
              }
            },
            "description": "분개 방향 코드 필터\n\n| 값 | 의미 |\n|---:|---|\n| `1000` | 잔액 증가(CREDIT) |\n| `2000` | 잔액 감소(DEBIT) |"
          }
        ],
        "responses": {
          "200": {
            "description": "원장 분개 목록 (id 오름차순)",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "items": {
                              "type": "array",
                              "items": {
                                "$ref": "#/components/schemas/ReconLedgerEntry"
                              }
                            },
                            "next_cursor": {
                              "type": "integer",
                              "description": "마지막 item의 ledger_id. items가 없으면 요청한 after_id"
                            },
                            "has_more": {
                              "type": "boolean",
                              "description": "items.length == limit이면 true. 정확히 limit건으로 끝난 경우에도 true일 수 있다."
                            }
                          },
                          "required": [
                            "items",
                            "next_cursor",
                            "has_more"
                          ]
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "INVALID_FIELD_VALUE — after_id/limit/계정·자산 ID의 형식·범위가 잘못되었거나 transaction_type/entry_type이 허용 코드가 아님. details.reason을 수정한다.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "인증 실패 — MISSING_AUTH_HEADER, INVALID_API_KEY, INVALID_TIMESTAMP, NONCE_REPLAYED, INVALID_SIGNATURE 중 하나. error.code와 action에 따라 인증값을 수정한다.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "500": {
            "description": "INTERNAL_ERROR — 내부 정보는 노출되지 않는다. 자동 반복을 중단하고 request_id로 문의한다.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/reconciliation/transactions": {
      "get": {
        "tags": [
          "Reconciliation"
        ],
        "summary": "거래 상태 조회 (커서 기반)",
        "operationId": "listReconciliationTransactions",
        "description": "입금/출금·내부이체 원천 거래를 커서 기반으로 조회한다. 거래 유형별 ID가 독립적이므로 transaction_type별로 커서를 분리 관리해야 한다.",
        "parameters": [
          {
            "in": "query",
            "name": "transaction_type",
            "required": true,
            "schema": {
              "type": "integer",
              "enum": [
                1000,
                2000
              ],
              "x-enumDescriptions": {
                "1000": "입금 이벤트",
                "2000": "출금·내부이체 요청"
              }
            },
            "description": "조회할 원천 거래 유형\n\n| 값 | 의미 |\n|---:|---|\n| `1000` | 입금 이벤트 |\n| `2000` | 출금·내부이체 요청 |"
          },
          {
            "in": "query",
            "name": "after_id",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            },
            "description": "마지막으로 조회한 거래 ID. 이 ID 이후의 거래를 조회한다."
          },
          {
            "in": "query",
            "name": "status",
            "schema": {
              "type": "integer",
              "description": "transaction_type=1000: 1000=PENDING, 1300=INSPECTED, 1400=APPROVE_PENDING, 1500=APPROVED, 1600=VERIFIED, 2000=REFUND_REQUIRED, 2100=REFUND_REQUESTED, 2200=REFUND_PENDING, 3000=COMPLETED, 4000=REFUNDED, 9000=FAILED. transaction_type=2000: 1000=REQUESTED, 1100=INSPECTED, 1200=APPROVE_PENDING, 1300=APPROVED, 1400=VERIFIED, 1500=AGENT_SIGNED, 2000=HOT_STAGE, 9000=COMPLETED, 9100=HOT_FAILED, 9300=HOT_REJECTED, 9400=REJECTED, 9500=CANCELLED"
            },
            "description": "원천 거래 상태 코드 필터"
          },
          {
            "in": "query",
            "name": "updated_from",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "updated_at 하한 (UTC ISO-8601, 경계 포함: updated_at >= updated_from)"
          },
          {
            "in": "query",
            "name": "updated_to",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "updated_at 상한 (UTC ISO-8601, 경계 포함: updated_at <= updated_to)"
          },
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 10000,
              "default": 1000
            },
            "description": "조회 건수 (기본 1000, 최대 10000)"
          }
        ],
        "responses": {
          "200": {
            "description": "거래 목록 (원천 PK 오름차순)",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "items": {
                              "type": "array",
                              "items": {
                                "$ref": "#/components/schemas/ReconTransaction"
                              }
                            },
                            "next_cursor": {
                              "type": "integer",
                              "description": "마지막 item의 reference_id. items가 없으면 요청한 after_id"
                            },
                            "has_more": {
                              "type": "boolean",
                              "description": "items.length == limit이면 true. 정확히 limit건으로 끝난 경우에도 true일 수 있다."
                            }
                          },
                          "required": [
                            "items",
                            "next_cursor",
                            "has_more"
                          ]
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "INVALID_FIELD_VALUE — transaction_type 누락·코드 오류, after_id/limit/status 오류, 시각 형식 오류 또는 updated_from > updated_to. details.reason을 수정한다.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "인증 실패 — MISSING_AUTH_HEADER, INVALID_API_KEY, INVALID_TIMESTAMP, NONCE_REPLAYED, INVALID_SIGNATURE 중 하나. error.code와 action에 따라 인증값을 수정한다.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "500": {
            "description": "INTERNAL_ERROR — 내부 정보는 노출되지 않는다. 자동 반복을 중단하고 request_id로 문의한다.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/reconciliation/balances": {
      "get": {
        "tags": [
          "Reconciliation"
        ],
        "summary": "현재 잔액 조회",
        "operationId": "listReconciliationBalances",
        "description": "asset_balance 기준 현재 잔액을 조회한다. as_of_ledger_id는 응답 생성 시 조회한 MAX(ledger.id)이다. 잔액 행과 MAX(ledger.id)는 하나의 DB 트랜잭션에서 원자적으로 고정되지 않으므로 as_of_ledger_id를 계정별 정밀 스냅샷 경계로 사용하면 안 된다.",
        "parameters": [
          {
            "in": "query",
            "name": "account_id",
            "schema": {
              "type": "integer",
              "minimum": 1
            },
            "description": "계정 필터 (숫자 PK)"
          },
          {
            "in": "query",
            "name": "asset_type_id",
            "schema": {
              "type": "integer",
              "minimum": 1
            },
            "description": "자산 필터"
          }
        ],
        "responses": {
          "200": {
            "description": "잔액 스냅샷",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "as_of": {
                              "type": "string",
                              "format": "date-time"
                            },
                            "as_of_ledger_id": {
                              "type": "integer",
                              "description": "스냅샷 기준 MAX(ledger.id)"
                            },
                            "items": {
                              "type": "array",
                              "items": {
                                "$ref": "#/components/schemas/ReconBalance"
                              }
                            }
                          },
                          "required": [
                            "as_of",
                            "as_of_ledger_id",
                            "items"
                          ]
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "INVALID_FIELD_VALUE — account_id 또는 asset_type_id가 양의 정수가 아님. details.reason을 수정한다. 존재하지 않는 ID는 오류가 아니라 빈 items를 반환한다.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "인증 실패 — MISSING_AUTH_HEADER, INVALID_API_KEY, INVALID_TIMESTAMP, NONCE_REPLAYED, INVALID_SIGNATURE 중 하나. error.code와 action에 따라 인증값을 수정한다.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "500": {
            "description": "INTERNAL_ERROR — 내부 정보는 노출되지 않는다. 자동 반복을 중단하고 request_id로 문의한다.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/reconciliation/ledger-summary": {
      "get": {
        "tags": [
          "Reconciliation"
        ],
        "summary": "원장 구간 합계 조회",
        "operationId": "getReconciliationLedgerSummary",
        "description": "지정 구간(from_id exclusive ~ to_id inclusive)의 건수/CREDIT 합계/DEBIT 합계를 집계한다. 상세 대사 전 합계 비교로 대사 비용을 최소화한다.",
        "parameters": [
          {
            "in": "query",
            "name": "from_id",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 0
            },
            "description": "시작 ledger.id (exclusive)"
          },
          {
            "in": "query",
            "name": "to_id",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 0
            },
            "description": "종료 ledger.id (inclusive). from_id < to_id이고 to_id - from_id <= 1000000이어야 한다."
          },
          {
            "in": "query",
            "name": "group_by",
            "schema": {
              "type": "string",
              "enum": [
                "asset",
                "account"
              ],
              "default": "asset",
              "description": "asset=자산 유형별 합계, account=계정·자산 유형별 합계"
            },
            "description": "집계 단위"
          }
        ],
        "responses": {
          "200": {
            "description": "구간 합계",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "from_id": {
                              "type": "integer"
                            },
                            "to_id": {
                              "type": "integer"
                            },
                            "count": {
                              "type": "integer",
                              "description": "구간 내 전체 분개 건수"
                            },
                            "items": {
                              "type": "array",
                              "items": {
                                "$ref": "#/components/schemas/ReconLedgerSummaryItem"
                              }
                            }
                          },
                          "required": [
                            "from_id",
                            "to_id",
                            "count",
                            "items"
                          ]
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "INVALID_FIELD_VALUE — from_id/to_id 누락·형식 오류, from_id >= to_id, 범위 1,000,000 초과 또는 group_by 오류. details.reason을 수정한다.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "인증 실패 — MISSING_AUTH_HEADER, INVALID_API_KEY, INVALID_TIMESTAMP, NONCE_REPLAYED, INVALID_SIGNATURE 중 하나. error.code와 action에 따라 인증값을 수정한다.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "500": {
            "description": "INTERNAL_ERROR — 내부 정보는 노출되지 않는다. 자동 반복을 중단하고 request_id로 문의한다.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/networks": {
      "get": {
        "tags": [
          "Refdata"
        ],
        "summary": "네트워크 목록 조회",
        "operationId": "listNetworks",
        "description": "지원하는 블록체인 네트워크를 조건별로 페이지 조회한다. `is_active`는 문자열 `true` 또는 `1`일 때만 true로 해석되며 그 외의 값은 false로 필터링된다.",
        "parameters": [
          {
            "in": "query",
            "name": "is_active",
            "schema": {
              "type": "string"
            },
            "description": "활성화 여부 (true/false)"
          },
          {
            "in": "query",
            "name": "code",
            "schema": {
              "type": "string"
            },
            "description": "네트워크 코드"
          },
          {
            "in": "query",
            "name": "name",
            "schema": {
              "type": "string"
            },
            "description": "네트워크 이름"
          },
          {
            "in": "query",
            "name": "page",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          },
          {
            "in": "query",
            "name": "page_size",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 20,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "네트워크 목록(페이지네이션)",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "items": {
                              "type": "array",
                              "items": {
                                "$ref": "#/components/schemas/Network"
                              }
                            },
                            "page": {
                              "type": "integer"
                            },
                            "page_size": {
                              "type": "integer"
                            },
                            "total": {
                              "type": "integer"
                            }
                          },
                          "required": [
                            "items",
                            "page",
                            "page_size",
                            "total"
                          ]
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/networks/{id}": {
      "get": {
        "tags": [
          "Refdata"
        ],
        "summary": "네트워크 상세 조회",
        "operationId": "getNetwork",
        "description": "숫자 ID로 네트워크의 체인 식별 정보, 탐색기 URL과 활성 상태를 조회한다.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "example": 31
            }
          }
        ],
        "responses": {
          "200": {
            "description": "네트워크 상세",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/Network"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/asset-types": {
      "get": {
        "tags": [
          "Refdata"
        ],
        "summary": "자산 타입 목록 조회",
        "operationId": "listAssetTypes",
        "description": "BTC, ETH, USDT와 같은 체인 독립적 자산 유형을 조건별로 페이지 조회한다. 네트워크별 실제 운영 자산은 `/assets`에서 조회한다.",
        "parameters": [
          {
            "in": "query",
            "name": "id",
            "schema": {
              "type": "integer",
              "minimum": 1
            },
            "description": "ID"
          },
          {
            "in": "query",
            "name": "code",
            "schema": {
              "type": "string"
            },
            "description": "코드"
          },
          {
            "in": "query",
            "name": "name",
            "schema": {
              "type": "string"
            },
            "description": "이름"
          },
          {
            "in": "query",
            "name": "symbol",
            "schema": {
              "type": "string"
            },
            "description": "심볼"
          },
          {
            "in": "query",
            "name": "page",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          },
          {
            "in": "query",
            "name": "page_size",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 20,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "자산 타입 목록(페이지네이션)",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "items": {
                              "type": "array",
                              "items": {
                                "$ref": "#/components/schemas/AssetType"
                              }
                            },
                            "page": {
                              "type": "integer"
                            },
                            "page_size": {
                              "type": "integer"
                            },
                            "total": {
                              "type": "integer"
                            }
                          },
                          "required": [
                            "items",
                            "page",
                            "page_size",
                            "total"
                          ]
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/asset-types/list": {
      "get": {
        "tags": [
          "Refdata"
        ],
        "summary": "자산 타입 목록 조회 (ID 리스트)",
        "operationId": "getAssetTypesByIds",
        "description": "쉼표로 구분한 자산 타입 ID 목록을 한 번에 조회한다. 페이지네이션 없이 일치한 항목과 `total`을 반환한다.",
        "parameters": [
          {
            "in": "query",
            "name": "ids",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "ID 리스트 (쉼표로 구분, 예: 1,2,3)"
          }
        ],
        "responses": {
          "200": {
            "description": "자산 타입 목록",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "items": {
                              "type": "array",
                              "items": {
                                "$ref": "#/components/schemas/AssetType"
                              }
                            },
                            "total": {
                              "type": "integer"
                            }
                          },
                          "required": [
                            "items",
                            "total"
                          ]
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/asset-types/{id}": {
      "get": {
        "tags": [
          "Refdata"
        ],
        "summary": "자산 타입 상세 조회",
        "operationId": "getAssetType",
        "description": "숫자 ID로 자산 유형의 코드, 표시 심볼, 소수점 자릿수와 스테이블코인 여부를 조회한다.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "example": 18
            }
          }
        ],
        "responses": {
          "200": {
            "description": "자산 타입 상세",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/AssetType"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/asset-types/{id}/networks": {
      "get": {
        "tags": [
          "Refdata"
        ],
        "summary": "자산 타입별 네트워크 목록 조회",
        "operationId": "listAssetTypeNetworks",
        "description": "특정 자산 타입이 지원되는 네트워크 목록을 조회한다.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "example": 1
            },
            "description": "자산 타입 ID"
          }
        ],
        "responses": {
          "200": {
            "description": "자산 네트워크 목록",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "asset_type_id": {
                              "type": "integer"
                            },
                            "asset_type_code": {
                              "type": "string",
                              "nullable": true
                            },
                            "items": {
                              "type": "array",
                              "items": {
                                "$ref": "#/components/schemas/Asset"
                              }
                            },
                            "total": {
                              "type": "integer"
                            }
                          },
                          "required": [
                            "asset_type_id",
                            "asset_type_code",
                            "items",
                            "total"
                          ]
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/assets": {
      "get": {
        "tags": [
          "Refdata"
        ],
        "summary": "운영 자산 목록 조회",
        "operationId": "listAssets",
        "description": "자산 유형과 네트워크의 실제 운영 조합을 페이지 조회한다. 출금·주소 검증에는 이 응답의 `asset_id`, `network_id`, `decimals`, `is_active`를 사용한다.",
        "parameters": [
          {
            "in": "query",
            "name": "id",
            "schema": {
              "type": "integer",
              "minimum": 1
            },
            "description": "자산 ID"
          },
          {
            "in": "query",
            "name": "network_id",
            "schema": {
              "type": "integer",
              "minimum": 1
            },
            "description": "네트워크 ID"
          },
          {
            "in": "query",
            "name": "asset_type_id",
            "schema": {
              "type": "integer",
              "minimum": 1
            },
            "description": "자산 타입 ID"
          },
          {
            "in": "query",
            "name": "symbol",
            "schema": {
              "type": "string"
            },
            "description": "심볼"
          },
          {
            "in": "query",
            "name": "contract_address",
            "schema": {
              "type": "string"
            },
            "description": "컨트랙트 주소"
          },
          {
            "in": "query",
            "name": "is_active",
            "schema": {
              "type": "string"
            },
            "description": "활성화 여부 (true/false)"
          },
          {
            "in": "query",
            "name": "page",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          },
          {
            "in": "query",
            "name": "page_size",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 20,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "운영 자산 목록(페이지네이션)",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "items": {
                              "type": "array",
                              "items": {
                                "$ref": "#/components/schemas/Asset"
                              }
                            },
                            "page": {
                              "type": "integer"
                            },
                            "page_size": {
                              "type": "integer"
                            },
                            "total": {
                              "type": "integer"
                            }
                          },
                          "required": [
                            "items",
                            "page",
                            "page_size",
                            "total"
                          ]
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/assets/by-type-network": {
      "get": {
        "tags": [
          "Refdata"
        ],
        "summary": "자산 타입 및 네트워크로 자산 조회",
        "operationId": "getAssetByTypeAndNetwork",
        "description": "자산 유형 ID와 네트워크 ID의 조합으로 단일 운영 자산을 조회한다. 두 ID는 모두 1 이상의 정수여야 한다.",
        "parameters": [
          {
            "in": "query",
            "name": "asset_type_id",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "in": "query",
            "name": "network_id",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "운영 자산 상세",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/Asset"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/assets/{id}": {
      "get": {
        "tags": [
          "Refdata"
        ],
        "summary": "운영 자산 상세 조회",
        "operationId": "getAsset",
        "description": "숫자 `asset_id`로 네트워크·컨트랙트·소수점 등 운영 자산 상세를 조회한다.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "example": 36
            }
          }
        ],
        "responses": {
          "200": {
            "description": "운영 자산 상세",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/Asset"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/assets/{asset_id}/validate-address": {
      "post": {
        "tags": [
          "Refdata"
        ],
        "summary": "입금 주소 유효성 검사",
        "operationId": "validateAssetAddress",
        "description": "특정 운영 자산의 체인 규칙으로 주소 형식과 정규화 결과를 검사한다. `is_valid=false`는 API 오류가 아니라 정상 검사 결과다.",
        "parameters": [
          {
            "in": "path",
            "name": "asset_id",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "example": 1
            },
            "description": "자산 ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "address"
                ],
                "properties": {
                  "address": {
                    "type": "string",
                    "example": "0xabc...def"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "검사 결과",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/ValidateAddressResult"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/time": {
      "get": {
        "tags": [
          "System"
        ],
        "summary": "서버 시간 조회",
        "operationId": "getServerTime",
        "description": "서버의 현재 시간을 ISO 8601 형식과 타임스탬프로 반환한다.",
        "security": [],
        "responses": {
          "200": {
            "description": "서버 시간 정보",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/SystemTime"
                        }
                      }
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/health": {
      "get": {
        "tags": [
          "System"
        ],
        "summary": "헬스 체크",
        "operationId": "getHealth",
        "description": "서비스에 연결할 수 있는지 확인하는 상태를 반환한다. 입출금 처리 가능 여부나 외부 네트워크의 정상 상태를 보장하지 않으므로 업무 API도 함께 확인한다.",
        "security": [],
        "responses": {
          "200": {
            "description": "시스템 상태 정보",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/SystemHealth"
                        }
                      }
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/version": {
      "get": {
        "tags": [
          "System"
        ],
        "summary": "버전 정보 조회",
        "operationId": "getVersion",
        "description": "현재 실행 중인 서버의 버전, 빌드 ID, 커밋 해시를 반환한다.",
        "security": [],
        "responses": {
          "200": {
            "description": "버전 정보",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/SystemVersion"
                        }
                      }
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/users/{uid}/accounts": {
      "get": {
        "tags": [
          "Users"
        ],
        "summary": "사용자 계정 목록 조회",
        "operationId": "listUserAccounts",
        "description": "특정 고객사 사용자 식별자 `uid`에 속한 모든 계정을 조회한다. 일치하는 계정이 없으면 오류 대신 빈 `items`와 `total=0`을 반환한다.",
        "parameters": [
          {
            "in": "path",
            "name": "uid",
            "required": true,
            "schema": {
              "type": "string",
              "example": "user-001"
            },
            "description": "계정 생성 시 사용한 고객사 사용자 고유 식별자"
          }
        ],
        "responses": {
          "200": {
            "description": "사용자 계정 목록",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "items": {
                              "type": "array",
                              "items": {
                                "$ref": "#/components/schemas/UserAccount"
                              }
                            },
                            "total": {
                              "type": "integer"
                            }
                          },
                          "required": [
                            "items",
                            "total"
                          ]
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/withdrawals/quote": {
      "post": {
        "tags": [
          "Withdrawals"
        ],
        "summary": "출금 견적 조회",
        "operationId": "quoteWithdrawal",
        "description": "출금 전에 계정 상태, 주소, 한도, 수수료, 잔액과 내부이체 여부를 검증한다. `to_address`가 플랫폼 입금 주소이면 INTERNAL 견적으로 판별될 수 있다. 견적은 예약이나 보장이 아니며 실제 생성 시 동일한 검증을 다시 수행한다.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QuoteWithdrawalReq"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "출금 견적",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/WithdrawalQuote"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/withdrawals": {
      "post": {
        "tags": [
          "Withdrawals"
        ],
        "summary": "외부 출금 생성",
        "operationId": "createWithdrawal",
        "description": "외부 체인 주소로 출금을 생성한다. 금액은 문자열 전송을 권장하며 실제 계정 차감액은 `amount + fee_amount`다. 응답 유실 복구와 중복 생성 방지를 위해 고객사에서 고유한 `client_request_id`를 지정해야 한다.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWithdrawalReq"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "생성된 출금",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/Withdrawal"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/InsufficientBalance"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "get": {
        "tags": [
          "Withdrawals"
        ],
        "summary": "출금 목록 조회",
        "operationId": "listWithdrawals",
        "description": "기본은 page/page_size 기반 조회이며, after_id를 지정하면 커서(출금 ID 오름차순) 기반 증분 조회로 동작한다(외부 백엔드 동기화 용도). 커서 조회 응답은 page/page_size/total 대신 next_cursor/has_more를 반환한다.",
        "parameters": [
          {
            "in": "query",
            "name": "account_id",
            "required": true,
            "description": "1 이상의 정수 ID",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "example": 1
            }
          },
          {
            "in": "query",
            "name": "from",
            "description": "조회 시작일(포함), YYYY-MM-DD",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "in": "query",
            "name": "to",
            "description": "조회 종료일(포함), YYYY-MM-DD",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "in": "query",
            "name": "page",
            "description": "페이지 번호 (after_id 지정 시 무시됨)",
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "in": "query",
            "name": "page_size",
            "description": "페이지 크기 (after_id 지정 시 무시됨)",
            "schema": {
              "type": "integer",
              "default": 20,
              "maximum": 100
            }
          },
          {
            "in": "query",
            "name": "after_id",
            "description": "커서(after_id) 기반 동기화 조회용. 마지막으로 조회한 withdrawal_id (exclusive). 지정 시 page/page_size는 무시된다.",
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          },
          {
            "in": "query",
            "name": "limit",
            "description": "커서 조회 시 조회 건수 (기본 100, 최대 1000)",
            "schema": {
              "type": "integer",
              "default": 100,
              "maximum": 1000
            }
          }
        ],
        "responses": {
          "200": {
            "description": "출금 목록. page/page_size 지정 시 페이지네이션 응답(page/page_size/total), after_id 지정 시 커서 응답(next_cursor/has_more)을 반환한다.",
            "content": {
              "application/json": {
                "examples": {
                  "pageMode": {
                    "summary": "페이지 조회",
                    "value": {
                      "success": true,
                      "data": {
                        "items": [
                          {
                            "withdrawal_id": 8001,
                            "transfer_type": 1000,
                            "from_account_id": 1,
                            "to_account_id": null,
                            "from_user_id": "user-001",
                            "to_user_id": null,
                            "account_id": 1,
                            "asset_id": "36",
                            "asset_type_id": "18",
                            "asset_type_code": "USDC",
                            "asset_type_name": "USD Coin",
                            "network_id": "31",
                            "network_code": "sepolia",
                            "network_display_name": "Ethereum Sepolia",
                            "decimals": 6,
                            "amount": "125.5",
                            "fee_amount": "1",
                            "amount_raw": "125500000",
                            "fee_amount_raw": "1000000",
                            "to_address": "0x1111111111111111111111111111111111111111",
                            "request_type": "EXTERNAL",
                            "status": "COMPLETED",
                            "user_status": "COMPLETED",
                            "client_request_id": "wd-20260819-000001",
                            "tx_hash": "0x7f3d9d8c4a12",
                            "created_at": "2026-08-19T05:30:00.000Z",
                            "updated_at": "2026-08-19T05:35:00.000Z",
                            "completed_at": "2026-08-19T05:35:00.000Z"
                          }
                        ],
                        "page": 1,
                        "page_size": 20,
                        "total": 1
                      },
                      "error": null
                    }
                  },
                  "cursorMode": {
                    "summary": "커서 조회",
                    "value": {
                      "success": true,
                      "data": {
                        "items": [
                          {
                            "withdrawal_id": 8001,
                            "transfer_type": 1000,
                            "from_account_id": 1,
                            "to_account_id": null,
                            "from_user_id": "user-001",
                            "to_user_id": null,
                            "account_id": 1,
                            "asset_id": "36",
                            "asset_type_id": "18",
                            "asset_type_code": "USDC",
                            "asset_type_name": "USD Coin",
                            "network_id": "31",
                            "network_code": "sepolia",
                            "network_display_name": "Ethereum Sepolia",
                            "decimals": 6,
                            "amount": "125.5",
                            "fee_amount": "1",
                            "amount_raw": "125500000",
                            "fee_amount_raw": "1000000",
                            "to_address": "0x1111111111111111111111111111111111111111",
                            "request_type": "EXTERNAL",
                            "status": "COMPLETED",
                            "user_status": "COMPLETED",
                            "client_request_id": "wd-20260819-000001",
                            "tx_hash": "0x7f3d9d8c4a12",
                            "created_at": "2026-08-19T05:30:00.000Z",
                            "updated_at": "2026-08-19T05:35:00.000Z",
                            "completed_at": "2026-08-19T05:35:00.000Z"
                          }
                        ],
                        "next_cursor": 8001,
                        "has_more": false
                      },
                      "error": null
                    }
                  }
                },
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "items": {
                              "type": "array",
                              "items": {
                                "$ref": "#/components/schemas/WithdrawalListItem"
                              }
                            },
                            "page": {
                              "type": "integer",
                              "description": "page 기반 조회일 때만 포함"
                            },
                            "page_size": {
                              "type": "integer",
                              "description": "page 기반 조회일 때만 포함"
                            },
                            "total": {
                              "type": "integer",
                              "description": "page 기반 조회일 때만 포함"
                            },
                            "next_cursor": {
                              "type": "integer",
                              "description": "after_id 기반 조회일 때만 포함. 마지막 item의 withdrawal_id"
                            },
                            "has_more": {
                              "type": "boolean",
                              "description": "after_id 기반 조회일 때만 포함. items.length == limit이면 true"
                            }
                          },
                          "required": [
                            "items"
                          ],
                          "oneOf": [
                            {
                              "required": [
                                "page",
                                "page_size",
                                "total"
                              ]
                            },
                            {
                              "required": [
                                "next_cursor",
                                "has_more"
                              ]
                            }
                          ]
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/withdrawals/internal": {
      "post": {
        "tags": [
          "Withdrawals"
        ],
        "summary": "내부 이체 생성",
        "operationId": "createInternalTransfer",
        "description": "동일 플랫폼 내 다른 활성 계정으로 자산을 즉시 이체한다. 동일 계정으로의 이체는 허용되지 않으며 내부이체 수수료는 0이다. 재시도 안전성을 위해 고유한 `client_request_id` 사용을 권장한다.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateInternalTransferReq"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "생성된 내부 이체",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/Withdrawal"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/InsufficientBalance"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/withdrawals/{withdrawal_id}": {
      "get": {
        "tags": [
          "Withdrawals"
        ],
        "summary": "출금 상세 조회",
        "operationId": "getWithdrawal",
        "description": "숫자 `withdrawal_id`로 외부 출금 또는 내부이체의 현재 처리 상태와 체인 트랜잭션 정보를 조회한다.",
        "parameters": [
          {
            "in": "path",
            "name": "withdrawal_id",
            "required": true,
            "description": "1 이상의 정수 ID",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "example": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "출금 상세",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/WithdrawalDetail"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/withdrawals/client-request/{client_request_id}": {
      "get": {
        "tags": [
          "Withdrawals"
        ],
        "summary": "client_request_id로 출금 상세 조회",
        "operationId": "getWithdrawalByClientRequestId",
        "description": "출금 생성 응답을 받지 못했을 때 요청에 사용한 `client_request_id`로 생성 결과를 복구 조회한다. 결과가 없을 때만 신규 생성 요청 여부를 판단한다.",
        "parameters": [
          {
            "in": "path",
            "name": "client_request_id",
            "required": true,
            "description": "출금 요청 시 전달한 고객사 고유 요청 ID",
            "schema": {
              "type": "string",
              "example": "wd-20260819-000001"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "출금 상세",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/WithdrawalDetail"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/withdrawals/{withdrawal_id}/cancel": {
      "post": {
        "tags": [
          "Withdrawals"
        ],
        "summary": "출금 취소",
        "operationId": "cancelWithdrawal",
        "description": "아직 취소 가능한 초기 상태의 출금 요청을 취소한다. 이미 체인 전송 단계로 진행된 요청은 `WITHDRAWAL_NOT_CANCELLABLE`(409)을 반환한다.",
        "parameters": [
          {
            "in": "path",
            "name": "withdrawal_id",
            "required": true,
            "description": "1 이상의 정수 ID",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "example": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "취소 결과",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiSuccess"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/CancelWithdrawalResult"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    }
  },
  "tags": [
    {
      "name": "Accounts",
      "description": "계정 및 입금 주소, 잔액 조회"
    },
    {
      "name": "Deposits",
      "description": "입금 내역 조회"
    },
    {
      "name": "Ledger",
      "description": "원장 및 트랜잭션 내역 조회"
    },
    {
      "name": "Prices",
      "description": "시세 정보 조회"
    },
    {
      "name": "Reconciliation",
      "description": "외부 시스템과의 자산 대사(Reconciliation)용 커서 기반 조회 API"
    },
    {
      "name": "Refdata",
      "description": "자산 및 네트워크 참조 데이터 조회"
    },
    {
      "name": "System",
      "description": "시스템 상태 및 유틸리티"
    },
    {
      "name": "Users",
      "description": "사용자 관련 정보 및 계정 목록 조회"
    },
    {
      "name": "Withdrawals",
      "description": "출금(외부/내부이체) 견적, 생성, 조회, 취소"
    }
  ]
}
