Carambus API Documentation¶
Overview¶
The Carambus API provides RESTful endpoints for managing billiards tournaments, leagues, players, and real-time scoreboard functionality. The API is built on Ruby on Rails and follows REST conventions.
Authentication¶
Session-based Authentication¶
Most endpoints require authentication via Devise. Include session cookies in your requests:
# Login to get session
curl -X POST http://localhost:3000/login \
-H "Content-Type: application/json" \
-d '{"user": {"email": "user@example.com", "password": "password"}}' \
-c cookies.txt
# Use session for authenticated requests
curl -X GET http://localhost:3000/api/tournaments \
-b cookies.txt
API Token Authentication (Future)¶
Token-based authentication is planned for future releases.
Base URL¶
Development: http://localhost:3000
Production: https://carambus.de
Response Format¶
All API responses are in JSON format:
{
"data": {
"id": 1,
"type": "tournament",
"attributes": {
"name": "Regional Championship 2024",
"start_date": "2024-01-15",
"status": "active"
},
"relationships": {
"discipline": {
"data": {
"id": 1,
"type": "discipline"
}
}
}
}
}
Error Responses¶
{
"error": {
"code": "validation_error",
"message": "Validation failed",
"details": {
"name": ["can't be blank"]
}
}
}
Core Endpoints¶
Tournaments¶
List Tournaments¶
GET /tournaments
Query Parameters:
- page
: Page number (default: 1)
- per_page
: Items per page (default: 25)
- status
: Filter by status (active
, completed
, draft
)
- discipline_id
: Filter by discipline
- location_id
: Filter by location
Response:
{
"data": [
{
"id": 1,
"type": "tournament",
"attributes": {
"name": "Regional Championship 2024",
"start_date": "2024-01-15",
"end_date": "2024-01-17",
"status": "active",
"discipline_name": "3-Cushion",
"location_name": "Billard Club Wedel"
}
}
],
"meta": {
"total_count": 50,
"total_pages": 2,
"current_page": 1
}
}
Get Tournament¶
GET /tournaments/{id}
Response:
{
"data": {
"id": 1,
"type": "tournament",
"attributes": {
"name": "Regional Championship 2024",
"start_date": "2024-01-15",
"end_date": "2024-01-17",
"status": "active",
"discipline_name": "3-Cushion",
"location_name": "Billard Club Wedel",
"participant_count": 16,
"game_count": 24
},
"relationships": {
"discipline": {
"data": {
"id": 1,
"type": "discipline"
}
},
"location": {
"data": {
"id": 1,
"type": "location"
}
},
"seedings": {
"data": [
{
"id": 1,
"type": "seeding"
}
]
}
}
}
}
Create Tournament¶
POST /tournaments
Request Body:
{
"tournament": {
"name": "New Tournament",
"discipline_id": 1,
"location_id": 1,
"start_date": "2024-02-01",
"end_date": "2024-02-03",
"max_participants": 16
}
}
Update Tournament¶
PATCH /tournaments/{id}
Delete Tournament¶
DELETE /tournaments/{id}
Tournament Actions¶
Start Tournament¶
POST /tournaments/{id}/start
Reset Tournament¶
POST /tournaments/{id}/reset
Generate Game Plan¶
POST /tournaments/{id}/generate_game_plan
Players¶
List Players¶
GET /players
Query Parameters:
- page
: Page number
- per_page
: Items per page
- region_id
: Filter by region
- club_id
: Filter by club
- search
: Search by name
Get Player¶
GET /players/{id}
Response:
{
"data": {
"id": 1,
"type": "player",
"attributes": {
"first_name": "John",
"last_name": "Doe",
"ba_id": "12345",
"club_name": "Billard Club Wedel",
"region_name": "Schleswig-Holstein",
"ranking": 1250
}
}
}
Leagues¶
List Leagues¶
GET /leagues
Get League¶
GET /leagues/{id}
League Teams¶
GET /leagues/{id}/league_teams
Parties (Matches)¶
List Parties¶
GET /parties
Query Parameters:
- tournament_id
: Filter by tournament
- league_id
: Filter by league
- status
: Filter by status
- date
: Filter by date
Get Party¶
GET /parties/{id}
Response:
{
"data": {
"id": 1,
"type": "party",
"attributes": {
"date": "2024-01-15T14:00:00Z",
"status": "in_progress",
"team_a_name": "Team Alpha",
"team_b_name": "Team Beta",
"score_a": 3,
"score_b": 2
},
"relationships": {
"league_team_a": {
"data": {
"id": 1,
"type": "league_team"
}
},
"league_team_b": {
"data": {
"id": 2,
"type": "league_team"
}
}
}
}
}
Table Monitors¶
Get Table Monitor¶
GET /table_monitors/{id}
Response:
{
"data": {
"id": 1,
"type": "table_monitor",
"attributes": {
"table_number": 1,
"status": "active",
"current_game": {
"id": 123,
"player_a": "John Doe",
"player_b": "Jane Smith",
"score_a": 15,
"score_b": 12,
"balls_goal": 30
}
}
}
}
Update Table Monitor¶
PATCH /table_monitors/{id}
Request Body:
{
"table_monitor": {
"balls_a": 16,
"balls_b": 12
}
}
Table Monitor Actions¶
Add Points¶
POST /table_monitors/{id}/add_one
POST /table_monitors/{id}/add_ten
Subtract Points¶
POST /table_monitors/{id}/minus_one
POST /table_monitors/{id}/minus_ten
Next Step¶
POST /table_monitors/{id}/next_step
Start Game¶
POST /table_monitors/{id}/start_game
Evaluate Result¶
POST /table_monitors/{id}/evaluate_result
Real-time API¶
Action Cable Channels¶
Table Monitor Channel¶
Subscribe to real-time table monitor updates:
import { createConsumer } from "@rails/actioncable"
const consumer = createConsumer()
const subscription = consumer.subscriptions.create(
{ channel: "TableMonitorChannel", table_id: 1 },
{
connected() {
console.log("Connected to table monitor")
},
disconnected() {
console.log("Disconnected from table monitor")
},
received(data) {
console.log("Received update:", data)
// Update UI with new data
updateTableDisplay(data)
}
}
)
Channel Events:
- score_update
: Score changes
- game_start
: New game started
- game_end
: Game completed
- status_change
: Table status changed
Scoreboard Channel¶
Subscribe to scoreboard updates:
const scoreboardSubscription = consumer.subscriptions.create(
{ channel: "ScoreboardChannel", location_id: 1 },
{
received(data) {
updateScoreboard(data)
}
}
)
WebSocket Message Format¶
{
"type": "score_update",
"table_id": 1,
"data": {
"player_a": "John Doe",
"player_b": "Jane Smith",
"score_a": 16,
"score_b": 12,
"balls_goal": 30,
"status": "in_progress"
},
"timestamp": "2024-01-15T14:30:00Z"
}
Data Synchronization API¶
External Data Sources¶
BA (Billiards Association) Sync¶
POST /api/sync/ba/players
POST /api/sync/ba/tournaments
CC (Competition Center) Sync¶
POST /api/sync/cc/competitions
POST /api/sync/cc/results
Region Management¶
Check Region Data¶
GET /region_ccs/{id}/check
Fix Region Data¶
POST /region_ccs/{id}/fix
Admin API¶
User Management¶
GET /admin/users
POST /admin/users
PATCH /admin/users/{id}
DELETE /admin/users/{id}
System Settings¶
GET /settings/club_settings
POST /settings/update_club_settings
GET /settings/tournament_settings
POST /settings/update_tournament_settings
Rate Limiting¶
API requests are rate-limited to prevent abuse:
- Authenticated users: 1000 requests per hour
- Unauthenticated users: 100 requests per hour
Rate limit headers are included in responses:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1642248000
Pagination¶
List endpoints support pagination with the following parameters:
page
: Page number (default: 1)per_page
: Items per page (default: 25, max: 100)
Pagination metadata is included in responses:
{
"data": [...],
"meta": {
"total_count": 150,
"total_pages": 6,
"current_page": 1,
"per_page": 25
}
}
Filtering and Sorting¶
Filtering¶
Most list endpoints support filtering:
GET /tournaments?status=active&discipline_id=1&location_id=2
Sorting¶
Sorting is supported on most endpoints:
GET /tournaments?sort=start_date&direction=desc
GET /players?sort=last_name&direction=asc
Error Codes¶
Code | Description |
---|---|
400 | Bad Request - Invalid parameters |
401 | Unauthorized - Authentication required |
403 | Forbidden - Insufficient permissions |
404 | Not Found - Resource not found |
422 | Unprocessable Entity - Validation errors |
429 | Too Many Requests - Rate limit exceeded |
500 | Internal Server Error |
SDKs and Libraries¶
JavaScript/TypeScript¶
npm install carambus-api-client
import { CarambusAPI } from 'carambus-api-client'
const api = new CarambusAPI({
baseURL: 'https://carambus.de',
credentials: 'include'
})
// Get tournaments
const tournaments = await api.tournaments.list()
// Create tournament
const tournament = await api.tournaments.create({
name: 'New Tournament',
discipline_id: 1,
location_id: 1
})
Ruby¶
require 'carambus_api'
client = CarambusAPI::Client.new(
base_url: 'https://carambus.de',
session_cookies: session_cookies
)
# Get tournaments
tournaments = client.tournaments.list
# Create tournament
tournament = client.tournaments.create(
name: 'New Tournament',
discipline_id: 1,
location_id: 1
)
Examples¶
Complete Tournament Workflow¶
// 1. Create tournament
const tournament = await api.tournaments.create({
name: 'Championship 2024',
discipline_id: 1,
location_id: 1,
start_date: '2024-02-01',
max_participants: 16
})
// 2. Add participants
for (const player of players) {
await api.tournaments.addParticipant(tournament.id, player.id)
}
// 3. Generate game plan
await api.tournaments.generateGamePlan(tournament.id)
// 4. Start tournament
await api.tournaments.start(tournament.id)
// 5. Subscribe to real-time updates
const subscription = consumer.subscriptions.create(
{ channel: "TournamentChannel", tournament_id: tournament.id },
{
received(data) {
updateTournamentDisplay(data)
}
}
)
Real-time Scoreboard Integration¶
// Connect to scoreboard
const scoreboard = consumer.subscriptions.create(
{ channel: "ScoreboardChannel", location_id: 1 },
{
received(data) {
// Update scoreboard display
document.getElementById('scoreboard').innerHTML =
generateScoreboardHTML(data)
}
}
)
// Update table scores
async function updateScore(tableId, player, points) {
await api.tableMonitors.update(tableId, {
[`balls_${player}`]: points
})
}
Support¶
For API support and questions:
- Documentation: API.md
- Issues: GitHub Issues
- Discussions: GitHub Discussions
This API documentation is maintained by the Carambus development team. For questions or contributions, please see the Contributing Guide.