558 lines
17 KiB
YAML
558 lines
17 KiB
YAML
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: 에러 설명
|