Public Users API
Read-only JSON endpoints for looking up TetroWars player profiles and recent activity.
- Base URL:
https://tetrowars.com/api/v1 - Format: JSON (UTF-8)
- Auth: None required
- CORS:
Access-Control-Allow-Origin: *(cross-origin friendly) - Rate Limit: 30 requests/minute per IP for
/users/search, 60/minute for/users/{id}
For browsing ranked lists, see Public Leaderboard API. Every leaderboard row already contains a user_id, so you can skip the search step when drilling into a player.
All responses follow the shape:
{ "ok": true, "data": { ... } }
or on error:
{ "ok": false, "error": "message" }
GET /users/search
Find users by partial username or display name.
Query Parameters
| Param | Type | Default | Notes |
|---|---|---|---|
q |
string | — | Required, min 2 chars |
limit |
int | 10 |
Max 50 |
Example
curl "https://tetrowars.com/api/v1/users/search?q=nar&limit=3"
Response
{
"ok": true,
"data": {
"rows": [
{
"id": 220,
"username": "naraa0327_",
"display_name": "naraa0327_",
"glicko_rating": 1030,
"elo_combined": 1041,
"level": 27,
"xp": 63156,
"avatar_url": null,
"games_played": 71,
"games_won": 49,
"highest_score": 668862,
"sprint_best_ms": 20654
}
],
"count": 1,
"query": "nar"
}
}
Results exclude bots and inactive accounts. Exact matches rank first, then by Glicko rating, then by games played.
GET /users/{id}
Full profile for one user plus their 10 most recent games. Use this when you already have a user_id (e.g. from the leaderboard endpoint).
GET /users/{id}/stats is an alias for the same endpoint and returns identical data.
Example
curl "https://tetrowars.com/api/v1/users/220"
Response
{
"ok": true,
"data": {
"id": 220,
"username": "naraa0327_",
"display_name": "naraa0327_",
"glicko_rating": 1030,
"games_played": 71,
"games_won": 49,
"win_rate": 69.0,
"total_score": 3883370,
"total_lines": 2221,
"highest_score": 668862,
"highest_level": 21,
"created_at": "2026-04-07 08:06:19",
"recent_games": [
{
"game_id": 272394,
"score": 32104,
"level": 4,
"lines_cleared": 39,
"duration": 32263,
"mode": "multiplayer",
"game_mode": "marathon",
"room_mode": "1v1",
"winner_user_id": 220,
"placement": 1,
"has_replay": 1
}
]
}
}
Errors
| HTTP | Meaning |
|---|---|
| 400 | Bad request (e.g. q too short) |
| 404 | User not found (inactive or doesn't exist) |
| 429 | Rate limit exceeded - slow down |
| 500 | Server error - report via Discord |
Typical Flows
Coming from the leaderboard (preferred, one less request):
- Call
GET /leaderboard?tab=ranked. - Pick a row, read its
user_id. - Call
GET /users/{user_id}for full stats.
Searching by name:
- User types a name in your UI.
- Call
GET /users/search?q=nameto resolve them to anid. - Call
GET /users/{id}for full stats.
Questions or found a bug? Ping us on Discord in #dev.