서버 REST API
내 서버에서 채팅방 상태를 읽고 플러그인 채널로 데이터를 보내는 REST API(v2)의 인증, 엔드포인트, 응답, 오류 코드와 예전 v1 방식이에요.
마지막 수정 2026년 10월 19일
서버 REST API로 내 서버에서 채팅방 상태(접속자 수·접속자 목록·최근 채팅)를 읽고, 플러그인 채널로 데이터를 보내요. 이 문서는 요청 형식·응답·오류 코드의 정본이에요. 따라 하며 써 보려면 서버에서 채팅방으로 알림 보내기를 보세요.
준비: API 키와 채팅방 아이디
관리 페이지의 API 메뉴에서 두 값을 확인해요.
| 값 | 모양 | 설명 |
|---|---|---|
| API 채팅방 아이디 | room_ + 소문자·숫자 16자 |
주소의 {id} 자리에 넣어요. 채팅방 아이디와 달리 바뀌지 않고 주소에 그대로 쓸 수 있어요 |
| API 키 | uchat_ + 소문자·숫자 32자 |
발급할 때 한 번만 보여요. 잃어버리면 그 키를 다시 발급하거나 폐기하고 새로 발급해요 |
- 키마다 이름과 권한을 정해요. 조회(
read)는 GET 엔드포인트, 이벤트(events)는 이벤트 보내기에 필요해요. 권한과 이름은 나중에 바꿀 수 있고, 바꾼 권한은 다음 호출부터 적용돼요. - 값 다시 발급은 이름·권한·사용 기록을 그대로 두고 키 값만 바꿔요. 옛 값은 바로 쓸 수 없어요.
- 채팅방마다 쓰는 중인 키는 20개까지예요.
- API 키는 서버에만 두세요. 브라우저에서 부르면 키가 드러나 누구나 채팅방에 데이터를 보낼 수 있게 돼요.
- 호출은 키마다 API 메뉴의 사용량·호출 기록에 30일 동안 남아요(요청 본문 앞 1KB와 IP 포함). 개인정보·결제정보를 그대로 보내지 마세요.
- API 메뉴의 시험하기에서 키 없이 엔드포인트를 실행해 실제 응답을 볼 수 있어요(호출 횟수에는 세지 않아요).
요청 형식
| 항목 | 값 |
|---|---|
| 주소 | https://api.uchat.io/v2/rooms/{id}/... |
Authorization 헤더 |
Bearer {API 키} |
| 본문 | POST는 JSON 객체(아래 이벤트 보내기) |
| 메서드 | 경로 | 권한 | 요금제 | 설명 |
|---|---|---|---|---|
GET |
/v2/rooms/{id} |
조회 | 유료 | 채팅방 요약 |
GET |
/v2/rooms/{id}/stats |
조회 | 무료 | 접속자 수 |
GET |
/v2/rooms/{id}/users |
조회 | 유료 | 접속자 목록 |
GET |
/v2/rooms/{id}/messages |
조회 | 유료 | 최근 채팅 |
POST |
/v2/rooms/{id}/events |
이벤트 | 무료 | 이벤트 보내기 |
응답과 한도
성공하면 data에 결과가 담겨요(이벤트는 HTTP 202).
{ "data": { "online": 15 } }
실패하면 HTTP 상태와 error가 와요. 전체 목록은 오류 코드예요.
{ "error": { "code": "invalid_key", "message": "This API key is not valid for this room." } }
| 요금제 | 분당 | 하루(UTC) |
|---|---|---|
| 무료 채팅방 | 60회 | 1,000회 |
| 유료 채팅방 | 600회 | 제한 없음 |
- 넘으면 HTTP 429(
rate_limited,daily_limit)예요. 분당 한도는Retry-After헤더에 기다릴 초를 알려 줘요. - 하루 횟수는 키가 맞은 호출만 세요. 키가 틀린 요청은 따로 분당 한도가 있어서, 남의 잘못된 요청이 내 한도를 쓰지 못해요.
채팅방 요약
GET /v2/rooms/{id} (유료)
curl https://api.uchat.io/v2/rooms/room_xxxxxxxxxxxxxxxx \
-H "Authorization: Bearer uchat_..."
{
"data": {
"id": "room_xxxxxxxxxxxxxxxx",
"room_id": "my-room",
"name": "내 채팅방",
"channel": false,
"plan": "paid",
"paid": true,
"created_at": "2026-10-11T01:59:53.000Z",
"online": 15,
"settings": { "frozen": false, "join_password": false, "chat_length_limit": 100 }
}
}
접속자 수
GET /v2/rooms/{id}/stats (무료)
{
"data": {
"online": 15,
"roles": { "guest": 3, "member": 10, "subadmin": 1, "admin": 1 },
"devices": { "pc": 9, "mobile": 6 }
}
}
접속자가 없어도 오류 없이 모두 0이에요.
접속자 목록
GET /v2/rooms/{id}/users (유료)
{
"data": [
{
"nick": "민지",
"user_id": "minji",
"role": "member",
"level": 3,
"device": "mobile",
"connected_at": "2026-10-19T03:12:45.000Z"
}
]
}
role은guest·member·subadmin·admin이에요.user_id는 회원 연동으로 들어온 사람만 있고 나머지는null이에요.- IP·세션과 숨은 접속은 주지 않아요.
최근 채팅
GET /v2/rooms/{id}/messages?limit=50&before={메시지 id} (유료)
{
"data": [
{
"id": "bfd6a342c0f549beb12f4a1c4e05831c",
"type": "message",
"nick": "민지",
"user_id": null,
"role": "guest",
"text": "안녕하세요",
"created_at": "2026-10-19T03:15:02.000Z"
}
]
}
| 값 | 설명 |
|---|---|
limit |
1~100, 기본 50. 새것부터 와요 |
before |
이 메시지 id보다 오래된 것부터. 다음 쪽을 볼 때 마지막 메시지의 id를 넣어요 |
type |
message(채팅) 또는 notice(공지) |
id |
웹훅 알림의 이벤트 id와 같은 값(32자 16진수) |
- 모두에게 보인 채팅과 공지만 와요. 귓속말, 지운 채팅, AI가 가린 채팅은 빠져요.
- 채팅 서버가 묶어서 저장하므로 방금 한 채팅은 몇 초 늦게 보일 수 있어요.
이벤트 보내기
POST /v2/rooms/{id}/events (무료)
curl -X POST https://api.uchat.io/v2/rooms/room_xxxxxxxxxxxxxxxx/events \
-H "Authorization: Bearer uchat_..." \
-H "Content-Type: application/json" \
-d '{"plugin":"payment","data":["paid","order-1001",15000]}'
{ "data": { "sent": true } }
| 키 | 설명 |
|---|---|
plugin |
받을 채널 이름(영문·숫자·_·- 1~64자) |
data |
값 배열(20칸, 합쳐서 2KB까지). 문자열·숫자·불리언만 쓰고, 받는 쪽에는 모두 문자열로 가요. 줄바꿈 같은 제어 문자는 넣을 수 없어요 |
to |
(선택) 닉네임. 그 사람에게만 보내요 |
save |
(선택) true면 그 채널의 마지막 값으로 저장해 나중에 들어오는 사람에게도 보내요. 빈 data를 저장하면 지워요 |
- 받는 쪽은
room.plugin.add('{plugin}').onReceived예요.data.user.auth가4이고 닉네임은 비어 있어요.data.type은 모두에게0, 한 사람에게·저장값은1이에요. - 접속자가 없어도 성공이에요(받을 사람이 없을 뿐이에요).
save는 이때도 저장돼서 다음에 들어온 사람이 받아요. save의 한도는 채널 저장과 같아요. 무료 채팅방은 채널 하나·1KB, 유료 채팅방은 채널마다 4KB·합쳐서 60KB예요. 무료 채팅방에서 다른 채널을 저장하면 앞의 채널은 지워져요. 저장값은 채팅방이 비거나 서버가 다시 시작돼도 남아요.save와to는 함께 쓸 수 없어요.- 무료 채팅방은 페이지 스크립트의 전송과 같은 1분 한도를 나눠 써요. 넘으면
chat_rate_limited(429)예요. 채널 API와 한도 - 유챗 플러그인 중 이벤트 알림창·후원 목표 막대·방송 상태·점수판·카운트다운·순위표는 이 API로 보낸 값을 그려요. 보내는 형식은 각 플러그인 안내에 있어요.
받는 쪽 코드:
U.chat('*').on('after.create#payment', function (room) {
if (room.id !== 'my-room') return;
room.plugin.add('payment').onReceived(function (room, data) {
if (!data.user || data.user.auth !== 4) return; // 서버가 보낸 것만
if (data.data[0] === 'paid') room.print('결제가 완료되었습니다: ' + data.data[1]);
});
});
오류 코드
| HTTP | code |
뜻 |
|---|---|---|
| 400 | invalid_limit, invalid_before |
messages의 값이 형식에 맞지 않음 |
| 400 | invalid_json, invalid_body |
본문이 JSON 객체가 아님 |
| 400 | invalid_plugin, invalid_to, invalid_save |
plugin·to·save 값이 형식에 맞지 않음 |
| 400 | invalid_data, data_too_large |
data가 배열이 아니거나, 값 종류·제어 문자·칸 수·크기가 맞지 않음 |
| 400 | save_with_to |
save와 to를 함께 씀 |
| 400 | state_too_large |
저장 한도를 넘음 |
| 401 | missing_key |
Authorization: Bearer 헤더가 없음 |
| 401 | invalid_key |
이 채팅방의 키가 아니거나 폐기한 키 |
| 403 | insufficient_scope |
키에 이 엔드포인트의 권한(조회·이벤트)이 없음 |
| 403 | paid_plan_required |
유료 채팅방 전용 엔드포인트 |
| 404 | room_not_found |
API 채팅방 아이디가 없음 |
| 404 | target_not_found |
to의 닉네임이 채팅방에 없음 |
| 429 | rate_limited, daily_limit |
분당·하루 호출 한도 초과 |
| 429 | chat_rate_limited |
무료 채팅방 채널 전송 한도 초과 |
| 503 | chat_server_unavailable |
채팅 서버가 답하지 않음. 잠시 뒤 다시 해 보세요 |
예전 방식(v1)
예전에 만든 연동을 위해 v1도 그대로 동작해요. 새로 만들 때는 v2를 쓰세요. v1은 같은 API 키로 인증하고(예전 API 토큰은 API 메뉴에 "v1 키"로 옮겨져 있어요), 호출 기록에도 남아요.
| 항목 | 값 |
|---|---|
| 주소 | https://api.uchat.io/rooms/{채팅방 아이디}/stats, .../plugin/{채널}, .../plugin/{채널}/{닉네임} |
User-Agent 헤더 |
정확히 uchat_api_client_v1(아니면 HTTP 404 {"status":"fail","msg":"unknown_api_version"}) |
X-UCHAT-API-TOKEN 헤더 |
API 키 |
X-UCHAT-API-ROOM 헤더 |
채팅방 아이디. 주소에 /rooms/{채팅방 아이디}를 넣지 않을 때만 |
| 본문 | POST는 JSON 배열 |
- 성공은 HTTP 200
{"success":true,"status":"success","data":...}, 실패는 언제나 HTTP 500과error_code예요. stats는 접속자가 없으면 모두 0이고, 채널 전송은 접속자가 없어도 성공이에요(한 사람에게 보내면 404).save는 없어요.
error_code |
뜻 |
|---|---|
1 |
키가 맞지 않거나 폐기한 키, 또는 없는 채팅방 |
2 |
채팅방 아이디가 없음 |
4, 5 |
없는 경로, 지원하지 않는 메서드 |
6 |
X-UCHAT-API-TOKEN 헤더가 없음 |
7, 8, 10 |
채널 이름이 없음, 본문이 비어 있음, 본문이 배열이 아님 |
11 |
키에 이 API의 권한이 없음(stats는 조회, plugin은 이벤트) |
101 |
채팅 서버와의 통신 형식 오류 |
404 |
대상 닉네임이 채팅방에 없음 |
428 |
무료 채팅방 채널 전송 한도 초과 |
0 |
그 밖의 오류 |
봐도 잘 이해가 되지 않나요? 문의 게시판에 질문을 남겨 주세요.