ESC

MVNO TMS API 개요

MVNO TMS(Ticket Management System)는 MVNO 사업자를 위한 고객 상담 티켓 관리 시스템 API입니다. 멀티테넌트 아키텍처를 기반으로 CS 티켓, 고객, 회원 관리 및 대시보드 기능을 제공합니다.

Base URL

Base URL
http://localhost:8000

인증 방식

모든 API 요청에는 JWT Bearer 토큰이 필요합니다. /api/auth/login 엔드포인트를 통해 토큰을 발급받으세요. Webhook 엔드포인트는 JWT 대신 API Key 인증을 사용합니다.

인증 헤더
Authorization: Bearer <access_token>

// Webhook 엔드포인트
X-API-Key: <api_key>
X-Tenant-ID: <tenant_id>

공통 에러 응답 형식

모든 에러 응답은 아래의 통일된 형식을 따릅니다.

JSON
{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "인증이 필요합니다",
    "details": null
  }
}

에러 코드 목록

HTTP 상태에러 코드설명
400INVALID_STATUS_TRANSITION허용되지 않는 상태 변경
400INVALID_REQUEST요청 데이터 검증 실패
401UNAUTHORIZED인증 실패
403FORBIDDEN권한 없음
403TENANT_INACTIVE비활성 테넌트
404NOT_FOUND리소스 없음
409SEAT_LIMIT_EXCEEDED최대 좌석 수 초과
409DUPLICATE_ENTRY중복 데이터
429RATE_LIMIT_EXCEEDED요청 속도 제한 초과

속도 제한 (Rate Limiting)

API 요청은 속도 제한이 적용됩니다. 제한을 초과하면 429 RATE_LIMIT_EXCEEDED 에러가 반환됩니다. 응답 헤더에서 현재 상태를 확인할 수 있습니다.

응답 헤더
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1710000000

CS 티켓 상태 플로우

received assigned in_progress on_hold / completed
참고: 상태 변경은 허용된 전환만 가능합니다. 허용되지 않는 상태 전환 시 INVALID_STATUS_TRANSITION 에러가 반환됩니다.

페이지네이션

목록 조회 API는 커서 기반 페이지네이션을 사용합니다. 응답에 포함된 next_cursor 값을 다음 요청의 쿼리 파라미터로 전달하세요.

JSON
{
  "items": [...],
  "next_cursor": "eyJpZCI6IDEwMH0",
  "total": 254
}

인증 (Auth)

사용자 인증 및 계정 관리 API입니다. 로그인하여 JWT 토큰을 발급받고, 이를 사용하여 다른 API에 접근합니다.

POST /api/auth/login 사용자 로그인

이메일과 비밀번호로 로그인하여 JWT 액세스 토큰을 발급받습니다.

Request Body
JSON
{
  "email": "admin@example.com",
  "password": "securePassword123"
}
필드타입필수설명
emailstring필수사용자 이메일
passwordstring필수비밀번호
Response 200
JSON
{
  "access_token": "eyJhbGciOiJIUzI1NiIs...",
  "token_type": "bearer",
  "user": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "tenant_id": "tenant-001",
    "email": "admin@example.com",
    "name": "관리자",
    "role_name": "admin",
    "permissions": [
      "cs:read",
      "cs:write",
      "members:read",
      "members:write"
    ]
  }
}
에러 응답
HTTP 상태코드설명
401UNAUTHORIZED이메일 또는 비밀번호가 일치하지 않습니다
403TENANT_INACTIVE비활성 테넌트에 속한 사용자입니다
POST /api/auth/logout 로그아웃

현재 세션을 종료하고 토큰을 무효화합니다.

Request Headers
헤더필수
AuthorizationBearer <token>필수
Response 200
JSON
{
  "message": "로그아웃 되었습니다"
}
GET /api/auth/me 내 정보 조회

현재 인증된 사용자의 정보를 조회합니다.

Response 200
JSON
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "tenant_id": "tenant-001",
  "email": "admin@example.com",
  "name": "관리자",
  "role_name": "admin",
  "permissions": [
    "cs:read",
    "cs:write",
    "members:read",
    "members:write"
  ]
}
에러 응답
HTTP 상태코드설명
401UNAUTHORIZED유효하지 않은 토큰입니다
POST /api/auth/change-password 비밀번호 변경

현재 비밀번호를 확인 후 새 비밀번호로 변경합니다.

