이 API는 Client SDK 키(osk_ 접두사)로 인증합니다.
REST API 채팅(OpenAI 호환)과는 별도의 엔드포인트입니다.
메시지 전송
POST /v1/chat/{persona_id}
페르소나에게 메시지를 전송합니다. thread_id를 생략하면 새 스레드가 생성되고, 포함하면 기존 스레드를 이어갑니다.
사용 가능한 모델은 GET /v1/models로 조회할 수 있습니다.
요청 — 새 스레드
{
"model": "12d10e3e-9ce7-47f9-9f84-45d22ebb496a",
"messages": [
{
"role": "user",
"content": "오늘 저녁은 뭐 먹으면 좋을까?"
}
]
}
요청 — 기존 스레드 이어가기
{
"thread_id": "thr_a1b2c3d4e5f6",
"messages": [
{
"role": "user",
"content": "카레 재료 알려줘"
}
]
}
| 필드 | 타입 | 필수 | 설명 |
|---|
model | string | 새 스레드 시 필수 | 모델 ID (GET /v1/models의 id 값) |
thread_id | string | X | 기존 스레드 ID (생략 시 새 스레드 생성) |
messages | array | O | 메시지 배열 |
messages[].role | string | O | user |
messages[].content | string | O | 메시지 내용 |
stream | boolean | X | 스트리밍 여부 (기본: false) |
새 스레드 생성 시 지정한 모델이 해당 스레드에 고정됩니다. 이후 대화에서는 model 필드를 생략해도 동일한 모델이 사용됩니다.
{
"success": true,
"data": {
"thread_id": "thr_a1b2c3d4e5f6",
"is_new_thread": true,
"user_message": {
"message_id": "msg_u1v2w3x4y5z6",
"role": "user",
"content": "오늘 저녁은 뭐 먹으면 좋을까?",
"created_at": "2026-04-16T10:00:00Z"
},
"assistant_message": {
"message_id": "msg_a7b8c9d0e1f2",
"role": "assistant",
"blocks": [
{
"type": "text",
"content": "비가 오는 날엔 따뜻한 소고기 카레는 어떠세요?"
},
{
"type": "product_list",
"title": "매콤 소고기 카레 재료",
"badge": "AI 추천",
"items": [
{ "id": "p_001", "name": "한우 등심 (300g)", "section": "정육 코너", "price": 24500 },
{ "id": "p_002", "name": "유기농 감자/당근 세트", "section": "신선 채소", "price": 4800 }
],
"actions": [
{ "id": "view_recipe", "label": "자세한 내용 보기", "style": "primary" },
{ "id": "show_alternates", "label": "다른 추천 보기", "style": "secondary" }
]
},
{
"type": "suggestion",
"content": "카레와 함께 곁들일 레드 와인도 추천해 드릴까요?",
"actions": [
{ "id": "wine_yes", "label": "추천받기", "style": "primary" },
{ "id": "wine_no", "label": "괜찮아요", "style": "secondary" }
]
}
],
"created_at": "2026-04-16T10:00:01Z"
},
"credits": {
"used": 289,
"balance": 149.50
}
}
}
블록 타입
assistant 응답은 구조화된 blocks 배열로 반환됩니다.
| 타입 | 설명 | 주요 필드 |
|---|
text | 텍스트 메시지 | content |
image | 이미지 | url |
product_list | 상품 목록 | title, items[], actions[] |
suggestion | AI 추천/제안 | content, actions[] |
블록에 포함된 actions는 클라이언트에서 사용자 인터랙션을 처리하기 위한 정보입니다.
| 필드 | 설명 |
|---|
id | 액션 식별자 |
label | 버튼 텍스트 |
style | primary / secondary / text |
스레드 조회
GET /v1/chat/{persona_id}/threads/{thread_id}
스레드의 메타 정보를 조회합니다 (메시지 본문은 미포함).
{
"success": true,
"data": {
"thread_id": "thr_a1b2c3d4e5f6",
"title": "오늘 저녁 메뉴 추천",
"status": "ACTIVE",
"message_count": 4,
"started_at": "2026-04-16T10:00:00Z",
"last_active_at": "2026-04-16T10:30:00Z"
}
}
스레드 종료
POST /v1/chat/{persona_id}/threads/{thread_id}/close
스레드를 종료합니다. 페르소나 상태가 CHAT → READY로 전환됩니다.
{
"success": true,
"data": {
"thread_id": "thr_a1b2c3d4e5f6",
"thread_status": "CLOSED",
"persona_status": "READY",
"closed_at": "2026-04-16T10:35:00Z"
}
}
이미 종료된 스레드에 요청하면 409 Conflict가 반환됩니다:
{
"success": false,
"error": {
"code": "ALREADY_CLOSED",
"message": "thread is already closed"
}
}
메시지 목록 조회
GET /v1/chat/{persona_id}/threads/{thread_id}/messages
스레드의 메시지 목록을 조회합니다 (오래된 순). 커서 기반 페이지네이션을 지원합니다.
쿼리 파라미터
| 파라미터 | 타입 | 기본값 | 설명 |
|---|
limit | integer | 50 | 반환할 메시지 수 (최대 100) |
before | string | - | 이 message_id 이전 메시지 로드 (역방향 페이징) |
{
"success": true,
"data": {
"thread_id": "thr_a1b2c3d4e5f6",
"messages": [
{
"message_id": "msg_u1v2w3x4y5z6",
"role": "user",
"content": "오늘 저녁은 뭐 먹으면 좋을까?",
"created_at": "2026-04-16T10:00:00Z"
},
{
"message_id": "msg_a7b8c9d0e1f2",
"role": "assistant",
"blocks": [
{ "type": "text", "content": "소고기 카레는 어떠세요?" }
],
"created_at": "2026-04-16T10:00:01Z"
}
],
"has_more": false,
"next_before": null
}
}
has_more가 true이면 next_before 값을 before 파라미터로 전달하여 다음 페이지를 로드합니다.
전체 흐름 예제
# 1. 페르소나 생성
PERSONA_ID=$(curl -s -X POST https://api.ones1ght.com/v1/persona \
-H "Authorization: Bearer $SDK_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "홍길동", "locale": "ko"}' | jq -r '.data.persona_id')
# 2. 모델 목록 조회 → 첫 번째 모델 ID 사용
MODEL_ID=$(curl -s https://api.ones1ght.com/v1/models \
-H "Authorization: Bearer $SDK_KEY" | jq -r '.data[0].id')
# 3. 채팅 시작 (새 스레드 — model 필수)
THREAD_ID=$(curl -s -X POST https://api.ones1ght.com/v1/chat/$PERSONA_ID \
-H "Authorization: Bearer $SDK_KEY" \
-H "Content-Type: application/json" \
-d "{\"model\": \"$MODEL_ID\", \"messages\": [{\"role\": \"user\", \"content\": \"오늘 저녁 뭐 먹을까?\"}]}" | jq -r '.data.thread_id')
# 4. 대화 이어가기 (model 생략 — 스레드에 고정됨)
curl -X POST https://api.ones1ght.com/v1/chat/$PERSONA_ID \
-H "Authorization: Bearer $SDK_KEY" \
-H "Content-Type: application/json" \
-d "{\"thread_id\": \"$THREAD_ID\", \"messages\": [{\"role\": \"user\", \"content\": \"카레 재료 알려줘\"}]}"
# 5. 메시지 이력 조회
curl https://api.ones1ght.com/v1/chat/$PERSONA_ID/threads/$THREAD_ID/messages \
-H "Authorization: Bearer $SDK_KEY"
# 6. 스레드 종료
curl -X POST https://api.ones1ght.com/v1/chat/$PERSONA_ID/threads/$THREAD_ID/close \
-H "Authorization: Bearer $SDK_KEY"