Chessmail REST API v3
The Chessmail API v3 provides programmatic access to user profiles and correspondence chess games.
Authentication
All API requests require authentication via the X-Client-Id header.
X-Client-Id: your-client-id
To obtain a client ID, please contact the chessmail administrators via contact@chessmail.info.
Also, contact us if you need other or more types of calls to the API for your projects.
Rate Limiting
API requests are rate-limited per client:
- Maximum requests per minute (60 for now, could be changed in the future)
- Maximum requests per hour (300 for now, could be changed in the future)
When the rate limit is exceeded, the API returns HTTP status 509 Bandwidth Limit Exceeded.
Base URL
https://www.chessmail.de/api/v3
Endpoints
Users
Get User Profile
Returns public profile information for a user.
GET /api/v3/users/{username}
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
| username | string | The username of the user (case-insensitive) |
Response:
{
"username": "player1",
"rating": 1650,
"ratingLive": 1580,
"rank": 5,
"created": "2020-05-10T00:00:00Z",
"statement": "Chess is life!",
"club": "Chess Masters",
"supporting": true
}
Response Fields:
| Field | Type | Description |
|---|---|---|
| username | string | The user's username |
| rating | integer | Correspondence chess ELO rating (null for newbies) |
| ratingLive | integer | Live chess ELO rating (null for newbies) |
| rank | integer | User's rank (1-15) |
| created | string | Account creation date (ISO 8601) |
| statement | string | User's public statement |
| club | string | Name of the user's chess club (if member) |
| supporting | boolean | Whether the user is a supporting member |
Get User Games
Returns games for a user with pagination.
GET /api/v3/users/{username}/games
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
| username | string | The username of the user (case-insensitive) |
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
| sort | string | lastMoveDate | Sort field: lastMoveDate, created, opponent, timeControl, gameType |
| order | string | desc | Sort order: asc, desc |
| status | string | running | Filter by status: running, finished |
| page | integer | 0 | Page number (0-based) |
| size | integer | 20 | Page size (max: 100) |
Response:
{
"content": [
{
"id": "abc123",
"gameType": "TOURNAMENT",
"rated": true,
"timeControl": "T1_5",
"result": null,
"startTime": "2024-01-15T10:30:00Z",
"playerWhite": "player1",
"playerBlack": "player2",
"ratingWhiteStart": 1650,
"ratingBlackStart": 1580,
"ratingWhiteEnd": null,
"ratingBlackEnd": null,
"plyCount": 24,
"status": "RUNNING",
"lastMoveDate": "2024-01-16T14:20:00Z"
}
],
"page": 0,
"size": 20,
"totalElements": 150,
"totalPages": 8
}
Games
Get Started Games of Users
Returns recently started (running) games for the specified users.
GET /api/v3/games/started
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| usernames | string | Yes | Comma-separated list of usernames |
| since-hours | integer | Yes | Number of hours to look back (1-48) |
Response:
[
{
"id": "abc123",
"playerWhite": "player1",
"playerBlack": "player2",
"startTime": "2024-01-15T10:30:00Z"
}
]
Response Fields:
| Field | Type | Description |
|---|---|---|
| id | string | Unique game identifier (game key) |
| playerWhite | string | Username of the white player |
| playerBlack | string | Username of the black player |
| startTime | string | Game start date (ISO 8601) |
Get Finished Games of Users
Returns recently finished games for the specified users.
GET /api/v3/games/finished
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| usernames | string | Yes | Comma-separated list of usernames |
| since-hours | integer | Yes | Number of hours to look back (1-48) |
Response:
[
{
"id": "abc123",
"playerWhite": "player1",
"playerBlack": "player2",
"startTime": "2024-01-15T10:30:00Z",
"finishedTime": "2024-02-20T18:45:00Z",
"result": "1-0"
}
]
Response Fields:
| Field | Type | Description |
|---|---|---|
| id | string | Unique game identifier (game key) |
| playerWhite | string | Username of the white player |
| playerBlack | string | Username of the black player |
| startTime | string | Game start date (ISO 8601) |
| finishedTime | string | Game end date (ISO 8601) |
| result | string | Game result: 1-0 (white wins), 0-1 (black wins), ½-½ (draw), --- (aborted) |
Get Game by ID
Returns a specific game by its ID.
GET /api/v3/games/{id}
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
| id | string | The game ID (game key) |
Response:
{
"id": "abc123",
"gameType": "TOURNAMENT",
"rated": true,
"timeControl": "T1_5",
"result": "1-0",
"startTime": "2024-01-15T10:30:00Z",
"playerWhite": "player1",
"playerBlack": "player2",
"ratingWhiteStart": 1650,
"ratingBlackStart": 1580,
"ratingWhiteEnd": 1662,
"ratingBlackEnd": 1568,
"plyCount": 78,
"status": "FINISHED",
"lastMoveDate": "2024-02-20T18:45:00Z"
}
Response Fields:
| Field | Type | Description |
|---|---|---|
| id | string | Unique game identifier |
| gameType | string | Type of game (see Game Types below) |
| rated | boolean | Whether the game affects player ratings |
| timeControl | string | Time control setting (see Time Controls below) |
| result | string | Game result: 1-0 (white wins), 0-1 (black wins), ½-½ (draw), --- (aborted), or null for running games |
| startTime | string | Game start date (ISO 8601) |
| playerWhite | string | Username of the white player |
| playerBlack | string | Username of the black player |
| ratingWhiteStart | integer | White player's rating at game start (null if not available) |
| ratingBlackStart | integer | Black player's rating at game start (null if not available) |
| ratingWhiteEnd | integer | White player's rating after game ended (null for running games) |
| ratingBlackEnd | integer | Black player's rating after game ended (null for running games) |
| plyCount | integer | Number of half-moves (plies) played in the game |
| status | string | RUNNING or FINISHED |
| lastMoveDate | string | Date of the last move (ISO 8601) |
Reference
Game Types
The gameType field indicates the category of the game, while the rated field indicates whether the game affects player ratings.
| Value | Description |
|---|---|
| NORMAL | Standard game between players |
| TOURNAMENT | Club tournament game |
| MANUAL_TOURNAMENT | Manual tournament game |
| TEAM_COMPETITION | Team competition game |
| ENGINE | Game against chess engine |
| TRANSIENT | Temporary/transient game |
Time Controls
| Value | Description |
|---|---|
| T1_30 | 30 days per move |
| T1_7 | 7 days per move |
| T1_5 | 5 days per move |
| T1_3 | 3 days per move |
| T1_2 | 2 days per move |
| T1_1 | 1 day per move |
| INF | Unlimited time |
Error Responses
401 Unauthorized
Returned when the X-Client-Id header is missing or invalid.
{
"error": "UnauthorizedException",
"message": "X-Client-Id header is required",
"code": 401,
"key": "error-12345"
}
404 Not Found
Returned when a requested resource (user or game) does not exist.
{
"error": "DataNotFoundException",
"message": "User not found: unknown_user",
"code": 404,
"key": "error-12346"
}
509 Bandwidth Limit Exceeded
Returned when the rate limit is exceeded.
{
"error": "RateLimitExceededException",
"message": "API calls limit exceeded (60 calls per minute allowed)",
"code": 509,
"key": "error-12347"
}
Examples
cURL
# Get user profile
curl -H "X-Client-Id: your-client-id" \
https://www.chessmail.de/api/v3/users/player1
# Get user's running games, sorted by last move date
curl -H "X-Client-Id: your-client-id" \
"https://www.chessmail.de/api/v3/users/player1/games?status=running&sort=lastMoveDate&order=desc"
# Get second page of running games
curl -H "X-Client-Id: your-client-id" \
"https://www.chessmail.de/api/v3/users/player1/games?page=1&size=50"
# Get a specific game
curl -H "X-Client-Id: your-client-id" \
https://www.chessmail.de/api/v3/games/abc123
# Get games started in the last 24 hours for multiple users
curl -H "X-Client-Id: your-client-id" \
"https://www.chessmail.de/api/v3/games/started?usernames=player1,player2,player3&since-hours=24"
# Get games finished in the last 48 hours for multiple users
curl -H "X-Client-Id: your-client-id" \
"https://www.chessmail.de/api/v3/games/finished?usernames=player1,player2&since-hours=48"
JavaScript (Fetch API)
const clientId = 'your-client-id';
const baseUrl = 'https://www.chessmail.de/api/v3';
// Get user profile
async function getUser(username) {
const response = await fetch(`${baseUrl}/users/${username}`, {
headers: { 'X-Client-Id': clientId }
});
return response.json();
}
// Get user's games with pagination
async function getUserGames(username, page = 0, size = 20) {
const response = await fetch(
`${baseUrl}/users/${username}/games?page=${page}&size=${size}`,
{ headers: { 'X-Client-Id': clientId } }
);
return response.json();
}
Python (requests)
import requests
CLIENT_ID = 'your-client-id'
BASE_URL = 'https://www.chessmail.de/api/v3'
headers = {'X-Client-Id': CLIENT_ID}
def get_user(username):
"""Get user profile."""
response = requests.get(f'{BASE_URL}/users/{username}', headers=headers)
response.raise_for_status()
return response.json()
def get_user_games(username, page=0, size=20, status='running', sort='lastMoveDate', order='desc'):
"""Get user's games with pagination."""
params = {
'page': page,
'size': size,
'status': status,
'sort': sort,
'order': order
}
response = requests.get(f'{BASE_URL}/users/{username}/games', headers=headers, params=params)
response.raise_for_status()
return response.json()
def get_game(game_id):
"""Get a specific game by ID."""
response = requests.get(f'{BASE_URL}/games/{game_id}', headers=headers)
response.raise_for_status()
return response.json()
def get_started_games(usernames, since_hours=24):
"""Get recently started games for multiple users."""
params = {
'usernames': ','.join(usernames),
'since-hours': since_hours
}
response = requests.get(f'{BASE_URL}/games/started', headers=headers, params=params)
response.raise_for_status()
return response.json()
def get_finished_games(usernames, since_hours=24):
"""Get recently finished games for multiple users."""
params = {
'usernames': ','.join(usernames),
'since-hours': since_hours
}
response = requests.get(f'{BASE_URL}/games/finished', headers=headers, params=params)
response.raise_for_status()
return response.json()
# Example usage
if __name__ == '__main__':
# Get user profile
user = get_user('player1')
print(f"User: {user['username']}, Rating: {user.get('rating')}")
# Get all running games
games = get_user_games('player1', status='running')
print(f"Running games: {games['totalElements']}")
for game in games['content']:
print(f" {game['id']}: {game['playerWhite']} vs {game['playerBlack']}")
# Get recently started games for multiple users
started = get_started_games(['player1', 'player2'], since_hours=24)
print(f"Started games in last 24h: {len(started)}")
# Get recently finished games for multiple users
finished = get_finished_games(['player1', 'player2'], since_hours=48)
print(f"Finished games in last 48h: {len(finished)}")