Navigation Menu
API Reference
Dutchie's Brackets provides a REST API for tournament organizers to programmatically manage their tournaments, participants, and matches.
Important Notes
Intended Audience: Tournament Organizers who want to integrate Dutchie's Brackets with their own systems
Access Scope: You can only access and modify tournaments that you created. You cannot access other users' tournaments or modify platform-wide settings.
Authentication: All API endpoints require authentication with your Dutchie's Brackets account.
Base URL
https://dutchieb.com/api
All API requests must be made to this base URL.
Authentication
API Token Authentication
The Dutchie's Brackets API uses API token authentication for external applications. You must be authenticated with a full account to use the API.
Generating an API Token:
- Sign in to your Dutchie's Brackets account
- Navigate to Account Settings → API Tokens
- Click Generate New Token
- Give your token a descriptive name (e.g., "Production Integration", "Tournament Manager Bot")
- Copy the token immediately - it will only be shown once
- Store it securely in your application's environment variables
Note: The API token generation UI is currently under development. For early access to API integration, please contact support at [email protected] with your use case.
Using Your API Token:
Include your API token in the Authorization header with the Bearer scheme for all API requests:
curl https://dutchieb.com/api/tournaments/create \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "My Tournament", ...}'
JavaScript/TypeScript:
const API_TOKEN = process.env.DUTCHIEB_API_TOKEN;
const response = await fetch('https://dutchieb.com/api/tournaments/create', {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_TOKEN}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Summer Pool Championship',
sport: 'POOL',
// ... other fields
})
});
Python:
import os
import requests
API_TOKEN = os.getenv('DUTCHIEB_API_TOKEN')
headers = {
'Authorization': f'Bearer {API_TOKEN}',
'Content-Type': 'application/json'
}
response = requests.post(
'https://dutchieb.com/api/tournaments/create',
json={'name': 'Summer Pool Championship', ...},
headers=headers
)
Security Best Practices:
- Never commit API tokens to version control
- Store tokens in environment variables or secure vaults (AWS Secrets Manager, HashiCorp Vault, etc.)
- Use different tokens for development, staging, and production environments
- Rotate tokens periodically (recommended: every 90 days)
- Revoke tokens immediately if compromised
- Use token names to identify where each token is used
- Monitor token usage in your account settings
Tournaments
Create Tournament
Create a new tournament in your account.
Endpoint: POST /api/tournaments/create
Authentication: Required
Request Body:
{
"name": "Summer Pool Championship 2025",
"description": "Annual pool tournament",
"sport": "POOL",
"bracketType": "DOUBLE_ELIMINATION",
"maxPlayers": 16,
"venueCount": 3,
"visibility": "PRIVATE",
"requireFullAccount": false,
"startDate": "2025-07-15T10:00:00Z",
"endDate": "2025-07-15T18:00:00Z"
}
Field Descriptions:
name(required): Tournament name, 1-100 charactersdescription(optional): Tournament description, max 500 characterssport(required): Sport type (POOL, DARTS, CORNHOLE, PINGPONG, etc.)bracketType(required): Tournament formatSINGLE_ELIMINATION: Traditional single-elimination bracketDOUBLE_ELIMINATION: Loser's bracket formatROUND_ROBIN: Everyone plays everyone
maxPlayers(required): Maximum participants, 2-128venueCount(required): Number of simultaneous match locations, 1-50visibility(required): Who can see the tournamentPUBLIC: Anyone can viewPRIVATE: Only accessible via invite link
requireFullAccount(optional): If true, participants must create an account to join (defaults to false)startDate(optional): Planned start date/time (ISO 8601 format)endDate(optional): Planned end date/time (ISO 8601 format)
Response: 201 Created
{
"success": true,
"tournament": {
"id": "clx123abc",
"name": "Summer Pool Championship 2025",
"sport": "POOL",
"status": "DRAFT",
"visibility": "PRIVATE",
"inviteCode": "ABC123"
}
}
Error Responses:
401 Unauthorized: Not authenticated400 Bad Request: Validation error (invalid field values)
Get Tournament Details
Retrieve details for one of your tournaments.
Endpoint: GET /api/tournaments/:id
Authentication: Required (must be tournament creator)
Response: 200 OK
{
"tournament": {
"id": "clx123abc",
"name": "Summer Pool Championship 2025",
"description": "Annual pool tournament",
"sport": "POOL",
"type": "DOUBLE_ELIMINATION",
"status": "IN_PROGRESS",
"visibility": "PRIVATE",
"maxPlayers": 16,
"requireFullAccount": false,
"inviteCode": "ABC123",
"startDate": "2025-07-15T10:00:00Z",
"endDate": "2025-07-15T18:00:00Z",
"createdAt": "2025-07-01T14:30:00Z",
"creator": {
"name": "John Smith",
"email": "[email protected]"
},
"participantCount": 12
}
}
Error Responses:
401 Unauthorized: Not authenticated403 Forbidden: Not the tournament creator404 Not Found: Tournament doesn't exist
Participants
Get Tournament Participants
Retrieve all participants registered for your tournament.
Endpoint: GET /api/tournaments/:id/participants
Authentication: Required (must be tournament creator)
Response: 200 OK
{
"participants": [
{
"id": "clp123xyz",
"displayName": "Alice Johnson",
"participantType": "FULL_ACCOUNT",
"status": "ACTIVE",
"seed": 1,
"createdAt": "2025-07-10T09:15:00Z",
"userName": "Alice Johnson",
"userEmail": "[email protected]"
},
{
"id": "clp456abc",
"displayName": "Bob Smith",
"participantType": "QUICK_SESSION",
"status": "ACTIVE",
"seed": 2,
"createdAt": "2025-07-10T09:20:00Z",
"userName": null,
"userEmail": null
}
]
}
Participant Types:
FULL_ACCOUNT: User with a Dutchie's Brackets accountQUICK_SESSION: Temporary participant (joined via quick join)
Error Responses:
401 Unauthorized: Not authenticated403 Forbidden: Not the tournament creator404 Not Found: Tournament doesn't exist
Bracket Management
Get Tournament Bracket
Retrieve the complete bracket structure with all rounds and matches for your tournament.
Endpoint: GET /api/tournaments/:id/bracket
Authentication: Required (must be tournament creator)
Response: 200 OK
{
"rounds": [
{
"id": "clr123",
"tournamentId": "clx123abc",
"roundNumber": 1,
"name": "Round 1",
"status": "COMPLETED",
"matches": [
{
"id": "clm456",
"roundId": "clr123",
"matchNumber": 1,
"player1Id": "clp123xyz",
"player2Id": "clp456abc",
"player1": {
"id": "clp123xyz",
"displayName": "Alice Johnson"
},
"player2": {
"id": "clp456abc",
"displayName": "Bob Smith"
},
"player1Score": 5,
"player2Score": 3,
"winnerId": "clp123xyz",
"status": "COMPLETED",
"completedAt": "2025-07-15T10:45:00Z"
}
]
}
]
}
Match Statuses:
PENDING: Not yet startedIN_PROGRESS: Currently being playedCOMPLETED: Finished with results
Round Statuses:
PENDING: Not yet startedIN_PROGRESS: Some matches completedCOMPLETED: All matches completed
Error Responses:
401 Unauthorized: Not authenticated403 Forbidden: Not the tournament creator404 Not Found: Tournament doesn't exist or bracket not generated
Generate Bracket
Generate the tournament bracket based on registered participants. This can only be done once per tournament.
Endpoint: POST /api/tournaments/:id/generate-bracket
Authentication: Required (must be tournament creator)
Request Body: None required
Response: 200 OK
{
"success": true,
"message": "Bracket generated successfully",
"roundCount": 4,
"matchCount": 15
}
Requirements:
- Tournament must be in
DRAFTorREGISTRATION_OPENstatus - Must have at least 2 participants
- Bracket cannot already be generated
Error Responses:
401 Unauthorized: Not authenticated403 Forbidden: Not the tournament creator400 Bad Request: Insufficient participants (minimum 2 required)409 Conflict: Bracket already generated404 Not Found: Tournament doesn't exist
Match Management
Update Match Score
Enter or update the score for a match in your tournament.
Endpoint: POST /api/tournaments/:tournamentId/matches/:matchId/score
Authentication: Required (must be tournament creator)
Request Body:
{
"winnerId": "clp123xyz",
"player1Score": 5,
"player2Score": 3
}
Field Descriptions:
winnerId(required): ID of the winning participantplayer1Score(required): Score for player 1player2Score(required): Score for player 2
Response: 200 OK
{
"success": true,
"match": {
"id": "clm456",
"winnerId": "clp123xyz",
"player1Score": 5,
"player2Score": 3,
"status": "COMPLETED",
"completedAt": "2025-07-15T10:45:00Z"
}
}
Behavior:
- Automatically updates match status to
COMPLETED - Advances winner to next round (if applicable)
- Triggers real-time updates via WebSocket to all connected clients
- Updates tournament status if this was the final match
Error Responses:
401 Unauthorized: Not authenticated403 Forbidden: Not the tournament creator400 Bad Request: Invalid scores or winner ID404 Not Found: Tournament or match doesn't exist
Tournament Status Management
Update Tournament Status
Change the status of your tournament (e.g., open registration, start tournament, complete tournament).
Endpoint: POST /api/tournaments/:id/status
Authentication: Required (must be tournament creator)
Request Body:
{
"status": "REGISTRATION_OPEN"
}
Valid Status Transitions:
DRAFT→REGISTRATION_OPEN: Open registration for participantsREGISTRATION_OPEN→IN_PROGRESS: Start the tournamentIN_PROGRESS→COMPLETED: End the tournament- Any status →
CANCELLED: Cancel the tournament
Response: 200 OK
{
"success": true,
"tournament": {
"id": "clx123abc",
"status": "REGISTRATION_OPEN"
}
}
Error Responses:
401 Unauthorized: Not authenticated403 Forbidden: Not the tournament creator400 Bad Request: Invalid status transition404 Not Found: Tournament doesn't exist
Error Handling
Standard Error Response
All errors follow this format:
{
"error": "Human-readable error message",
"details": {
"field": ["Specific validation error"]
}
}
HTTP Status Codes
| Code | Meaning | When Used |
|---|---|---|
200 | OK | Successful GET/POST request |
201 | Created | Resource successfully created |
400 | Bad Request | Validation error or invalid data |
401 | Unauthorized | Not authenticated (missing/invalid session) |
403 | Forbidden | Authenticated but not authorized (not tournament creator) |
404 | Not Found | Resource doesn't exist |
409 | Conflict | Resource state conflict (e.g., bracket already generated) |
500 | Server Error | Internal server error |
Code Examples
JavaScript/TypeScript
Create Tournament and Generate Bracket:
async function createAndSetupTournament() {
// 1. Create tournament
const createResponse = await fetch('/api/tournaments/create', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'Summer Pool Championship',
sport: 'POOL',
bracketType: 'DOUBLE_ELIMINATION',
maxPlayers: 16,
venueCount: 3,
visibility: 'PRIVATE',
requireFullAccount: false
}),
});
if (!createResponse.ok) {
const error = await createResponse.json();
throw new Error(error.error);
}
const { tournament } = await createResponse.json();
console.log('Created tournament:', tournament.id);
// 2. Wait for participants to register...
// (They join via the invite link: https://dutchieb.com/join/${tournament.inviteCode})
// 3. Generate bracket when ready
const generateResponse = await fetch(`/api/tournaments/${tournament.id}/generate-bracket`, {
method: 'POST'
});
if (!generateResponse.ok) {
const error = await generateResponse.json();
throw new Error(error.error);
}
const { roundCount, matchCount } = await generateResponse.json();
console.log(`Bracket generated: ${roundCount} rounds, ${matchCount} matches`);
return tournament;
}
Get Bracket and Update Match Scores:
async function updateMatchScore(tournamentId: string, matchId: string) {
// 1. Get current bracket
const bracketResponse = await fetch(`/api/tournaments/${tournamentId}/bracket`);
const { rounds } = await bracketResponse.json();
// 2. Update match score
const scoreResponse = await fetch(
`/api/tournaments/${tournamentId}/matches/${matchId}/score`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
winnerId: 'clp123xyz',
player1Score: 5,
player2Score: 3
}),
}
);
if (!scoreResponse.ok) {
const error = await scoreResponse.json();
throw new Error(error.error);
}
const { match } = await scoreResponse.json();
console.log('Match completed:', match);
}
Python
Create Tournament:
import os
import requests
def create_tournament(api_token):
"""Create a new tournament using API token authentication"""
url = "https://dutchieb.com/api/tournaments/create"
headers = {
"Authorization": f"Bearer {api_token}",
"Content-Type": "application/json"
}
data = {
"name": "Summer Pool Championship",
"sport": "POOL",
"bracketType": "DOUBLE_ELIMINATION",
"maxPlayers": 16,
"venueCount": 3,
"visibility": "PRIVATE",
"requireFullAccount": False
}
response = requests.post(url, json=data, headers=headers)
response.raise_for_status()
tournament = response.json()["tournament"]
print(f"Created tournament: {tournament['id']}")
print(f"Invite code: {tournament['inviteCode']}")
print(f"Share link: https://dutchieb.com/join/{tournament['inviteCode']}")
return tournament
# Usage - Load token from environment variable
api_token = os.getenv("DUTCHIEB_API_TOKEN")
if not api_token:
raise ValueError("DUTCHIEB_API_TOKEN environment variable not set")
tournament = create_tournament(api_token)
Monitor Tournament and Update Scores:
import os
import requests
class TournamentManager:
"""Manage tournaments via the Dutchie's Brackets API"""
def __init__(self, api_token=None):
"""
Initialize the tournament manager
Args:
api_token: Your API token. If not provided, will read from
DUTCHIEB_API_TOKEN environment variable
"""
self.base_url = "https://dutchieb.com/api"
self.api_token = api_token or os.getenv("DUTCHIEB_API_TOKEN")
if not self.api_token:
raise ValueError("API token required. Set DUTCHIEB_API_TOKEN environment variable or pass token to constructor")
self.headers = {
"Authorization": f"Bearer {self.api_token}",
"Content-Type": "application/json"
}
def get_participants(self, tournament_id):
"""Get all participants for a tournament"""
url = f"{self.base_url}/tournaments/{tournament_id}/participants"
response = requests.get(url, headers=self.headers)
response.raise_for_status()
return response.json()["participants"]
def generate_bracket(self, tournament_id):
"""Generate the tournament bracket"""
url = f"{self.base_url}/tournaments/{tournament_id}/generate-bracket"
response = requests.post(url, headers=self.headers)
response.raise_for_status()
return response.json()
def get_bracket(self, tournament_id):
"""Get current bracket state"""
url = f"{self.base_url}/tournaments/{tournament_id}/bracket"
response = requests.get(url, headers=self.headers)
response.raise_for_status()
return response.json()["rounds"]
def update_match_score(self, tournament_id, match_id, winner_id, p1_score, p2_score):
"""Update score for a match"""
url = f"{self.base_url}/tournaments/{tournament_id}/matches/{match_id}/score"
data = {
"winnerId": winner_id,
"player1Score": p1_score,
"player2Score": p2_score
}
response = requests.post(url, json=data, headers=self.headers)
response.raise_for_status()
return response.json()
# Usage - API token loaded from environment variable
manager = TournamentManager() # Reads from DUTCHIEB_API_TOKEN env var
# Or explicitly pass the token
# manager = TournamentManager(api_token="your-api-token-here")
# Get participants
participants = manager.get_participants("clx123abc")
print(f"Total participants: {len(participants)}")
# Generate bracket
result = manager.generate_bracket("clx123abc")
print(f"Bracket generated: {result['matchCount']} matches")
# Update first match
manager.update_match_score(
tournament_id="clx123abc",
match_id="clm456",
winner_id="clp123xyz",
p1_score=5,
p2_score=3
)
print("Match score updated successfully")
Best Practices
1. Error Handling
Always check response status codes and handle errors appropriately:
const API_TOKEN = process.env.DUTCHIEB_API_TOKEN;
const response = await fetch('https://dutchieb.com/api/tournaments/create', {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_TOKEN}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ /* tournament data */ })
});
if (!response.ok) {
const error = await response.json();
if (response.status === 401) {
// Invalid or expired API token
console.error('Authentication failed: Invalid or expired API token');
console.error('Generate a new token at https://dutchieb.com/settings/api');
} else if (response.status === 403) {
// Not authorized for this resource
console.error('Forbidden: You do not have access to this tournament');
} else if (response.status === 400) {
// Validation error
console.error('Validation error:', error.details);
} else {
// Other error
console.error('API Error:', error.error);
}
return;
}
2. Authentication Security
Protect your API tokens:
- Never commit API tokens to version control (add
.envto.gitignore) - Store tokens in environment variables or secure secret managers
- Use different tokens for development, staging, and production
- Rotate tokens every 90 days
- Revoke compromised tokens immediately through your account settings
- Always use HTTPS for API requests (never HTTP)
- Monitor token usage in your account dashboard
3. Rate Limiting
While rate limiting is not currently enforced, plan for future limits:
- Implement exponential backoff for retries
- Cache responses when appropriate
- Batch operations when possible
4. Real-Time Updates
For live tournament updates, use WebSockets instead of polling:
- Don't repeatedly call
/api/tournaments/:id/bracket - Use WebSocket events for live match updates
- See WebSocket Events for details
5. Tournament Workflow
Follow this recommended sequence:
- Create tournament via API
- Share invite code with participants (they join via web UI)
- Monitor participant registration
- Generate bracket when ready
- Update match scores as they complete
- Monitor bracket progression via WebSocket events
Limitations
Current Limitations:
- Cannot delete tournaments via API (use web UI)
- Cannot modify participants via API (they self-register)
- Cannot customize bracket seeding via API (automatic)
- No bulk operations (must update matches individually)
Planned Features:
- Webhooks for tournament events
- Bulk match score updates
- Advanced bracket customization
- Tournament templates
Support
Need Help?
- WebSocket Events Reference - For real-time updates
- FAQ - Common questions
- Troubleshooting Guide - Common issues
- GitHub Issues - Report bugs
Security Issues: If you discover a security vulnerability, please email [email protected] instead of using public issue trackers.
Was this page helpful?
Help us improve our documentation. Found a typo or have a suggestion?
Report an Issue