Request Body
JSON
{
  "current_password": "oldPassword123",
  "new_password": "newSecurePassword456"
}
필드타입필수설명
current_passwordstring필수현재 비밀번호
new_passwordstring필수새 비밀번호
Response 200
JSON
{
  "message": "비밀번호가 변경되었습니다"
}
에러 응답
HTTP 상태코드설명
400INVALID_REQUEST비밀번호 형식이 올바르지 않습니다
401UNAUTHORIZED현재 비밀번호가 일치하지 않습니다

CS 관리

CS 티켓의 조회, 상태 변경, 담당자 배정, 통화 기록, 이력, 메모 관리 API입니다.

GET /api/cs/tickets 티켓 목록 조회

필터 조건에 맞는 CS 티켓 목록을 조회합니다. 커서 기반 페이지네이션을 지원합니다.

Query Parameters
파라미터타입필수설명
statusstring선택상태 필터 (received, assigned, in_progress, on_hold, completed)
assignee_idstring선택담당자 ID 필터
prioritystring선택우선순위 필터 (low, medium, high, urgent)
date_fromstring선택시작일 (YYYY-MM-DD)
date_tostring선택종료일 (YYYY-MM-DD)
limitinteger선택조회 건수 (기본값: 20, 최대: 100)
cursorstring선택페이지네이션 커서
Response 200
JSON
{
  "items": [
    {
      "id": "ticket-001",
      "ticket_number": "CS-20260317-0001",
      "status": "in_progress",
      "priority": "high",
      "category": "billing",
      "customer_name": "홍길동",
      "customer_phone": "010-1234-5678",
      "assignee_name": "김상담",
      "created_at": "2026-03-17T09:30:00Z",
      "updated_at": "2026-03-17T10:15:00Z"
    }
  ],
  "next_cursor": "eyJpZCI6IDEwMH0",
  "total": 254
}
GET /api/cs/tickets/{id} 티켓 상세 조회

특정 CS 티켓의 상세 정보를 조회합니다.

Path Parameters
파라미터타입필수설명
idstring필수티켓 ID
Response 200
JSON
{
  "id": "ticket-001",
  "ticket_number": "CS-20260317-0001",
  "status": "in_progress",
  "priority": "high",
  "category": "billing",
  "customer": {
    "id": "cust-001",
    "name": "홍길동",
    "phone": "010-1234-5678",
    "carrier": "KT",
    "language": "ko"
  },
  "assignee": {
    "id": "user-002",
    "name": "김상담"
  },
  "stt_text": "요금 관련 문의입니다...",
  "stt_summary": "요금제 변경 요청",
  "recording_url": "https://r2.example.com/recordings/call-001.mp3",
  "duration_seconds": 180,
  "created_at": "2026-03-17T09:30:00Z",
  "updated_at": "2026-03-17T10:15:00Z"
}
에러 응답
HTTP 상태코드설명
404NOT_FOUND티켓을 찾을 수 없습니다
PATCH /api/cs/tickets/{id}/status 티켓 상태 변경

CS 티켓의 상태를 변경합니다. 허용된 상태 전환만 가능합니다.

상태 전환 규칙: received → assigned → in_progress → on_hold / completed. 역방향 전환은 허용되지 않습니다.
Request Body
JSON
{
  "status": "in_progress"
}
Response 200
JSON
{
  "ticket_id": "ticket-001",
  "status": "in_progress"
}
에러 응답
HTTP 상태코드설명
400INVALID_STATUS_TRANSITION허용되지 않는 상태 변경입니다
404NOT_FOUND티켓을 찾을 수 없습니다
PATCH /api/cs/tickets/{id}/assign 담당자 배정

CS 티켓에 담당자를 배정합니다.

Request Body
JSON
{
  "assignee_id": "user-002"
}
Response 200
JSON
{
  "ticket_id": "ticket-001",
  "assignee_id": "user-002"
}
에러 응답
HTTP 상태코드설명
404NOT_FOUND티켓 또는 담당자를 찾을 수 없습니다
GET /api/cs/tickets/{id}/calls 통화 기록 조회

특정 티켓에 연결된 통화 기록 목록을 조회합니다.

Response 200
JSON
[
  {
    "id": "call-001",
    "caller_phone": "010-1234-5678",
    "duration_seconds": 180,
    "recording_url": "https://r2.example.com/recordings/call-001.mp3",
    "stt_text": "요금 관련 문의입니다...",
    "called_at": "2026-03-17T09:30:00Z"
  }
]
GET /api/cs/tickets/{id}/history 티켓 이력 조회

특정 티켓의 상태 변경 및 작업 이력을 조회합니다.

