- Add delete_sessions_by_character() method to SessionService that cleans up all game sessions associated with a character - Update delete_character() to hard delete instead of soft delete - Call session cleanup before deleting character to prevent orphaned data - Delete associated chat messages when cleaning up sessions - Update API documentation to reflect new behavior 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
42 KiB
API Testing Guide
Last Updated: November 15, 2025 Version: 0.2.0
This document provides manual testing instructions for Code of Conquest API endpoints.
Table of Contents
Setup
Prerequisites
- httpie (recommended) or curl
- Flask app running locally (default:
http://localhost:5000) - Appwrite configured with valid credentials in
.env
Install httpie
# macOS
brew install httpie
# Ubuntu/Debian
apt-get install httpie
# Python pip
pip install httpie
Start the Application
# Activate virtual environment
source venv/bin/activate
# Run Flask app
python wsgi.py
The app will be available at http://localhost:5000
Authentication Endpoints
1. Register User
Endpoint: POST /api/v1/auth/register
Description: Create a new user account and trigger email verification.
Request:
# httpie
http POST localhost:5000/api/v1/auth/register \
email="hero@example.com" \
password="SecurePass123!" \
name="Brave Adventurer"
# curl
curl -X POST http://localhost:5000/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "hero@example.com",
"password": "SecurePass123!",
"name": "Brave Adventurer"
}'
Success Response (201 Created):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 201,
"timestamp": "2025-11-14T12:00:00Z",
"result": {
"user": {
"id": "user_abc123",
"email": "hero@example.com",
"name": "Brave Adventurer",
"email_verified": false,
"tier": "free",
"created_at": "2025-11-14T12:00:00Z",
"updated_at": "2025-11-14T12:00:00Z"
},
"message": "Registration successful. Please check your email to verify your account."
}
}
Error Response (400 Bad Request - Email exists):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 400,
"timestamp": "2025-11-14T12:00:00Z",
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid input data",
"details": {
"email": "An account with this email already exists"
}
}
}
Error Response (400 Bad Request - Weak password):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 400,
"timestamp": "2025-11-14T12:00:00Z",
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid input data",
"details": {
"password": "Password must contain at least one uppercase letter, at least one number, at least one special character"
}
}
}
2. Login User
Endpoint: POST /api/v1/auth/login
Description: Authenticate user and create session. Sets HTTP-only cookie.
Request:
# httpie (with cookie jar)
http --session=user1 POST localhost:5000/api/v1/auth/login \
email="hero@example.com" \
password="SecurePass123!" \
remember_me:=false
# curl (save cookies)
curl -X POST http://localhost:5000/api/v1/auth/login \
-H "Content-Type: application/json" \
-c cookies.txt \
-d '{
"email": "hero@example.com",
"password": "SecurePass123!",
"remember_me": false
}'
Success Response (200 OK):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 200,
"timestamp": "2025-11-14T12:00:00Z",
"result": {
"user": {
"id": "user_abc123",
"email": "hero@example.com",
"name": "Brave Adventurer",
"email_verified": true,
"tier": "free"
},
"message": "Login successful"
}
}
Set-Cookie Header:
Set-Cookie: coc_session=session_xyz789; HttpOnly; Path=/; SameSite=Lax; Max-Age=86400
Error Response (401 Unauthorized):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 401,
"timestamp": "2025-11-14T12:00:00Z",
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid email or password"
}
}
3. Logout User
Endpoint: POST /api/v1/auth/logout
Description: Delete user session and clear cookie. Requires authentication.
Request:
# httpie (with saved session)
http --session=user1 POST localhost:5000/api/v1/auth/logout
# curl (with saved cookies)
curl -X POST http://localhost:5000/api/v1/auth/logout \
-b cookies.txt \
-c cookies.txt
Success Response (200 OK):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 200,
"timestamp": "2025-11-14T12:00:00Z",
"result": {
"message": "Logout successful"
}
}
Set-Cookie Header (clears cookie):
Set-Cookie: coc_session=; HttpOnly; Path=/; SameSite=Lax; Max-Age=0
Error Response (401 Unauthorized - Not logged in):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 401,
"timestamp": "2025-11-14T12:00:00Z",
"error": {
"code": "UNAUTHORIZED",
"message": "Authentication required. Please log in."
}
}
4. Verify Email
Endpoint: GET /api/v1/auth/verify-email?userId=XXX&secret=YYY
Description: Verify user's email address. Called from link in verification email.
Request:
# httpie
http GET "localhost:5000/api/v1/auth/verify-email?userId=user_abc123&secret=verification_secret_xyz"
# curl
curl "http://localhost:5000/api/v1/auth/verify-email?userId=user_abc123&secret=verification_secret_xyz"
Success Response:
Redirects to /auth/login with success flash message.
Error Response:
Redirects to /auth/login with error flash message.
5. Request Password Reset
Endpoint: POST /api/v1/auth/forgot-password
Description: Request password reset email. Always returns success for security.
Request:
# httpie
http POST localhost:5000/api/v1/auth/forgot-password \
email="hero@example.com"
# curl
curl -X POST http://localhost:5000/api/v1/auth/forgot-password \
-H "Content-Type: application/json" \
-d '{"email": "hero@example.com"}'
Success Response (200 OK):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 200,
"timestamp": "2025-11-14T12:00:00Z",
"result": {
"message": "If an account exists with this email, you will receive a password reset link shortly."
}
}
Note: Response is always the same, regardless of whether the email exists (security best practice).
6. Reset Password
Endpoint: POST /api/v1/auth/reset-password
Description: Confirm password reset with new password. Requires userId and secret from email link.
Request:
# httpie
http POST localhost:5000/api/v1/auth/reset-password \
user_id="user_abc123" \
secret="reset_secret_xyz" \
password="NewSecurePass123!"
# curl
curl -X POST http://localhost:5000/api/v1/auth/reset-password \
-H "Content-Type: application/json" \
-d '{
"user_id": "user_abc123",
"secret": "reset_secret_xyz",
"password": "NewSecurePass123!"
}'
Success Response (200 OK):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 200,
"timestamp": "2025-11-14T12:00:00Z",
"result": {
"message": "Password reset successful. You can now log in with your new password."
}
}
Error Response (400 Bad Request - Invalid/expired link):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 400,
"timestamp": "2025-11-14T12:00:00Z",
"error": {
"code": "PASSWORD_RESET_ERROR",
"message": "Password reset failed. The link may be invalid or expired."
}
}
Character Endpoints
1. Get User's Characters
Endpoint: GET /api/v1/characters
Description: Retrieve all characters belonging to the authenticated user.
Request:
# httpie (with saved session)
http --session=user1 GET localhost:5000/api/v1/characters
# curl (with saved cookies)
curl http://localhost:5000/api/v1/characters -b cookies.txt
Success Response (200 OK):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 200,
"timestamp": "2025-11-15T12:00:00Z",
"result": {
"characters": [
{
"character_id": "char_123",
"name": "Thorin Ironforge",
"class": "vanguard",
"class_name": "Vanguard",
"level": 5,
"experience": 2400,
"gold": 150,
"current_location": "forgotten_crypt",
"origin": "soul_revenant"
}
],
"count": 1,
"tier": "free",
"limit": 1
}
}
Error Response (401 Unauthorized):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 401,
"timestamp": "2025-11-14T12:00:00Z",
"error": {
"code": "UNAUTHORIZED",
"message": "Authentication required. Please log in."
}
}
2. Get Single Character
Endpoint: GET /api/v1/characters/<character_id>
Description: Retrieve detailed information for a specific character. Returns full character data including class, origin, stats, skills, inventory, and equipment.
Request:
# httpie
http --session=user1 GET localhost:5000/api/v1/characters/char_123
# curl
curl http://localhost:5000/api/v1/characters/char_123 -b cookies.txt
Success Response (200 OK):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 200,
"timestamp": "2025-11-15T12:00:00Z",
"result": {
"character_id": "char_123",
"user_id": "user_abc123",
"name": "Thorin Ironforge",
"player_class": {
"class_id": "vanguard",
"name": "Vanguard",
"description": "Armored warriors who excel in melee combat...",
"base_stats": {
"strength": 14,
"dexterity": 10,
"constitution": 14,
"intelligence": 8,
"wisdom": 10,
"charisma": 9
},
"skill_trees": [...],
"starting_equipment": ["Rusty Sword", "Tattered Cloth Armor"],
"starting_abilities": []
},
"origin": {
"id": "soul_revenant",
"name": "The Soul Revenant",
"description": "You died. That much you remember...",
"starting_location": {
"id": "forgotten_crypt",
"name": "The Forgotten Crypt",
"description": "A crumbling stone tomb..."
},
"narrative_hooks": [...],
"starting_bonus": {
"type": "stat",
"value": {"constitution": 1}
}
},
"level": 5,
"experience": 2400,
"base_stats": {
"strength": 16,
"dexterity": 10,
"constitution": 14,
"intelligence": 8,
"wisdom": 12,
"charisma": 10
},
"unlocked_skills": ["shield_wall", "toughness"],
"inventory": [],
"equipped": {},
"gold": 150,
"active_quests": [],
"discovered_locations": ["forgotten_crypt"],
"current_location": "forgotten_crypt"
}
}
Error Response (404 Not Found):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 404,
"timestamp": "2025-11-14T12:00:00Z",
"error": {
"code": "CHARACTER_NOT_FOUND",
"message": "Character not found or you do not have access to it"
}
}
3. Create Character
Endpoint: POST /api/v1/characters
Description: Create a new character. Subject to tier limits (Free: 1, Basic: 3, Premium: 5, Elite: 10).
Valid class_id values: vanguard, assassin, arcanist, luminary, wildstrider, oathkeeper, necromancer, lorekeeper
Valid origin_id values: soul_revenant, memory_thief, shadow_apprentice, escaped_captive
Request:
# httpie
http --session=user1 POST localhost:5000/api/v1/characters \
name="Elara Moonwhisper" \
class_id="arcanist" \
origin_id="memory_thief"
# curl
curl -X POST http://localhost:5000/api/v1/characters \
-H "Content-Type: application/json" \
-b cookies.txt \
-d '{
"name": "Elara Moonwhisper",
"class_id": "arcanist",
"origin_id": "memory_thief"
}'
Success Response (201 Created):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 201,
"timestamp": "2025-11-15T12:00:00Z",
"result": {
"character_id": "char_456",
"name": "Elara Moonwhisper",
"class": "arcanist",
"class_name": "Arcanist",
"origin": "memory_thief",
"origin_name": "The Memory Thief",
"level": 1,
"gold": 0,
"current_location": "thornfield_plains",
"message": "Character created successfully"
}
}
Error Response (400 Bad Request - Character limit exceeded):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 400,
"timestamp": "2025-11-14T12:00:00Z",
"error": {
"code": "CHARACTER_LIMIT_EXCEEDED",
"message": "You have reached your character limit for your tier (Free: 1 character)"
}
}
Error Response (400 Bad Request - Invalid name):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 400,
"timestamp": "2025-11-14T12:00:00Z",
"error": {
"code": "INVALID_INPUT",
"message": "Character name must be between 2 and 50 characters and contain only letters, numbers, spaces, hyphens, and apostrophes"
}
}
4. Delete Character
Endpoint: DELETE /api/v1/characters/<character_id>
Description: Permanently delete a character from the database. Also cleans up all associated game sessions to prevent orphaned data.
Request:
# httpie
http --session=user1 DELETE localhost:5000/api/v1/characters/char_456
# curl
curl -X DELETE http://localhost:5000/api/v1/characters/char_456 \
-b cookies.txt
Success Response (200 OK):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 200,
"timestamp": "2025-11-14T12:00:00Z",
"result": {
"message": "Character deleted successfully"
}
}
Error Response (404 Not Found):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 404,
"timestamp": "2025-11-14T12:00:00Z",
"error": {
"code": "CHARACTER_NOT_FOUND",
"message": "Character not found or you do not have access to it"
}
}
5. Unlock Skill
Endpoint: POST /api/v1/characters/<character_id>/skills/unlock
Description: Unlock a skill for a character. Validates prerequisites, skill points, and tier requirements. Requires 1 skill point (gained per level).
Request:
# httpie
http --session=user1 POST localhost:5000/api/v1/characters/char_123/skills/unlock \
skill_id="shield_wall"
# curl
curl -X POST http://localhost:5000/api/v1/characters/char_123/skills/unlock \
-H "Content-Type: application/json" \
-b cookies.txt \
-d '{
"skill_id": "shield_wall"
}'
Success Response (200 OK):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 200,
"timestamp": "2025-11-15T12:00:00Z",
"result": {
"message": "Skill unlocked successfully",
"character_id": "char_123",
"skill_id": "shield_wall",
"unlocked_skills": ["shield_wall"],
"available_points": 0
}
}
Error Response (400 Bad Request - Prerequisites not met):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 400,
"timestamp": "2025-11-14T12:00:00Z",
"error": {
"code": "SKILL_UNLOCK_ERROR",
"message": "Cannot unlock skill: Prerequisites not met (requires: shield_bash)"
}
}
Error Response (400 Bad Request - Insufficient skill points):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 400,
"timestamp": "2025-11-14T12:00:00Z",
"error": {
"code": "SKILL_UNLOCK_ERROR",
"message": "Cannot unlock skill: Insufficient skill points (requires: 1, available: 0)"
}
}
6. Respec Skills
Endpoint: POST /api/v1/characters/<character_id>/skills/respec
Description: Reset all unlocked skills and refund skill points. Costs gold (level × 100 gold).
Request:
# httpie
http --session=user1 POST localhost:5000/api/v1/characters/char_123/skills/respec
# curl
curl -X POST http://localhost:5000/api/v1/characters/char_123/skills/respec \
-b cookies.txt
Success Response (200 OK):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 200,
"timestamp": "2025-11-15T12:00:00Z",
"result": {
"message": "Skills reset successfully",
"character_id": "char_123",
"cost": 500,
"remaining_gold": 100,
"available_points": 5
}
}
Error Response (400 Bad Request - Insufficient gold):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 400,
"timestamp": "2025-11-15T12:00:00Z",
"error": {
"code": "INSUFFICIENT_GOLD",
"message": "Insufficient gold for respec. Cost: 500, Available: 100"
}
}
7. Get Character Classes
Endpoint: GET /api/v1/classes
Description: Get all available character classes (8 total). No authentication required. Used for character creation UI.
Request:
# httpie
http GET localhost:5000/api/v1/classes
# curl
curl http://localhost:5000/api/v1/classes
Success Response (200 OK):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 200,
"timestamp": "2025-11-15T12:00:00Z",
"result": {
"classes": [
{
"class_id": "vanguard",
"name": "Vanguard",
"description": "Armored warriors who excel in melee combat and protecting allies",
"base_stats": {
"strength": 14,
"dexterity": 10,
"constitution": 14,
"intelligence": 8,
"wisdom": 10,
"charisma": 9
},
"skill_trees": ["Shield Bearer", "Weapon Master"],
"starting_equipment": ["Rusty Sword", "Tattered Cloth Armor"],
"starting_abilities": []
},
{
"class_id": "arcanist",
"name": "Arcanist",
"description": "Masters of elemental magic, wielding fire and ice",
"base_stats": {
"strength": 8,
"dexterity": 10,
"constitution": 9,
"intelligence": 15,
"wisdom": 12,
"charisma": 11
},
"skill_trees": ["Pyromancy", "Cryomancy"],
"starting_equipment": ["Worn Staff", "Tattered Cloth Armor"],
"starting_abilities": []
}
],
"count": 8
}
}
Note: Response includes all 8 classes: vanguard, assassin, arcanist, luminary, wildstrider, oathkeeper, necromancer, lorekeeper
8. Get Single Character Class
Endpoint: GET /api/v1/classes/<class_id>
Description: Get detailed information about a specific character class including full skill trees. No authentication required. Returns complete skill tree data with 20 skills (2 trees × 5 tiers × 2 nodes).
Request:
# httpie
http GET localhost:5000/api/v1/classes/vanguard
# curl
curl http://localhost:5000/api/v1/classes/vanguard
Success Response (200 OK):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 200,
"timestamp": "2025-11-15T12:00:00Z",
"result": {
"class_id": "vanguard",
"name": "Vanguard",
"description": "Armored warriors who excel in melee combat and protecting allies",
"base_stats": {
"strength": 14,
"dexterity": 10,
"constitution": 14,
"intelligence": 8,
"wisdom": 10,
"charisma": 9
},
"skill_trees": [
{
"tree_id": "shield_bearer",
"name": "Shield Bearer",
"description": "Defensive techniques and shield mastery",
"nodes": [
{
"skill_id": "shield_wall",
"name": "Shield Wall",
"description": "Increase armor by 5",
"tier": 1,
"prerequisites": [],
"effects": [{"type": "stat", "stat": "armor", "value": 5}]
}
]
},
{
"tree_id": "weapon_master",
"name": "Weapon Master",
"description": "Offensive prowess and weapon techniques",
"nodes": [...]
}
],
"starting_equipment": ["Rusty Sword", "Tattered Cloth Armor"],
"starting_abilities": []
}
}
Error Response (404 Not Found):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 404,
"timestamp": "2025-11-15T12:00:00Z",
"error": {
"code": "NOT_FOUND",
"message": "Class not found: warrior"
}
}
9. Get Character Origins
Endpoint: GET /api/v1/origins
Description: Get all available character origins (4 total). No authentication required. Used for character creation UI. Origins provide narrative backstory and starting location.
Request:
# httpie
http GET localhost:5000/api/v1/origins
# curl
curl http://localhost:5000/api/v1/origins
Success Response (200 OK):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 200,
"timestamp": "2025-11-15T12:00:00Z",
"result": {
"origins": [
{
"id": "soul_revenant",
"name": "The Soul Revenant",
"description": "You died. That much you remember. The cold embrace of death, the fading light, the silence. But something—or someone—pulled you back...",
"starting_location": {
"id": "forgotten_crypt",
"name": "The Forgotten Crypt",
"description": "A crumbling stone tomb beneath a dead forest..."
},
"narrative_hooks": [
"Who or what brought you back from death?",
"What life did you lead before your demise?",
"Do fragments of past lives haunt your dreams?"
],
"starting_bonus": {
"type": "stat",
"value": {"constitution": 1}
}
},
{
"id": "memory_thief",
"name": "The Memory Thief",
"description": "You awaken with fragments of memories that aren't yours...",
"starting_location": {
"id": "thornfield_plains",
"name": "Thornfield Plains",
"description": "Endless grasslands dotted with ancient ruins..."
},
"narrative_hooks": [
"Whose memories do you carry?",
"Why were these memories stolen?"
],
"starting_bonus": {
"type": "stat",
"value": {"intelligence": 1}
}
}
],
"count": 4
}
}
Note: Response includes all 4 origins: soul_revenant, memory_thief, shadow_apprentice, escaped_captive
Game Mechanics Endpoints
1. Perform Skill Check
Endpoint: POST /api/v1/game/check
Description: Perform a skill check (persuasion, stealth, perception, etc.) and get deterministic dice roll results. The result includes all dice roll details for UI display and can be passed to AI for narrative description.
Request (Skill Check - Persuasion):
# httpie
http --session=user1 POST localhost:5000/api/v1/game/check \
character_id="char_123" \
check_type="skill" \
skill="persuasion" \
dc:=15 \
bonus:=2 \
context:='{"npc_name": "Guard Captain"}'
# curl
curl -X POST http://localhost:5000/api/v1/game/check \
-H "Content-Type: application/json" \
-b cookies.txt \
-d '{
"character_id": "char_123",
"check_type": "skill",
"skill": "persuasion",
"dc": 15,
"bonus": 2,
"context": {"npc_name": "Guard Captain"}
}'
Success Response (200 OK - Skill Check Passes):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 200,
"timestamp": "2025-11-23T10:30:00Z",
"result": {
"check_result": {
"roll": 16,
"modifier": 3,
"total": 19,
"dc": 15,
"success": true,
"margin": 4,
"skill_type": "persuasion"
},
"context": {
"skill_used": "persuasion",
"stat_used": "charisma",
"npc_name": "Guard Captain"
}
}
}
Success Response (200 OK - Skill Check Fails):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 200,
"timestamp": "2025-11-23T10:30:00Z",
"result": {
"check_result": {
"roll": 7,
"modifier": 1,
"total": 8,
"dc": 15,
"success": false,
"margin": -7,
"skill_type": "stealth"
},
"context": {
"skill_used": "stealth",
"stat_used": "dexterity",
"situation": "Sneaking past guards"
}
}
}
2. Perform Search Action
Endpoint: POST /api/v1/game/check
Description: Perform a search action in a location and get items/gold based on perception check result.
Request (Search in Forest):
# httpie
http --session=user1 POST localhost:5000/api/v1/game/check \
character_id="char_123" \
check_type="search" \
location_type="forest" \
difficulty="medium" \
bonus:=0
# curl
curl -X POST http://localhost:5000/api/v1/game/check \
-H "Content-Type: application/json" \
-b cookies.txt \
-d '{
"character_id": "char_123",
"check_type": "search",
"location_type": "forest",
"difficulty": "medium",
"bonus": 0
}'
Success Response (200 OK - Search Succeeds):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 200,
"timestamp": "2025-11-23T10:30:00Z",
"result": {
"check_result": {
"roll": 18,
"modifier": 2,
"total": 20,
"dc": 15,
"success": true,
"margin": 5,
"skill_type": "perception"
},
"items_found": [
{
"template_key": "ancient_coin",
"name": "Ancient Coin",
"description": "A weathered coin from ages past",
"value": 25
},
{
"template_key": "healing_herb",
"name": "Healing Herb",
"description": "A medicinal plant bundle",
"value": 10
}
],
"gold_found": 12
}
}
Success Response (200 OK - Search Fails):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 200,
"timestamp": "2025-11-23T10:30:00Z",
"result": {
"check_result": {
"roll": 4,
"modifier": 2,
"total": 6,
"dc": 15,
"success": false,
"margin": -9,
"skill_type": "perception"
},
"items_found": [],
"gold_found": 0
}
}
3. Get Available Skills
Endpoint: GET /api/v1/game/skills
Description: Get all available skill types and their associated stats. Used to populate skill selection UI.
Request:
# httpie
http GET localhost:5000/api/v1/game/skills
# curl
curl http://localhost:5000/api/v1/game/skills
Success Response (200 OK):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 200,
"timestamp": "2025-11-23T10:30:00Z",
"result": {
"skills": [
{
"name": "perception",
"stat": "wisdom"
},
{
"name": "stealth",
"stat": "dexterity"
},
{
"name": "persuasion",
"stat": "charisma"
},
{
"name": "intimidation",
"stat": "charisma"
},
{
"name": "deception",
"stat": "charisma"
},
{
"name": "lockpicking",
"stat": "dexterity"
},
{
"name": "athletics",
"stat": "strength"
},
{
"name": "acrobatics",
"stat": "dexterity"
},
{
"name": "sleight_of_hand",
"stat": "dexterity"
},
{
"name": "arcana",
"stat": "intelligence"
},
{
"name": "history",
"stat": "intelligence"
},
{
"name": "investigation",
"stat": "intelligence"
},
{
"name": "nature",
"stat": "intelligence"
},
{
"name": "religion",
"stat": "intelligence"
},
{
"name": "insight",
"stat": "wisdom"
},
{
"name": "survival",
"stat": "wisdom"
},
{
"name": "medicine",
"stat": "wisdom"
},
{
"name": "performance",
"stat": "charisma"
},
{
"name": "endurance",
"stat": "constitution"
}
]
}
}
4. Get Difficulty Levels
Endpoint: GET /api/v1/game/difficulties
Description: Get all difficulty levels and their corresponding DC values. Used to help set appropriate check difficulties.
Request:
# httpie
http GET localhost:5000/api/v1/game/difficulties
# curl
curl http://localhost:5000/api/v1/game/difficulties
Success Response (200 OK):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 200,
"timestamp": "2025-11-23T10:30:00Z",
"result": {
"difficulties": [
{
"name": "trivial",
"dc": 5
},
{
"name": "easy",
"dc": 10
},
{
"name": "medium",
"dc": 15
},
{
"name": "hard",
"dc": 20
},
{
"name": "very_hard",
"dc": 25
},
{
"name": "nearly_impossible",
"dc": 30
}
]
}
}
9. Get Character Origins
Endpoint: GET /api/v1/origins
Description: Get all available character origins (4 total). No authentication required. Used for character creation UI. Origins provide narrative backstory and starting location.
Request:
# httpie
http GET localhost:5000/api/v1/origins
# curl
curl http://localhost:5000/api/v1/origins
Success Response (200 OK):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 200,
"timestamp": "2025-11-15T12:00:00Z",
"result": {
"origins": [
{
"id": "soul_revenant",
"name": "The Soul Revenant",
"description": "You died. That much you remember. The cold embrace of death, the fading light, the silence. But something—or someone—pulled you back...",
"starting_location": {
"id": "forgotten_crypt",
"name": "The Forgotten Crypt",
"description": "A crumbling stone tomb beneath a dead forest..."
},
"narrative_hooks": [
"Who or what brought you back from death?",
"What life did you lead before your demise?",
"Do fragments of past lives haunt your dreams?"
],
"starting_bonus": {
"type": "stat",
"value": {"constitution": 1}
}
},
{
"id": "memory_thief",
"name": "The Memory Thief",
"description": "You awaken with fragments of memories that aren't yours...",
"starting_location": {
"id": "thornfield_plains",
"name": "Thornfield Plains",
"description": "Endless grasslands dotted with ancient ruins..."
},
"narrative_hooks": [
"Whose memories do you carry?",
"Why were these memories stolen?"
],
"starting_bonus": {
"type": "stat",
"value": {"intelligence": 1}
}
}
],
"count": 4
}
}
Note: Response includes all 4 origins: soul_revenant, memory_thief, shadow_apprentice, escaped_captive
Session Endpoints
1. Create Session
Endpoint: POST /api/v1/sessions
Description: Create a new game session for a character. Subject to tier-based limits (Free: 1, Basic: 2, Premium: 3, Elite: 5).
Request:
# httpie
http --session=user1 POST localhost:5000/api/v1/sessions \
character_id="char_123"
# curl
curl -X POST http://localhost:5000/api/v1/sessions \
-H "Content-Type: application/json" \
-b cookies.txt \
-d '{
"character_id": "char_123"
}'
Success Response (201 Created):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 201,
"timestamp": "2025-11-26T10:30:00Z",
"result": {
"session_id": "sess_789",
"character_id": "char_123",
"turn_number": 0,
"game_state": {
"current_location": "crossville_village",
"location_type": "town",
"active_quests": []
}
}
}
Error Response (409 Conflict - Session Limit Exceeded):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 409,
"timestamp": "2025-11-26T10:30:00Z",
"error": {
"code": "SESSION_LIMIT_EXCEEDED",
"message": "Maximum active sessions reached for free tier (1/1). Please delete an existing session to start a new one."
}
}
2. List Sessions
Endpoint: GET /api/v1/sessions
Description: Get all active sessions for the authenticated user.
Request:
# httpie
http --session=user1 GET localhost:5000/api/v1/sessions
# curl
curl http://localhost:5000/api/v1/sessions -b cookies.txt
Success Response (200 OK):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 200,
"timestamp": "2025-11-26T10:30:00Z",
"result": [
{
"session_id": "sess_789",
"character_id": "char_123",
"turn_number": 5,
"status": "active",
"created_at": "2025-11-26T10:00:00Z",
"last_activity": "2025-11-26T10:25:00Z",
"game_state": {
"current_location": "crossville_village",
"location_type": "town"
}
}
]
}
3. Delete Session
Endpoint: DELETE /api/v1/sessions/<session_id>
Description: Permanently delete a session and all associated chat messages. This frees up a session slot for your tier limit.
Request:
# httpie
http --session=user1 DELETE localhost:5000/api/v1/sessions/sess_789
# curl
curl -X DELETE http://localhost:5000/api/v1/sessions/sess_789 \
-b cookies.txt
Success Response (200 OK):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 200,
"timestamp": "2025-11-26T10:30:00Z",
"result": {
"message": "Session deleted successfully",
"session_id": "sess_789"
}
}
Error Response (404 Not Found):
{
"app": "Code of Conquest",
"version": "0.1.0",
"status": 404,
"timestamp": "2025-11-26T10:30:00Z",
"error": {
"code": "NOT_FOUND",
"message": "Session not found"
}
}
Note: Deleting a session:
- Permanently removes the session from the database
- Deletes all chat messages associated with the session
- Cannot be undone
- Frees up a session slot for your tier limit
Testing Workflows
Complete Registration Flow
-
Register new user:
http POST localhost:5000/api/v1/auth/register \ email="newuser@example.com" \ password="SecurePass123!" \ name="New User" -
Check email for verification link
- Look for email from Appwrite
- Extract
userIdandsecretfrom verification URL
-
Verify email:
http GET "localhost:5000/api/v1/auth/verify-email?userId=XXX&secret=YYY" -
Login:
http --session=newuser POST localhost:5000/api/v1/auth/login \ email="newuser@example.com" \ password="SecurePass123!" \ remember_me:=false -
Verify session is active:
- Session cookie should be set
- Can now access protected routes
Complete Password Reset Flow
-
Request password reset:
http POST localhost:5000/api/v1/auth/forgot-password \ email="hero@example.com" -
Check email for reset link
- Look for email from Appwrite
- Extract
userIdandsecretfrom reset URL
-
Reset password:
http POST localhost:5000/api/v1/auth/reset-password \ user_id="XXX" \ secret="YYY" \ password="NewSecurePass123!" -
Login with new password:
http --session=user1 POST localhost:5000/api/v1/auth/login \ email="hero@example.com" \ password="NewSecurePass123!" \ remember_me:=false
Testing Protected Routes
Protected routes require authentication. Test with and without session cookies.
Without authentication:
# Should return 401 Unauthorized
http POST localhost:5000/api/v1/auth/logout
With authentication:
# Login first
http --session=user1 POST localhost:5000/api/v1/auth/login \
email="hero@example.com" \
password="SecurePass123!"
# Now can access protected route
http --session=user1 POST localhost:5000/api/v1/auth/logout
Complete Character Creation and Management Flow
-
Login first (required):
http --session=user1 POST localhost:5000/api/v1/auth/login \ email="hero@example.com" \ password="SecurePass123!" -
Browse available classes:
http GET localhost:5000/api/v1/classes -
Browse available origins:
http GET localhost:5000/api/v1/origins -
Create a new character:
http --session=user1 POST localhost:5000/api/v1/characters \ name="Thorin Ironforge" \ class_id="vanguard" \ origin_id="soul_revenant" -
View all your characters:
http --session=user1 GET localhost:5000/api/v1/characters -
View character details (replace char_123 with actual character_id from step 4):
http --session=user1 GET localhost:5000/api/v1/characters/char_123 -
Unlock a skill (when character has skill points from leveling):
http --session=user1 POST localhost:5000/api/v1/characters/char_123/skills/unlock \ skill_id="shield_wall" -
Respec skills (when needed, costs level × 100 gold):
http --session=user1 POST localhost:5000/api/v1/characters/char_123/skills/respec -
Delete a character:
http --session=user1 DELETE localhost:5000/api/v1/characters/char_123
Common Errors
400 Bad Request - Validation Error
Cause: Invalid input data (email format, weak password, etc.)
Example:
{
"status": 400,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid input data",
"details": {
"email": "Invalid email format",
"password": "Password must be at least 8 characters long"
}
}
}
Fix: Check input validation requirements in error details.
401 Unauthorized
Cause: Not authenticated or invalid session.
Example:
{
"status": 401,
"error": {
"code": "UNAUTHORIZED",
"message": "Authentication required. Please log in."
}
}
Fix: Login first and include session cookie with requests.
409 Conflict - User Already Exists
Cause: Email already registered.
Example:
{
"status": 400,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid input data",
"details": {
"email": "An account with this email already exists"
}
}
}
Fix: Use a different email or login instead.
500 Internal Server Error
Cause: Server error (Appwrite connection, configuration issue, etc.)
Example:
{
"status": 500,
"error": {
"code": "INTERNAL_ERROR",
"message": "An internal error occurred. Please try again later."
}
}
Fix: Check server logs, verify Appwrite credentials, check network connectivity.
Testing Tips
Using httpie Sessions
httpie sessions persist cookies automatically:
# Login (saves cookies)
http --session=user1 POST localhost:5000/api/v1/auth/login \
email="hero@example.com" \
password="SecurePass123!"
# Subsequent requests automatically include cookies
http --session=user1 POST localhost:5000/api/v1/auth/logout
Using curl Cookie Jar
# Login (save cookies)
curl -X POST http://localhost:5000/api/v1/auth/login \
-H "Content-Type: application/json" \
-c cookies.txt \
-d '{"email": "hero@example.com", "password": "SecurePass123!"}'
# Use cookies in next request
curl -X POST http://localhost:5000/api/v1/auth/logout \
-b cookies.txt
Pretty Print JSON
# httpie (automatic)
http POST localhost:5000/api/v1/auth/register ...
# curl (with jq)
curl ... | jq .
Verbose Output
# httpie
http -v POST localhost:5000/api/v1/auth/login ...
# curl
curl -v -X POST http://localhost:5000/api/v1/auth/login ...
Complete Testing Workflow with Game Mechanics
Here's an end-to-end workflow including skill checks and searches:
1. Setup (One-time)
# Register a new user
http POST localhost:5000/api/v1/auth/register \
email="adventurer@example.com" \
password="SecurePass123!" \
name="Brave Adventurer"
# Login and save session
http --session=adventurer POST localhost:5000/api/v1/auth/login \
email="adventurer@example.com" \
password="SecurePass123!" \
remember_me:=false
2. Create Character
# Create a character
http --session=adventurer POST localhost:5000/api/v1/characters \
name="Elara Moonwhisper" \
class_id="arcanist" \
origin_id="memory_thief"
# Save the character_id from the response
3. Get Available Skills and Difficulties
# Get available skills (before performing checks)
http GET localhost:5000/api/v1/game/skills
# Get difficulty levels
http GET localhost:5000/api/v1/game/difficulties
4. Perform Skill Checks
# Attempt persuasion check (charisma-based)
http --session=adventurer POST localhost:5000/api/v1/game/check \
character_id="<your_character_id>" \
check_type="skill" \
skill="persuasion" \
difficulty="hard" \
bonus:=1 \
context:='{"npc_name": "Merchant"}'
# Attempt stealth check (dexterity-based)
http --session=adventurer POST localhost:5000/api/v1/game/check \
character_id="<your_character_id>" \
check_type="skill" \
skill="stealth" \
dc:=20 \
bonus:=0
# Attempt arcana check (intelligence-based)
http --session=adventurer POST localhost:5000/api/v1/game/check \
character_id="<your_character_id>" \
check_type="skill" \
skill="arcana" \
difficulty="medium" \
bonus:=2
5. Perform Searches
# Search in a forest
http --session=adventurer POST localhost:5000/api/v1/game/check \
character_id="<your_character_id>" \
check_type="search" \
location_type="forest" \
difficulty="easy" \
bonus:=0
# Search in a cave
http --session=adventurer POST localhost:5000/api/v1/game/check \
character_id="<your_character_id>" \
check_type="search" \
location_type="cave" \
dc:=13 \
bonus:=1
# Search in a town
http --session=adventurer POST localhost:5000/api/v1/game/check \
character_id="<your_character_id>" \
check_type="search" \
location_type="town" \
difficulty="hard" \
bonus:=2
Next Steps
As additional API endpoints are implemented, they will be documented here with:
- Endpoint description
- Request examples (httpie and curl)
- Response examples (success and error cases)
- Testing workflows
Implemented endpoints:
- ✅ Authentication (
/api/v1/auth) - ✅ Character management (
/api/v1/characters) - ✅ Classes and Origins (
/api/v1/classes,/api/v1/origins) - ✅ Game Mechanics - Skill Checks and Searches (
/api/v1/game/check) - ✅ Game Mechanics - Skills and Difficulties Lists (
/api/v1/game/skills,/api/v1/game/difficulties)
Upcoming endpoints:
- Game sessions (
/api/v1/sessions) - Combat (
/api/v1/combat) - Marketplace (
/api/v1/marketplace) - Shop (
/api/v1/shop)
Document Version: 0.3.0 Created: November 14, 2025 Last Updated: November 23, 2025