openapi: 3.0.3 info: title: Telegram Bot Workers API description: | Cloudflare Workers 기반 Telegram Bot의 Public API 문서입니다. ## 인증 방식 - **API Key**: `X-API-Key` 헤더 사용 (Deposit API) - **Bearer Token**: `Authorization: Bearer {token}` 헤더 (Metrics API) - **Query Parameter**: `?token=...` (Telegram Webhook 관련) - **CORS**: hosting.inouter.com만 허용 (Contact Form) ## Rate Limiting - 사용자당 30 requests / 60초 (Telegram 메시지) - Rate limit 초과 시 429 응답 ## Architecture - **Runtime**: Cloudflare Workers (Edge Computing) - **Database**: D1 SQLite - **KV Store**: Rate Limiting, Caching - **AI**: OpenAI API (via Cloudflare AI Gateway) ## Related Services - **namecheap-api**: 도메인 등록 백엔드 (Deposit API 사용) - **Email Routing**: 입금 SMS 자동 매칭 - **Cloudflare Pages**: 공식 웹사이트 (hosting.inouter.com) version: 1.0.0 contact: name: API Support url: https://hosting.inouter.com license: name: MIT servers: - url: https://telegram-summary-bot.kappa-d8e.workers.dev description: Production server - url: http://localhost:8787 description: Local development tags: - name: Health description: 서비스 상태 확인 - name: Telegram description: Telegram Webhook 관리 - name: Contact description: 웹사이트 문의 - name: Deposit description: 예치금 관리 (Internal API) - name: Monitoring description: 시스템 모니터링 paths: /health: get: tags: [Health] summary: Health Check description: | 서비스 정상 동작 여부를 확인합니다. **보안 정책**: 최소 정보만 반환 (DB 정보 미노출) operationId: getHealth responses: '200': description: 서비스 정상 content: application/json: schema: type: object required: [status, timestamp] properties: status: type: string enum: [ok] example: ok description: 서비스 상태 timestamp: type: string format: date-time example: "2026-01-19T12:34:56.789Z" description: 응답 생성 시각 (ISO 8601) /webhook-info: get: tags: [Telegram] summary: Webhook 정보 조회 description: | 현재 설정된 Telegram Webhook 정보를 확인합니다. **인증**: Telegram Bot Token 필요 operationId: getWebhookInfo parameters: - name: token in: query required: true schema: type: string minLength: 40 description: Telegram Bot Token (BOT_TOKEN) example: "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11" responses: '200': description: Webhook 정보 (Telegram API 응답) content: application/json: schema: type: object description: Telegram getWebhookInfo API 응답 example: ok: true result: url: "https://telegram-summary-bot.kappa-d8e.workers.dev/webhook" has_custom_certificate: false pending_update_count: 0 '401': description: 인증 실패 (잘못된 Bot Token) content: application/json: schema: $ref: '#/components/schemas/Error' example: success: false error: "Unauthorized" '500': description: Telegram API 호출 실패 content: application/json: schema: $ref: '#/components/schemas/Error' /setup-webhook: get: tags: [Telegram] summary: Webhook 설정 description: | Telegram Webhook을 설정합니다. **인증**: Bot Token + Webhook Secret 필요 **주의**: 이 엔드포인트는 초기 설정 시에만 사용됩니다. operationId: setupWebhook parameters: - name: token in: query required: true schema: type: string minLength: 40 description: Telegram Bot Token (BOT_TOKEN) - name: secret in: query required: true schema: type: string minLength: 1 description: Webhook Secret Token (WEBHOOK_SECRET) responses: '200': description: Webhook 설정 성공 content: text/plain: schema: type: string example: "Webhook 설정 완료" '400': description: 잘못된 요청 (파라미터 누락) content: text/plain: schema: type: string example: "Token과 Secret이 필요합니다" '500': description: Webhook 설정 실패 content: text/plain: schema: type: string /api/contact: post: tags: [Contact] summary: 문의 제출 description: | 웹사이트 문의 폼을 제출합니다. **CORS 정책**: hosting.inouter.com만 허용 **처리**: Telegram 메시지로 전달 operationId: submitContact requestBody: required: true content: application/json: schema: type: object required: [name, email, message] properties: name: type: string minLength: 1 maxLength: 100 example: "홍길동" description: 문의자 이름 email: type: string format: email maxLength: 100 example: "hong@example.com" description: 문의자 이메일 phone: type: string maxLength: 20 example: "010-1234-5678" description: 문의자 연락처 (선택) message: type: string minLength: 10 maxLength: 1000 example: "도메인 등록 문의드립니다." description: 문의 내용 responses: '200': description: 문의 접수 완료 content: application/json: schema: type: object required: [success, message] properties: success: type: boolean example: true message: type: string example: "문의가 접수되었습니다." '400': description: 잘못된 요청 (필드 누락 또는 형식 오류) content: application/json: schema: $ref: '#/components/schemas/Error' example: success: false error: "이름, 이메일, 메시지는 필수입니다." '403': description: CORS 위반 (허용되지 않은 Origin) content: application/json: schema: $ref: '#/components/schemas/Error' example: success: false error: "Forbidden" '500': description: 서버 오류 content: application/json: schema: $ref: '#/components/schemas/Error' options: tags: [Contact] summary: CORS Preflight description: CORS preflight 요청 처리 operationId: contactPreflight responses: '200': description: CORS 허용 headers: Access-Control-Allow-Origin: schema: type: string example: https://hosting.inouter.com Access-Control-Allow-Methods: schema: type: string example: POST, OPTIONS Access-Control-Allow-Headers: schema: type: string example: Content-Type /api/deposit/balance: get: tags: [Deposit] summary: 잔액 조회 description: | 사용자의 예치금 잔액을 조회합니다. **용도**: Internal API (namecheap-api 전용) **인증**: API Key 필요 operationId: getDepositBalance security: - ApiKeyAuth: [] parameters: - name: telegram_id in: query required: true schema: type: string pattern: '^\d+$' description: Telegram User ID example: "821596605" responses: '200': description: 잔액 정보 content: application/json: schema: type: object required: [balance] properties: balance: type: integer minimum: 0 example: 50000 description: 예치금 잔액 (원) '400': description: 잘못된 요청 (telegram_id 누락) content: application/json: schema: $ref: '#/components/schemas/Error' example: success: false error: "telegram_id가 필요합니다." '401': description: 인증 실패 (잘못된 API Key) content: application/json: schema: $ref: '#/components/schemas/Error' example: success: false error: "Unauthorized" '404': description: 사용자 없음 content: application/json: schema: $ref: '#/components/schemas/Error' example: success: false error: "사용자를 찾을 수 없습니다." /api/deposit/deduct: post: tags: [Deposit] summary: 잔액 차감 description: | 예치금에서 금액을 차감합니다. **용도**: Internal API (namecheap-api 전용) **인증**: API Key 필요 **트랜잭션**: DB 트랜잭션으로 원자성 보장 operationId: deductDeposit security: - ApiKeyAuth: [] requestBody: required: true content: application/json: schema: type: object required: [telegram_id, amount, reason] properties: telegram_id: type: string pattern: '^\d+$' example: "821596605" description: Telegram User ID amount: type: integer minimum: 1 example: 15000 description: 차감 금액 (원, 양수) reason: type: string minLength: 1 maxLength: 200 example: "도메인 등록: example.com" description: 차감 사유 responses: '200': description: 차감 성공 content: application/json: schema: type: object required: [success, new_balance, transaction_id] properties: success: type: boolean example: true new_balance: type: integer minimum: 0 example: 35000 description: 차감 후 잔액 (원) transaction_id: type: integer example: 123 description: 생성된 거래 ID '400': description: 잘못된 요청 또는 잔액 부족 content: application/json: schema: type: object required: [success, error] properties: success: type: boolean example: false error: type: string example: "잔액이 부족합니다." examples: insufficient_balance: summary: 잔액 부족 value: success: false error: "잔액이 부족합니다." invalid_amount: summary: 잘못된 금액 value: success: false error: "금액은 양수여야 합니다." '401': description: 인증 실패 content: application/json: schema: $ref: '#/components/schemas/Error' '404': description: 사용자 없음 content: application/json: schema: $ref: '#/components/schemas/Error' /api/metrics: get: tags: [Monitoring] summary: 시스템 메트릭스 description: | Circuit Breaker 상태 및 API 성능 메트릭스를 조회합니다. **인증**: Bearer Token 필요 (관리자 전용) **용도**: 시스템 모니터링 및 디버깅 operationId: getMetrics security: - BearerAuth: [] responses: '200': description: 메트릭스 정보 content: application/json: schema: type: object required: [circuitBreakers, apiMetrics] properties: circuitBreakers: type: object description: Circuit Breaker 상태 맵 (서비스명 → 상태) additionalProperties: type: object properties: state: type: string enum: [CLOSED, OPEN, HALF_OPEN] description: 현재 상태 failureCount: type: integer description: 연속 실패 횟수 lastFailureTime: type: integer description: 마지막 실패 시각 (Unix timestamp ms) nextAttemptTime: type: integer description: 다음 시도 가능 시각 (Unix timestamp ms) example: "OpenAI API": state: "CLOSED" failureCount: 0 lastFailureTime: null nextAttemptTime: null apiMetrics: type: object description: API 호출 통계 맵 (API명 → 메트릭스) additionalProperties: type: object properties: totalCalls: type: integer description: 총 호출 횟수 successCalls: type: integer description: 성공 횟수 failureCalls: type: integer description: 실패 횟수 averageDuration: type: number description: 평균 응답 시간 (ms) lastError: type: string nullable: true description: 마지막 에러 메시지 example: "OpenAI Chat Completion": totalCalls: 1234 successCalls: 1200 failureCalls: 34 averageDuration: 1523.5 lastError: null '401': description: 인증 실패 content: application/json: schema: $ref: '#/components/schemas/Error' example: success: false error: "Unauthorized" components: securitySchemes: ApiKeyAuth: type: apiKey in: header name: X-API-Key description: | Deposit API 인증 키 (DEPOSIT_API_SECRET) **용도**: namecheap-api에서 사용 **획득**: wrangler secret BearerAuth: type: http scheme: bearer description: | Metrics API 인증 토큰 (WEBHOOK_SECRET) **형식**: `Authorization: Bearer {WEBHOOK_SECRET}` **용도**: 관리자 전용 모니터링 schemas: Error: type: object required: [success, error] properties: success: type: boolean example: false description: 항상 false error: type: string example: "오류 메시지" description: 에러 설명