Response 200
JSON
[
  {
    "id": "hist-001",
    "action": "status_changed",
    "from_value": "received",
    "to_value": "assigned",
    "changed_by": "김상담",
    "created_at": "2026-03-17T09:35:00Z"
  }
]
POST /api/cs/tickets/{id}/notes 티켓 메모 작성

특정 티켓에 메모를 추가합니다. 내부 메모는 고객에게 표시되지 않습니다.

Request Body
JSON
{
  "content": "고객이 요금제 변경을 원합니다. 확인 필요.",
  "is_internal": true
}
필드타입필수설명
contentstring필수메모 내용
is_internalboolean선택내부 메모 여부 (기본값: false)
Response 201
JSON
{
  "id": "note-001",
  "ticket_id": "ticket-001",
  "content": "고객이 요금제 변경을 원합니다. 확인 필요.",
  "is_internal": true,
  "created_by": "김상담",
  "created_at": "2026-03-17T10:00:00Z"
}
GET /api/cs/tickets/{id}/notes 티켓 메모 목록

특정 티켓의 메모 목록을 조회합니다.

Response 200
JSON
[
  {
    "id": "note-001",
    "content": "고객이 요금제 변경을 원합니다.",
    "is_internal": true,
    "created_by": "김상담",
    "created_at": "2026-03-17T10:00:00Z"
  }
]
POST /api/cs/translate 텍스트 번역

텍스트를 지정한 언어로 번역합니다. CS 상담 중 다국어 고객 대응에 사용합니다.

권한: cs:read
Request Body
JSON
{
  "text": "요금제 변경을 원합니다",
  "target_lang": "en"
}
필드타입필수설명
textstring필수번역할 텍스트
target_langstring필수목표 언어 코드 (ko, en, ja, zh, vi)
Response 200
JSON
{
  "translated_text": "I want to change my plan",
  "target_lang": "en"
}

고객 관리

고객 정보 조회, 수정 및 고객별 메모 관리 API입니다.

GET /api/customers 고객 목록 조회

고객 목록을 검색 및 조회합니다.

Query Parameters
파라미터타입필수설명
searchstring선택이름 또는 전화번호 검색
limitinteger선택조회 건수 (기본값: 20)
cursorstring선택페이지네이션 커서
Response 200
JSON
{
  "items": [
    {
      "id": "cust-001",
      "name": "홍길동",
      "phone": "010-1234-5678",
      "carrier": "KT",
      "language": "ko",
      "total_tickets": 3,
      "created_at": "2026-01-15T08:00:00Z"
    }
  ],
  "next_cursor": "eyJpZCI6IDUwfQ",
  "total": 128
}
GET /api/customers/{id} 고객 상세 조회

특정 고객의 상세 정보를 조회합니다.

Response 200
JSON
{
  "id": "cust-001",
  "name": "홍길동",
  "phone": "010-1234-5678",
  "carrier": "KT",
  "language": "ko",
  "total_tickets": 3,
  "recent_tickets": [
    {
      "id": "ticket-001",
      "ticket_number": "CS-20260317-0001",
      "status": "in_progress",
      "category": "billing",
      "created_at": "2026-03-17T09:30:00Z"
    }
  ],
  "created_at": "2026-01-15T08:00:00Z"
}
에러 응답
HTTP 상태코드설명
404NOT_FOUND고객을 찾을 수 없습니다
PATCH /api/customers/{id} 고객 정보 수정

고객의 기본 정보를 수정합니다.

Request Body
JSON
{
  "name": "홍길동",
  "carrier": "SKT",
  "language": "ko"
}
필드타입필수설명
namestring선택고객 이름
carrierstring선택통신사
languagestring선택언어 (ko, en, vi, zh 등)
Response 200
JSON
{
  "id": "cust-001",
  "name": "홍길동",
  "phone": "010-1234-5678",
  "carrier": "SKT",
  "language": "ko"
}
POST /api/customers/{id}/notes 고객 메모 작성

특정 고객에 대한 메모를 추가합니다. 고정 메모는 상단에 항상 표시됩니다.

Request Body
JSON
{
  "content": "VIP 고객 - 우선 처리 필요",
  "is_pinned": true
}
필드타입필수설명
contentstring필수메모 내용
is_pinnedboolean선택고정 메모 여부 (기본값: false)
Response 201
JSON
{
  "id": "cnote-001",
  "customer_id": "cust-001",
  "content": "VIP 고객 - 우선 처리 필요",
  "is_pinned": true,
  "created_by": "김상담",
  "created_at": "2026-03-17T10:30:00Z"
}
GET /api/customers/{id}/notes 고객 메모 목록

