API Usage Flow
This document outlines the typical workflow for using the ESFA Backend API, from authentication to completing game match operations.
Overview
The ESFA Backend API follows a simple but secure workflow:
Authenticate with the Authentication Service to obtain a Bearer token
Retrieve match information when needed
Submit match results when games are completed
Handle token expiration and refresh as needed
Detailed Workflow
Step 1: Obtain Bearer Token
First, authenticate with the external Authentication Service to get a short-lived Bearer token:
TOKEN=$(curl -s -X POST https://auth.your-service.tld/v1/oauth/token/machine \
-H "Content-Type: application/json" \
-d '{"apiKey":"<your-api-key>","secretKey":"<your-secret-key>"}' \
| jq -r '.data.token')
Response:
{
"data": {
"token": "eyJhbGciOi...<snip>...",
"expires": "2025-09-05T13:31:23.174Z"
}
}
Step 2: Use Token for API Calls
Include the Bearer token in the Authorization header for all Backend API requests:
curl -H "Authorization: Bearer $TOKEN" \
https://api.your-service.tld/api/v1/games/TTT/matches/<matchId>
Response:
{
"matchId": "a3c6e5f2-1a2b-4c5d-8e9f-0123456789ab",
"gameCode": "TTT",
"players": [
{
"id": "p1",
"name": "Alice",
"status": "Active",
"imgAvatarUrl": "https://api.dicebear.com/9.x/adventurer/svg?seed=Alice"
},
{
"id": "p2",
"name": "Bob",
"status": "Pending",
"imgAvatarUrl": "https://api.dicebear.com/9.x/adventurer/svg?seed=Bob"
}
]
}
Submit Match Results
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"results":[{"playerId":"p1","place":1,"score":1200},{"playerId":"p2","place":2,"score":900}]}' \
https://api.your-service.tld/api/v1/games/TTT/matches/<matchId>/finish
Response:
HTTP/1.1 204 No Content
Complete Example Script
Here's a comprehensive script demonstrating the full workflow:
#!/bin/bash
# Configuration
AUTH_SERVICE="https://auth.your-service.tld"
API_SERVICE="https://api.your-service.tld"
API_KEY="your-api-key"
SECRET_KEY="your-secret-key"
GAME_CODE="TTT"
MATCH_ID="a3c6e5f2-1a2b-4c5d-8e9f-0123456789ab"
# Function to get fresh token
get_token() {
echo "Obtaining authentication token..." >&2
TOKEN=$(curl -s -X POST $AUTH_SERVICE/v1/oauth/token/machine \
-H "Content-Type: application/json" \
-d "{\"apiKey\":\"$API_KEY\",\"secretKey\":\"$SECRET_KEY\"}" \
| jq -r '.data.token')
if [ "$TOKEN" = "null" ] || [ -z "$TOKEN" ]; then
echo "Failed to obtain token" >&2
return 1
fi
echo "Token obtained successfully" >&2
echo $TOKEN
}
# Function to make authenticated API calls with retry
api_call() {
local method=$1
local endpoint=$2
local data=$3
local retry=true
while $retry; do
if [ -z "$TOKEN" ]; then
TOKEN=$(get_token) || return 1
fi
if [ "$method" = "GET" ]; then
response=$(curl -s -w "%{http_code}" \
-H "Authorization: Bearer $TOKEN" \
$API_SERVICE$endpoint)
else
response=$(curl -s -w "%{http_code}" -X $method \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "$data" \
$API_SERVICE$endpoint)
fi
status_code=${response: -3}
body=${response%???}
case $status_code in
401)
echo "Token expired, refreshing..." >&2
TOKEN=$(get_token) || return 1
continue
;;
200|204)
retry=false
;;
*)
echo "API call failed with status $status_code: $body" >&2
return 1
;;
esac
done
echo "$body"
}
# Main workflow
echo "Starting ESFA API workflow..."
# Get match information
echo "Fetching match information..."
match_data=$(api_call GET "/api/v1/games/$GAME_CODE/matches/$MATCH_ID")
if [ $? -eq 0 ]; then
echo "Match data retrieved successfully:"
echo "$match_data" | jq .
else
echo "Failed to retrieve match data"
exit 1
fi
# Submit results
echo "Submitting match results..."
results_data='{"results":[{"playerId":"p1","place":1,"score":1200},{"playerId":"p2","place":2,"score":900}]}'
api_call POST "/api/v1/games/$GAME_CODE/matches/$MATCH_ID/finish" "$results_data"
if [ $? -eq 0 ]; then
echo "Match results submitted successfully"
else
echo "Failed to submit match results"
exit 1
fi
echo "Workflow completed successfully!"
Best Practices
Token Management
Store Securely: Never log or expose Bearer tokens
Handle Expiration: Implement automatic token refresh on 401 responses
Cache Wisely: Reuse tokens until expiration to avoid unnecessary auth calls
Monitor Expiry: Check token expiration timestamps before making calls
Error Handling
Retry Logic: Implement retry with exponential backoff for 5xx errors
Validate Input: Check parameters before making API calls
Log Appropriately: Log errors without exposing sensitive data
Graceful Degradation: Handle API unavailability gracefully
Batch Operations: Group related operations when possible
Connection Pooling: Reuse HTTP connections for multiple calls
Rate Limiting: Respect API rate limits (if applicable)
Caching: Cache match data when appropriate
Common Scenarios
Long-Running Applications
For applications that run continuously:
Store the token and its expiration time
Check token validity before each API call
Refresh automatically when needed
Handle authentication failures gracefully
Batch Processing
For processing multiple matches:
Obtain token once at the beginning
Process matches in batches
Handle token refresh during processing
Log progress and errors appropriately
Integration Testing
For testing your integration:
Use test credentials and endpoints
Validate all response codes and formats
Test token expiration scenarios
Verify error handling paths
Notes
Token Lifetime: Tokens are short-lived; refresh them when expired
Authentication Errors: If you receive 401 from the backend, verify your token is current
Service Dependencies: The Authentication Service and Backend API are separate services
Rate Limits: Be respectful of API limits and implement appropriate retry logic
05 September 2025