Server REST API

Authentication, endpoints, responses, and error codes for the REST API (v2) that lets your server read a chat room's state and send data to plugin channels, plus the older v1 method.

Last updated October 19, 2026

On this page

With the server REST API, your server can read a chat room's state (user count, user list, recent chats) and send data to plugin channels. This page is the authoritative reference for the request format, responses, and error codes. For a step-by-step walkthrough, see Sending notifications from your server to a chat room.

Setup: API key and chat room id

Find these two values in the API menu of the admin page.

Value Format Description
API chat room id room_ + 16 lowercase letters and digits Goes in the {id} slot of the URL. Unlike the chat room ID, it never changes and can be used in a URL as is
API key uchat_ + 32 lowercase letters and digits Shown only once when issued. If you lose it, roll that key or revoke it and issue a new one
  • Each key has a name and permissions. Read (read) is needed for GET endpoints, and Events (events) for sending events. You can change the permissions and name later; changed permissions apply from the next call.
  • Roll key changes only the key value and keeps the name, permissions, and usage history. The old value stops working immediately.
  • Each chat room can have up to 20 active keys.
  • Keep API keys only on your server. If you call the API from a browser, the key is exposed and anyone can send data to your chat room.
  • Calls are kept per key for 30 days in the usage and call log of the API menu (including the first 1KB of the request body and the IP). Do not send personal or payment information as-is.
  • With Try it in the API menu, you can run endpoints without a key and see real responses (these calls are not counted).

Request format

Item Value
URL https://api.uchat.io/v2/rooms/{id}/...
Authorization header Bearer {API key}
Body For POST, a JSON object (see Send events below)
Method Path Permission Plan Description
GET /v2/rooms/{id} Read Paid Chat room summary
GET /v2/rooms/{id}/stats Read Free User count
GET /v2/rooms/{id}/users Read Paid User list
GET /v2/rooms/{id}/messages Read Paid Recent chats
POST /v2/rooms/{id}/events Events Free Send events

Responses and limits

On success, the result is in data (events return HTTP 202).

{ "data": { "online": 15 } }

On failure, you get an HTTP status and error. See Error codes for the full list.

{ "error": { "code": "invalid_key", "message": "This API key is not valid for this room." } }
Plan Per minute Per day (UTC)
Free chat room 60 calls 1,000 calls
Paid chat room 600 calls Unlimited
  • Going over returns HTTP 429 (rate_limited, daily_limit). For the per-minute limit, the Retry-After header tells you how many seconds to wait.
  • The daily count includes only calls with a valid key. Requests with a wrong key have their own per-minute limit, so someone else's bad requests cannot use up your limit.

Chat room summary

GET /v2/rooms/{id} (paid)

curl https://api.uchat.io/v2/rooms/room_xxxxxxxxxxxxxxxx \
  -H "Authorization: Bearer uchat_..."
{
	"data": {
		"id": "room_xxxxxxxxxxxxxxxx",
		"room_id": "my-room",
		"name": "My chat room",
		"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 }
	}
}

User count

GET /v2/rooms/{id}/stats (free)

{
	"data": {
		"online": 15,
		"roles": { "guest": 3, "member": 10, "subadmin": 1, "admin": 1 },
		"devices": { "pc": 9, "mobile": 6 }
	}
}

Even when no one is connected, you get all zeros instead of an error.

User list

GET /v2/rooms/{id}/users (paid)

{
	"data": [
		{
			"nick": "Minji",
			"user_id": "minji",
			"role": "member",
			"level": 3,
			"device": "mobile",
			"connected_at": "2026-10-19T03:12:45.000Z"
		}
	]
}
  • role is guest, member, subadmin, or admin. user_id is set only for people who joined through member integration; it is null for everyone else.
  • IPs, sessions, and hidden connections are not included.

Recent chats

GET /v2/rooms/{id}/messages?limit=50&before={message id} (paid)

{
	"data": [
		{
			"id": "bfd6a342c0f549beb12f4a1c4e05831c",
			"type": "message",
			"nick": "Minji",
			"user_id": null,
			"role": "guest",
			"text": "Hello",
			"created_at": "2026-10-19T03:15:02.000Z"
		}
	]
}
Value Description
limit 1–100, default 50. Newest first
before Starts from messages older than this message id. To get the next page, pass the id of the last message
type message (chat) or notice (notice)
id Same value as the event id in webhook notifications (32 hex characters)
  • Only chats and notices visible to everyone are included. Whispers, deleted chats, and chats hidden by AI are left out.
  • The chat server saves in batches, so a chat sent just now may show up a few seconds late.