특정 고객의 메모 목록을 조회합니다. 고정 메모가 먼저 표시됩니다.

Response 200
JSON
[
  {
    "id": "cnote-001",
    "content": "VIP 고객 - 우선 처리 필요",
    "is_pinned": true,
    "created_by": "김상담",
    "created_at": "2026-03-17T10:30:00Z"
  }
]

회원 관리

팀 멤버 및 역할(Role) 관리 API입니다. 멤버 초대, 역할 생성, 권한 설정 등을 지원합니다.

GET /api/members 멤버 목록 조회

현재 테넌트의 전체 멤버 목록을 조회합니다.

Response 200
JSON
[
  {
    "id": "user-001",
    "email": "admin@example.com",
    "name": "관리자",
    "role_name": "admin",
    "status": "active",
    "created_at": "2026-01-01T00:00:00Z"
  }
]
POST /api/members 멤버 초대

새로운 멤버를 초대합니다. 테넌트의 최대 좌석 수를 초과할 수 없습니다.

Request Body
JSON
{
  "email": "newmember@example.com",
  "name": "박상담",
  "role_id": "role-agent"
}
필드타입필수설명
emailstring필수초대할 이메일
namestring필수멤버 이름
role_idstring필수할당할 역할 ID
Response 201
JSON
{
  "id": "user-003",
  "email": "newmember@example.com",
  "name": "박상담",
  "role_name": "agent",
  "status": "active",
  "created_at": "2026-03-17T11:00:00Z"
}
에러 응답
HTTP 상태코드설명
409SEAT_LIMIT_EXCEEDED최대 좌석 수를 초과했습니다
409DUPLICATE_ENTRY이미 등록된 이메일입니다
PATCH /api/members/{id} 멤버 정보 수정

멤버의 이름, 역할, 상태를 수정합니다.

Request Body
JSON
{
  "name": "박상담 (수정)",
  "role_id": "role-supervisor",
  "status": "active"
}
필드타입필수설명
namestring선택멤버 이름
role_idstring선택변경할 역할 ID
statusstring선택상태 (active, inactive)
Response 200
JSON
{
  "id": "user-003",
  "email": "newmember@example.com",
  "name": "박상담 (수정)",
  "role_name": "supervisor",
  "status": "active"
}

역할 (Roles)

GET /api/roles 역할 목록 조회

현재 테넌트의 역할 목록을 조회합니다.

Response 200
JSON
[
  {
    "id": "role-admin",
    "name": "admin",
    "level": 100,
    "member_count": 2
  },
  {
    "id": "role-agent",
    "name": "agent",
    "level": 10,
    "member_count": 5
  }
]
POST /api/roles 역할 생성

새로운 역할을 생성합니다.

Request Body
JSON
{
  "name": "supervisor",
  "level": 50
}
필드타입필수설명
namestring필수역할 이름
levelinteger필수권한 레벨 (높을수록 상위)
Response 201
JSON
{
  "id": "role-supervisor",
  "name": "supervisor",
  "level": 50,
  "member_count": 0
}
에러 응답
HTTP 상태코드설명
409DUPLICATE_ENTRY이미 존재하는 역할 이름입니다
PATCH /api/roles/{id}/permissions 역할 권한 설정

특정 역할의 메뉴별 접근 권한을 설정합니다.

Request Body
JSON
{
  "permissions": [
    {
      "menu_key": "cs",
      "can_read": true,
      "can_write": true,
      "can_delete": false
    },
    {
      "menu_key": "members",
      "can_read": true,
      "can_write": false,
      "can_delete": false
    }
  ]
}
필드타입필수설명
permissionsarray필수권한 설정 배열
permissions[].menu_keystring필수메뉴 키 (cs, customers, members, dashboard, reports, settings)
permissions[].can_readboolean필수읽기 권한
permissions[].can_writeboolean필수쓰기 권한
permissions[].can_deleteboolean필수삭제 권한
Response 200
JSON
{
  "message": "권한이 업데이트되었습니다"
}
POST /api/members/{member_id}/reset-password 비밀번호 초기화

멤버의 비밀번호를 초기화하고 임시 비밀번호를 생성합니다. 생성된 임시 비밀번호는 응답으로 반환됩니다.

권한: members:write
Path Parameters
파라미터타입필수설명
member_idstring필수멤버 ID
Response 200
JSON
{
  "message": "임시 비밀번호가 생성되었습니다",
  "temp_password": "Tmp@8f2kL9",
  "email": "member@example.com"
}
에러 응답
HTTP 상태코드설명
404NOT_FOUND멤버를 찾을 수 없습니다
403FORBIDDEN비밀번호 초기화 권한이 없습니다

