API Integration - RumenDamyanov/js-chess GitHub Wiki

API Integration Guide

Learn how to integrate with the go-chess backend API to build your own chess applications.

Overview

The JS Chess project uses a RESTful API with WebSocket support provided by the go-chess backend. All frontend frameworks interact with the same API endpoints.

Base URL

When running locally: http://localhost:8080

Authentication

The demo setup requires no authentication. For production use, implement proper API authentication.

Core Endpoints

Health Check

GET /health

Response:

{
  "status": "healthy",
  "version": "1.0.0",
  "timestamp": "2025-08-04T10:30:00Z",
  "game_count": 42
}

Create New Game

POST /api/games
Content-Type: application/json

Request Body:

{
  "ai_enabled": true,
  "difficulty": "medium"
}

Response:

{
  "id": 123,
  "status": "in_progress",
  "active_color": "white",
  "board": "  a b c d e f g h\n8 r n b q k b n r 8\n...",
  "move_count": 1,
  "move_history": [],
  "created_at": "2025-08-04T10:30:00Z"
}

Get Game State

GET /api/games/{id}

Response:

{
  "id": 123,
  "status": "in_progress",
  "active_color": "white",
  "board": "...",
  "move_count": 5,
  "move_history": [
    {
      "from": "e2",
      "to": "e4",
      "piece": "pawn",
      "timestamp": "2025-08-04T10:31:00Z"
    }
  ],
  "in_check": false,
  "checkmate": false,
  "stalemate": false
}

Make a Move

POST /api/games/{id}/moves
Content-Type: application/json

Request Body:

{
  "from": "e2",
  "to": "e4",
  "promotion": "queen"
}

Response:

{
  "success": true,
  "move": {
    "from": "e2",
    "to": "e4",
    "piece": "pawn",
    "captured": null,
    "promotion": null
  },
  "game_state": {
    "status": "in_progress",
    "active_color": "black",
    "in_check": false
  }
}

Get AI Move

POST /api/games/{id}/ai-move

Response:

{
  "move": {
    "from": "e7",
    "to": "e5",
    "piece": "pawn"
  },
  "analysis": {
    "evaluation": 0.2,
    "depth": 6,
    "best_line": ["e7-e5", "Nf3", "Nc6"]
  },
  "game_state": {
    "status": "in_progress",
    "active_color": "white"
  }
}

WebSocket Communication

Connection

const ws = new WebSocket('ws://localhost:8080/ws/games/123');

Message Types

Game Update:

{
  "type": "game_update",
  "game_id": 123,
  "data": {
    "status": "in_progress",
    "active_color": "black",
    "last_move": {
      "from": "e2",
      "to": "e4"
    }
  }
}

Move Made:

{
  "type": "move_made",
  "game_id": 123,
  "move": {
    "from": "e2",
    "to": "e4",
    "piece": "pawn"
  }
}

Game Over:

{
  "type": "game_over",
  "game_id": 123,
  "result": {
    "winner": "white",
    "reason": "checkmate"
  }
}

Error Handling

All endpoints return consistent error responses:

{
  "error": "invalid_move",
  "message": "Move is not legal",
  "details": {
    "from": "e2",
    "to": "e5",
    "reason": "piece_blocked"
  }
}

Common error codes:

  • invalid_move - Illegal chess move
  • game_not_found - Game ID doesn't exist
  • game_finished - Cannot modify completed game
  • invalid_request - Malformed request body
  • server_error - Internal server error

JavaScript API Client

Use the shared API client for consistent integration:

import { ChessAPI } from '/shared/api/chess-api.js';

const api = new ChessAPI('http://localhost:8080');

// Create a new game
const game = await api.createGame({ ai_enabled: true });

// Make a move
const result = await api.makeMove(game.id, 'e2', 'e4');

// Get AI move
const aiMove = await api.getAIMove(game.id);

TypeScript Support

For TypeScript projects, use the typed client:

import { ChessAPI, GameState, Move } from '/shared/api/chess-api.ts';

const api = new ChessAPI('http://localhost:8080');

const game: GameState = await api.createGame({ ai_enabled: true });
const move: Move = await api.makeMove(game.id, 'e2', 'e4');

Framework Examples

Vanilla JavaScript

async function createGame() {
  const response = await fetch('/api/games', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ ai_enabled: true })
  });
  return await response.json();
}

async function makeMove(gameId, from, to) {
  const response = await fetch(`/api/games/${gameId}/moves`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ from, to })
  });
  return await response.json();
}

jQuery

function createGame() {
  return $.ajax({
    url: '/api/games',
    method: 'POST',
    contentType: 'application/json',
    data: JSON.stringify({ ai_enabled: true })
  });
}

function makeMove(gameId, from, to) {
  return $.ajax({
    url: `/api/games/${gameId}/moves`,
    method: 'POST',
    contentType: 'application/json',
    data: JSON.stringify({ from, to })
  });
}

Vue.js

// In a Vue component
export default {
  methods: {
    async createGame() {
      try {
        const response = await fetch('/api/games', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ ai_enabled: true })
        });
        this.game = await response.json();
      } catch (error) {
        console.error('Failed to create game:', error);
      }
    }
  }
}

React

// Using hooks
import { useState, useCallback } from 'react';

function useChessAPI() {
  const [game, setGame] = useState(null);
  const [loading, setLoading] = useState(false);

  const createGame = useCallback(async () => {
    setLoading(true);
    try {
      const response = await fetch('/api/games', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ ai_enabled: true })
      });
      const newGame = await response.json();
      setGame(newGame);
    } finally {
      setLoading(false);
    }
  }, []);

  return { game, createGame, loading };
}

Angular

// Chess service
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable()
export class ChessService {
  constructor(private http: HttpClient) {}

  createGame(): Observable<any> {
    return this.http.post('/api/games', { ai_enabled: true });
  }

  makeMove(gameId: number, from: string, to: string): Observable<any> {
    return this.http.post(`/api/games/${gameId}/moves`, { from, to });
  }
}

Best Practices

  1. Error Handling: Always wrap API calls in try-catch blocks
  2. Loading States: Show loading indicators during API calls
  3. Debouncing: Debounce rapid move attempts
  4. WebSocket Reconnection: Implement reconnection logic for WebSockets
  5. State Synchronization: Keep local state in sync with server state

Rate Limiting

The API implements rate limiting:

  • 100 requests per minute per IP
  • 10 game creations per minute per IP
  • WebSocket connections limited to 10 per IP

CORS Configuration

For development, CORS is enabled for all origins. In production, configure appropriate CORS settings.

Advanced Features

Move Analysis

GET /api/games/{id}/analysis

Get position evaluation and suggested moves.

Game Export

GET /api/games/{id}/pgn

Export game in PGN format.

FEN Support

POST /api/games
Content-Type: application/json

{
  "fen": "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"
}

Start a game from a specific position using FEN notation.

Testing the API

Use the built-in testing commands:

# Test API health
make test-api

# Manual testing with curl
curl -X POST http://localhost:8080/api/games \
  -H "Content-Type: application/json" \
  -d '{"ai_enabled": true}'

For detailed API documentation, visit the go-chess API reference.

⚠️ **GitHub.com Fallback** ⚠️