Send events

POST /v2/rooms/{id}/events (free)

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 } }
Key Description
plugin Name of the receiving channel (1–64 English letters, digits, _, -)
data Array of values (20 slots, up to 2KB in total). Use only strings, numbers, and booleans; the receiving side gets them all as strings. Control characters such as line breaks are not allowed
to (Optional) A nickname. Sends only to that person
save (Optional) If true, saves it as the channel's last value and also sends it to people who join later. Saving an empty data deletes it
  • The receiving side is room.plugin.add('{plugin}').onReceived. data.user.auth is 4 and the nickname is empty. data.type is 0 for everyone and 1 for one person or a saved value.
  • It succeeds even when no one is connected (there is just no one to receive it). With save, the value is still saved, and the next person who joins receives it.
  • save has the same limits as channel save. A free chat room can save one channel up to 1KB; a paid chat room can save 4KB per channel and 60KB in total. In a free chat room, saving a different channel deletes the previous one. Saved values remain even when the chat room empties or the server restarts.
  • save and to cannot be used together.
  • Free chat rooms share the same one-minute limit with channel sends from page scripts. Going over returns chat_rate_limited (429). Channel API and limits
  • Among uchat plugins, Event alert box, Donation goal bar, Live status, Scoreboard, Countdown, and Ranking display values sent with this API. The format to send is in each plugin's guide.

Receiving code:

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; // only data sent by the server
		if (data.data[0] === 'paid') room.print('Payment complete: ' + data.data[1]);
	});
});

Error codes

HTTP code Meaning
400 invalid_limit, invalid_before A messages value has the wrong format
400 invalid_json, invalid_body The body is not a JSON object
400 invalid_plugin, invalid_to, invalid_save A plugin, to, or save value has the wrong format
400 invalid_data, data_too_large data is not an array, or its value types, control characters, slot count, or size are invalid
400 save_with_to save and to were used together
400 state_too_large The save limit was exceeded
401 missing_key No Authorization: Bearer header
401 invalid_key Not a key for this chat room, or a revoked key
403 insufficient_scope The key lacks the permission (Read or Events) for this endpoint
403 paid_plan_required Endpoint for paid chat rooms only
404 room_not_found The API chat room id does not exist
404 target_not_found The to nickname is not in the chat room
429 rate_limited, daily_limit Per-minute or daily call limit exceeded
429 chat_rate_limited Free chat room channel send limit exceeded
503 chat_server_unavailable The chat server did not respond. Try again shortly

Older method (v1)

v1 still works for integrations built earlier. Use v2 for anything new. v1 authenticates with the same API keys (old API tokens have been moved to the API menu as "v1 key") and its calls are also recorded in the call log.

Item Value
URL https://api.uchat.io/rooms/{chat room ID}/stats, .../plugin/{channel}, .../plugin/{channel}/{nickname}
User-Agent header Exactly uchat_api_client_v1 (otherwise HTTP 404 {"status":"fail","msg":"unknown_api_version"})
X-UCHAT-API-TOKEN header API key
X-UCHAT-API-ROOM header Chat room ID. Only when the URL does not include /rooms/{chat room ID}
Body For POST, a JSON array
  • Success is HTTP 200 {"success":true,"status":"success","data":...}; failure is always HTTP 500 with error_code.
  • stats returns all zeros when no one is connected, and channel sends succeed even when no one is connected (sending to one person returns 404).
  • There is no save.
error_code Meaning
1 The key does not match or was revoked, or the chat room does not exist
2 No chat room ID
4, 5 Unknown path, unsupported method
6 X-UCHAT-API-TOKEN header is missing
7, 8, 10 No channel name, empty body, body is not an array
11 The key lacks the permission for this API (Read for stats, Events for plugin)
101 Communication format error with the chat server
404 The target nickname is not in the chat room
428 Free chat room channel send limit exceeded
0 Other errors

Still not sure how it works? Ask your question on the contact board.

Business name UCHAT · CEO 김경욱 · Business registration no. 141-05-32832
Address 경기도 파주시 와석순환로 61 · Mail-order business registration no. 2013-경기파주-4485호
Phone 010-8677-8633 · Email support@uchat.io

ⓒ 2013–2026 UCHAT. All rights reserved.