대시보드

대시보드 통계 및 차트 데이터 API입니다.

GET /api/dashboard/stats 대시보드 통계

대시보드에 표시할 주요 통계 데이터를 조회합니다.

Response 200
JSON
{
  "status_counts": {
    "received": 12,
    "assigned": 8,
    "in_progress": 15,
    "on_hold": 3,
    "completed": 142
  },
  "today_completed": 7,
  "api_usage_month": 4523
}
GET /api/dashboard/chart 차트 데이터

일별 티켓 생성 수 차트 데이터를 조회합니다.

Query Parameters
파라미터타입필수설명
daysinteger선택조회 기간 일수 (기본값: 7)
Response 200
JSON
[
  {
    "date": "2026-03-11",
    "count": 23
  },
  {
    "date": "2026-03-12",
    "count": 31
  },
  {
    "date": "2026-03-13",
    "count": 18
  }
]

성과지표

상담원 성과 분석 및 리포트 내보내기 API입니다.

GET /api/reports/performance 성과 리포트

상담원별 성과 데이터를 조회합니다.

Query Parameters
파라미터타입필수설명
date_fromstring선택시작일 (YYYY-MM-DD)
date_tostring선택종료일 (YYYY-MM-DD)
Response 200
JSON
[
  {
    "user_id": "user-002",
    "name": "김상담",
    "total_tickets": 45,
    "completed_tickets": 38,
    "completion_rate": 84.4,
    "avg_handling_minutes": 12.5
  },
  {
    "user_id": "user-003",
    "name": "박상담",
    "total_tickets": 32,
    "completed_tickets": 30,
    "completion_rate": 93.8,
    "avg_handling_minutes": 8.3
  }
]
GET /api/reports/export 리포트 내보내기 (CSV)

성과 리포트를 CSV 파일로 스트리밍 다운로드합니다.

Query Parameters
파라미터타입필수설명
typestring필수리포트 유형 (performance)
date_fromstring선택시작일 (YYYY-MM-DD)
date_tostring선택종료일 (YYYY-MM-DD)
Response 200
Content-Type: text/csv; charset=utf-8
Content-Disposition: attachment; filename="performance_report_20260317.csv"

응답은 CSV 파일 스트리밍으로 반환됩니다. 브라우저에서 직접 다운로드됩니다.

Webhook

외부 시스템(AI 콜센터)에서 호출하는 Webhook API입니다. JWT 대신 API Key 인증을 사용합니다.

인증 방식: Webhook 엔드포인트는 X-API-KeyX-Tenant-ID 헤더를 사용합니다. JWT Bearer 토큰은 사용하지 않습니다.
POST /api/webhook/call-completed 통화 완료 Webhook

AI 콜센터에서 통화가 완료되었을 때 호출됩니다. 자동으로 CS 티켓을 생성합니다.

Request Headers
헤더필수설명
X-API-Keystring필수API 인증 키
X-Tenant-IDstring필수테넌트 식별자
Content-Typeapplication/json필수
Request Body
JSON
{
  "caller_phone": "010-1234-5678",
  "caller_carrier": "KT",
  "language": "ko",
  "category": "billing",
  "recording_file": "recordings/2026/03/17/call-001.mp3",
  "stt_text": "안녕하세요, 요금 관련 문의입니다...",
  "stt_summary": "요금제 변경 요청 건",
  "duration_seconds": 180,
  "called_at": "2026-03-17T09:30:00Z",
  "priority": "medium",
  "metadata": {
    "ai_confidence": 0.95,
    "sentiment": "neutral"
  }
}
필드타입필수설명
caller_phonestring필수발신자 전화번호
caller_carrierstring선택통신사
languagestring선택통화 언어 (기본값: ko)
categorystring선택문의 카테고리
recording_filestring선택녹음 파일 경로
stt_textstring선택STT 전문
stt_summarystring선택STT 요약
duration_secondsinteger필수통화 시간 (초)
called_atstring필수통화 시각 (ISO 8601)
prioritystring선택우선순위 (low, medium, high, urgent)
metadataobject선택추가 메타데이터
Response 201
JSON
{
  "ticket_id": "ticket-001",
  "ticket_number": "CS-20260317-0001",
  "status": "received",
  "message": "티켓이 생성되었습니다"
}
에러 응답
HTTP 상태코드설명
401UNAUTHORIZED유효하지 않은 API Key입니다
400INVALID_REQUEST요청 데이터가 올바르지 않습니다
403TENANT_INACTIVE비활성 테넌트입니다
POST /api/webhook/call-transferred 통화 전환 Webhook

