The Timeloop API provides RESTful endpoints for managing game definitions, game sessions, and character progression. All endpoints use JSON for request/response bodies.
Base URL: http://localhost:3000
Content-Type: application/json for all POST/PUT requests
Currently, no authentication is required. Authentication will be added in a future update.
All endpoints may return the following error responses:
{
"error": "Error message describing what went wrong"
}200 OK- Request succeeded201 Created- Resource created successfully204 No Content- Resource deleted successfully400 Bad Request- Invalid input or validation error404 Not Found- Resource not found409 Conflict- Duplicate resource (e.g., duplicate name)500 Internal Server Error- Server error
GET /health
Returns the health status of the server.
- Status:
200 OK - Body: Empty
curl http://localhost:3000/healthAttributes represent character statistics like Strength, Agility, Intelligence, etc.
POST /api/definitions/attributes
Creates a new attribute definition.
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Strength",
"description": "Physical power and muscle capability",
"category": "Physical",
"base_value": 10,
"min_value": 1,
"max_value": 100,
"training_difficulty": 100,
"icon": null
}id(string, UUID) - Unique identifier (generated client-side)name(string, required) - Unique name for the attributedescription(string, required) - Description of what the attribute representscategory(enum, required) - One of: "Physical", "Mental", "Social", "Spiritual"base_value(number, required) - Starting value (must be between min and max)min_value(number, required) - Minimum allowed valuemax_value(number, required) - Maximum allowed value (must be > min_value)training_difficulty(number, required) - Difficulty percentage (1-100)icon(string, optional) - Icon identifier or path
- Status:
201 Created - Body: The created attribute (same structure as request)
curl -X POST http://localhost:3000/api/definitions/attributes \
-H "Content-Type: application/json" \
-d '{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Strength",
"description": "Physical power",
"category": "Physical",
"base_value": 10,
"min_value": 1,
"max_value": 100,
"training_difficulty": 100,
"icon": null
}'400 Bad Request- Validation error- Empty name
- Empty description
- Invalid range (min >= max)
- Base value out of range
- Training difficulty = 0
409 Conflict- Attribute with this name already exists (case-insensitive)
GET /api/definitions/attributes/:id
Retrieves a specific attribute by ID.
id(path parameter) - UUID of the attribute
- Status:
200 OK - Body: Attribute object
curl http://localhost:3000/api/definitions/attributes/550e8400-e29b-41d4-a716-446655440000404 Not Found- Attribute with this ID does not exist
PUT /api/definitions/attributes/:id
Updates an existing attribute.
id(path parameter) - UUID of the attribute to update
Same structure as Create Attribute. The id in the body must match the id in the URL.
- Status:
200 OK - Body: The updated attribute
curl -X PUT http://localhost:3000/api/definitions/attributes/550e8400-e29b-41d4-a716-446655440000 \
-H "Content-Type: application/json" \
-d '{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Strength",
"description": "Updated description",
"category": "Physical",
"base_value": 15,
"min_value": 1,
"max_value": 100,
"training_difficulty": 100,
"icon": null
}'400 Bad Request- Validation error or ID mismatch404 Not Found- Attribute not found409 Conflict- Name conflicts with another attribute
DELETE /api/definitions/attributes/:id
Deletes an attribute definition.
id(path parameter) - UUID of the attribute to delete
- Status:
204 No Content - Body: Empty
curl -X DELETE http://localhost:3000/api/definitions/attributes/550e8400-e29b-41d4-a716-446655440000404 Not Found- Attribute not found
GET /api/definitions/attributes
Searches or lists all attributes. If query parameter is provided, returns matching attributes. Otherwise, returns all attributes.
q(optional) - Search query (case-insensitive substring match on name)
- Status:
200 OK - Body: Array of attribute objects
List all attributes:
curl http://localhost:3000/api/definitions/attributesSearch for attributes:
curl http://localhost:3000/api/definitions/attributes?q=strength[
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Strength",
"description": "Physical power",
"category": "Physical",
"base_value": 10,
"min_value": 1,
"max_value": 100,
"training_difficulty": 100,
"icon": null
},
{
"id": "650e8400-e29b-41d4-a716-446655440001",
"name": "Physical Endurance",
"description": "Stamina and resilience",
"category": "Physical",
"base_value": 10,
"min_value": 1,
"max_value": 100,
"training_difficulty": 120,
"icon": null
}
]POST /api/game/new
Creates a new game session with a character.
{
"character_name": "Aldric the Wise",
"starting_age": 18
}- Status:
200 OK - Body: Game state with character details
curl -X POST http://localhost:3000/api/game/new \
-H "Content-Type: application/json" \
-d '{"character_name": "Aldric", "starting_age": 18}'GET /api/game/current
Retrieves the current active game session.
- Status:
200 OK - Body: Current game state
404 Not Found- No active game session
curl http://localhost:3000/api/game/currentPOST /api/game/tick
Advances the game by one tick (processes training, aging, etc.).
- Status:
200 OK - Body: Updated game state
404 Not Found- No active game session
curl -X POST http://localhost:3000/api/game/tickPOST /api/game/training
Sets which attribute the character is training.
{
"attribute_id": "550e8400-e29b-41d4-a716-446655440000"
}- Status:
200 OK - Body: Updated game state
404 Not Found- No active game or invalid attribute ID
curl -X POST http://localhost:3000/api/game/training \
-H "Content-Type: application/json" \
-d '{"attribute_id": "550e8400-e29b-41d4-a716-446655440000"}'PUT /api/game/save
Saves the current game session to disk.
- Status:
200 OK - Body: Success message
404 Not Found- No active game session
curl -X PUT http://localhost:3000/api/game/saveGET /api/game/saves
Lists all available save files.
- Status:
200 OK - Body: Array of save file names
curl http://localhost:3000/api/game/savesResponse:
[
"aldric_2025-10-29.json",
"gandalf_2025-10-28.json"
]Currently, no rate limiting is implemented. This will be added in a future update.
API version: v1 (implicit)
Future versions will use URL prefixing: /api/v2/...
The API client is included in the codebase:
use timeloop::editor::api_client::EditorApiClient;
let client = EditorApiClient::new("http://localhost:3000");
let attributes = client.list_attributes().await?;See src/editor/api_client.rs for full implementation.
cargo run --bin timeloop-serverServer starts on http://localhost:3000
Run integration tests:
cargo test --test api_integration_testsFor issues or questions:
- Open an issue on GitHub
- Check
docs/plans/ARCHITECTURE_REFACTOR.mdfor architecture details