AI 콜센터에서 상담원으로 통화가 전환되었을 때 호출됩니다. 부분 정보로 티켓을 생성합니다.

Request Headers
헤더필수설명
X-API-Keystring필수API 인증 키
X-Tenant-IDstring필수테넌트 식별자
Request Body
JSON
{
  "caller_phone": "010-1234-5678",
  "caller_carrier": "KT",
  "language": "ko",
  "transfer_reason": "complex_issue",
  "partial_stt_text": "안녕하세요, 해지 관련...",
  "partial_summary": "회선 해지 요청 - AI 처리 불가",
  "duration_seconds": 45,
  "called_at": "2026-03-17T09:30:00Z"
}
필드타입필수설명
caller_phonestring필수발신자 전화번호
caller_carrierstring선택통신사
languagestring선택통화 언어
transfer_reasonstring필수전환 사유
partial_stt_textstring선택부분 STT 텍스트
partial_summarystring선택부분 요약
duration_secondsinteger필수AI 응대 시간 (초)
called_atstring필수통화 시각 (ISO 8601)
Response 201
JSON
{
  "ticket_id": "ticket-002",
  "ticket_number": "CS-20260317-0002",
  "status": "received",
  "message": "전환 티켓이 생성되었습니다"
}

설정

테넌트 설정 조회 및 수정 API입니다.

GET /api/settings/tenant 테넌트 설정 조회

현재 테넌트의 설정 정보를 조회합니다.

Response 200
JSON
{
  "name": "ABC 텔레콤",
  "slug": "abc-telecom",
  "plan": "business",
  "max_seats": 20,
  "is_active": true
}
PATCH /api/settings/tenant 테넌트 설정 수정

테넌트의 기본 설정을 수정합니다.

Request Body
JSON
{
  "name": "ABC 텔레콤 (주)"
}
필드타입필수설명
namestring필수테넌트 이름
Response 200
JSON
{
  "name": "ABC 텔레콤 (주)",
  "slug": "abc-telecom",
  "plan": "business",
  "max_seats": 20,
  "is_active": true
}
에러 응답
HTTP 상태코드설명
403FORBIDDEN설정 수정 권한이 없습니다

시스템

시스템 상태 확인 API입니다. 인증 없이 접근 가능합니다.

GET /api/health 헬스체크

시스템의 전반적인 상태를 확인합니다. 데이터베이스 및 R2 스토리지 연결 상태를 포함합니다.

인증 불필요: 이 엔드포인트는 인증 없이 접근할 수 있습니다.
Response 200
JSON
{
  "status": "healthy",
  "db": "connected",
  "r2": "connected",
  "timestamp": "2026-03-17T12:00:00Z"
}

조회 서비스 (Inquiry)

고객의 요금제, 청구, 데이터 사용량, 납부 이력을 조회하는 외부 연동 API입니다.

인증 방식: 이 섹션의 모든 엔드포인트는 JWT Bearer 토큰 대신 X-API-KeyX-Tenant-Id 헤더를 사용합니다.
인증 헤더
Headers
X-API-Key: <api_key>
X-Tenant-Id: <tenant_id>
GET /api/inquiry/customers/{customer_id}/plan 요금제 정보 조회

고객의 현재 가입 요금제 정보를 조회합니다.

Path Parameters
파라미터타입필수설명
customer_idstring필수고객 ID
Response 200
JSON
{
  "plan_name": "기본 5GB 요금제",
  "monthly_fee": 29000,
  "data_limit_gb": 5.0,
  "call_minutes": 300,
  "sms_count": 100,
  "start_date": "2026-01-01",
  "contract_end_date": null
}
GET /api/inquiry/customers/{customer_id}/billing 청구 내역 조회

고객의 월별 청구 내역 목록을 조회합니다.

Path Parameters
파라미터타입필수설명
customer_idstring필수고객 ID
Response 200
JSON
[
  {
    "billing_month": "2026-03",
    "total_amount": 32500,
    "data_charge": 29000,
    "call_charge": 2000,
    "sms_charge": 500,
    "additional_charge": 1000,
    "payment_status": "paid",
    "due_date": "2026-03-25"
  }
]
GET /api/inquiry/customers/{customer_id}/data-usage 데이터 사용량 조회

고객의 현재 청구 주기 내 데이터, 통화, SMS 사용량을 조회합니다.

Path Parameters
파라미터타입필수설명
customer_idstring필수고객 ID
Response 200
JSON
{
  "data_used_gb": 3.2,
  "data_limit_gb": 5.0,
  "data_remaining_gb": 1.8,
  "call_used_minutes": 120,
  "call_limit_minutes": 300,
  "call_remaining_minutes": 180,
  "sms_used": 45,
  "sms_limit": 100,
  "sms_remaining": 55,
  "period_start": "2026-03-01",
  "period_end": "2026-03-31"
}
GET /api/inquiry/customers/{customer_id}/payments 납부 이력 조회

고객의 납부 이력을 조회합니다.

Path Parameters
파라미터타입필수설명
customer_idstring필수고객 ID
Response 200
JSON
{
  "payments": [
    {
      "payment_date": "2026-03-20",
      "amount": 32500,
      "method": "card",
      "status": "completed",
      "billing_month": "2026-03"
    }
  ],
  "total_count": 12
}

AI 프록시

AI 콜센터 설정, 지식 베이스, 사용량 통계, 실시간 통화 관리 API입니다. JWT Bearer 토큰 인증을 사용합니다.

Health

GET /api/ai/health AI 서비스 헬스체크

AI 프록시 서비스 및 연결된 AI 프로바이더의 상태를 확인합니다.

인증 불필요: 이 엔드포인트는 인증 없이 접근할 수 있습니다.
Response 200
JSON
{
  "status": "ok",
  "providers": {
    "openai": "ok"
  }
}

테넌트 설정 (Tenant Config)

GET /api/ai/tenants/{tenant_id}/config AI 설정 조회

테넌트의 AI 설정 전체를 조회합니다.

권한: settings:read
Path Parameters
파라미터타입필수설명
tenant_idstring필수테넌트 ID
Response 200
JSON
{
  "ai_provider": "openai",
  "model": "gpt-4o",
  "temperature": 0.7,
  "system_prompt": "당신은 친절한 MVNO 고객 상담 AI입니다.",
  "welcome_message": "안녕하세요, 무엇을 도와드릴까요?",
  "voice_id": "ko-KR-Standard-A",
  "voice_speed": 1.0,
  "language": "ko",
  "max_call_duration_seconds": 300
}
PUT /api/ai/tenants/{tenant_id}/config AI 설정 전체 업데이트

테넌트의 AI 설정 전체를 업데이트합니다.

권한: settings:write
Request Body
JSON
{
  "ai_provider": "openai",
  "model": "gpt-4o",
  "temperature": 0.7,
  "system_prompt": "당신은 친절한 MVNO 고객 상담 AI입니다.",
  "welcome_message": "안녕하세요, 무엇을 도와드릴까요?",
  "voice_id": "ko-KR-Standard-A",
  "voice_speed": 1.0,
  "language": "ko",
  "max_call_duration_seconds": 300
}
Response 200
JSON
{
  "ai_provider": "openai",
  "model": "gpt-4o",
  "temperature": 0.7,
  "system_prompt": "당신은 친절한 MVNO 고객 상담 AI입니다.",
  "welcome_message": "안녕하세요, 무엇을 도와드릴까요?",
  "voice_id": "ko-KR-Standard-A",
  "voice_speed": 1.0,
  "language": "ko",
  "max_call_duration_seconds": 300
}
PATCH /api/ai/tenants/{tenant_id}/config/prompts 시스템 프롬프트 업데이트

AI 시스템 프롬프트만 업데이트합니다.

권한: settings:write
Request Body
JSON
{
  "system_prompt": "당신은 친절하고 전문적인 MVNO 고객 상담 AI입니다."
}
Response 200
JSON
{
  "system_prompt": "당신은 친절하고 전문적인 MVNO 고객 상담 AI입니다."
}
PATCH /api/ai/tenants/{tenant_id}/config/voice 음성 설정 업데이트

AI 음성 ID 및 속도를 업데이트합니다.

권한: settings:write
Request Body
JSON
{
  "voice_id": "ko-KR-Wavenet-B",
  "voice_speed": 1.1
}
Response 200
JSON
{
  "voice_id": "ko-KR-Wavenet-B",
  "voice_speed": 1.1
}
PATCH /api/ai/tenants/{tenant_id}/config/welcome 환영 메시지 업데이트

AI 통화 시작 시 재생되는 환영 메시지를 업데이트합니다.

권한: settings:write
Request Body
JSON
{
  "welcome_message": "안녕하세요, ABC 텔레콤 AI 상담사입니다."
}
Response 200
JSON
{
  "welcome_message": "안녕하세요, ABC 텔레콤 AI 상담사입니다."
}

지식 베이스 (Knowledge Base)

GET /api/ai/tenants/{tenant_id}/knowledge 지식 목록 조회

AI가 참조하는 FAQ / 지식 베이스 항목 목록을 조회합니다.

권한: settings:read
Response 200
JSON
[
  {
    "id": "kb-001",
    "question": "요금제 변경 방법은 무엇인가요?",
    "answer": "고객센터 앱에서 요금제 메뉴를 통해 변경하실 수 있습니다.",
    "category": "billing",
    "is_active": true
  }
]
POST /api/ai/tenants/{tenant_id}/knowledge 지식 항목 추가

지식 베이스에 새 항목을 추가합니다.

권한: settings:write
Request Body
JSON
{
  "question": "유심 분실 시 어떻게 하나요?",
  "answer": "가까운 대리점을 방문하시거나 고객센터에 신청하세요.",
  "category": "usim",
  "is_active": true
}
필드타입필수설명
questionstring필수질문
answerstring필수답변
categorystring선택카테고리
is_activeboolean선택활성화 여부 (기본값: true)
Response 201
JSON
{
  "id": "kb-002",
  "question": "유심 분실 시 어떻게 하나요?",
  "answer": "가까운 대리점을 방문하시거나 고객센터에 신청하세요.",
  "category": "usim",
  "is_active": true
}
PUT /api/ai/tenants/{tenant_id}/knowledge/{kid} 지식 항목 수정

지식 베이스 항목을 전체 업데이트합니다.

권한: settings:write
Path Parameters
파라미터타입필수설명
tenant_idstring필수테넌트 ID
kidstring필수지식 항목 ID
Request Body
JSON
{
  "question": "유심 분실 또는 파손 시 어떻게 하나요?",
  "answer": "가까운 대리점을 방문하시거나 앱에서 신청하세요.",
  "category": "usim",
  "is_active": true
}
Response 200
JSON
{
  "id": "kb-002",
  "question": "유심 분실 또는 파손 시 어떻게 하나요?",
  "answer": "가까운 대리점을 방문하시거나 앱에서 신청하세요.",
  "category": "usim",
  "is_active": true
}
DELETE /api/ai/tenants/{tenant_id}/knowledge/{kid} 지식 항목 삭제

지식 베이스 항목을 삭제합니다.

권한: settings:write
Path Parameters
파라미터타입필수설명
tenant_idstring필수테넌트 ID
kidstring필수지식 항목 ID
Response 200
JSON
{
  "message": "지식 항목이 삭제되었습니다"
}

사용량 통계 (Usage)

GET /api/ai/tenants/{tenant_id}/usage 월별 사용량 요약

테넌트의 월별 AI 통화 사용량 요약을 조회합니다.

권한: dashboard:read
Query Parameters
파라미터타입필수설명
monthstring선택조회 월 (YYYY-MM, 기본값: 현재 월)
Response 200
JSON
{
  "month": "2026-03",
  "total_calls": 1243,
  "total_duration_seconds": 224940,
  "total_cost": 187.50,
  "successful_calls": 1180,
  "transferred_calls": 63
}
GET /api/ai/tenants/{tenant_id}/usage/daily 일별 사용량 조회

테넌트의 일별 AI 통화 사용량을 조회합니다.

권한: dashboard:read
Query Parameters
파라미터타입필수설명
monthstring선택조회 월 (YYYY-MM)
Response 200
JSON
[
  {
    "date": "2026-03-17",
    "calls": 42,
    "duration_seconds": 7560,
    "cost": 6.30
  }
]
GET /api/ai/tenants/{tenant_id}/usage/calls 통화별 비용 상세

개별 통화의 비용 상세 내역을 조회합니다.

권한: dashboard:read
Query Parameters
파라미터타입필수설명
datestring선택조회 날짜 (YYYY-MM-DD)
limitinteger선택조회 건수 (기본값: 20)
cursorstring선택페이지네이션 커서
Response 200
JSON
[
  {
    "call_id": "call-001",
    "date": "2026-03-17T09:30:00Z",
    "duration_seconds": 180,
    "cost": 0.15,
    "status": "completed"
  }
]

실시간 통화 (Active Calls)

GET /api/ai/tenants/{tenant_id}/calls/active 진행 중인 통화 조회

현재 진행 중인 AI 통화 목록을 실시간으로 조회합니다.

권한: cs:read
Response 200
JSON
[
  {
    "call_id": "call-live-001",
    "caller_phone": "010-1234-5678",
    "started_at": "2026-03-17T12:05:00Z",
    "duration_seconds": 45,
    "status": "in_progress"
  }
]