1865 lines
39 KiB
Markdown
1865 lines
39 KiB
Markdown
# 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
|
||
|
||
1. [Setup](#setup)
|
||
2. [Authentication Endpoints](#authentication-endpoints)
|
||
3. [Character Endpoints](#character-endpoints)
|
||
4. [Testing Workflows](#testing-workflows)
|
||
5. [Common Errors](#common-errors)
|
||
|
||
---
|
||
|
||
## Setup
|
||
|
||
### Prerequisites
|
||
|
||
- **httpie** (recommended) or **curl**
|
||
- Flask app running locally (default: `http://localhost:5000`)
|
||
- Appwrite configured with valid credentials in `.env`
|
||
|
||
### Install httpie
|
||
|
||
```bash
|
||
# macOS
|
||
brew install httpie
|
||
|
||
# Ubuntu/Debian
|
||
apt-get install httpie
|
||
|
||
# Python pip
|
||
pip install httpie
|
||
```
|
||
|
||
### Start the Application
|
||
|
||
```bash
|
||
# 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:**
|
||
|
||
```bash
|
||
# 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):**
|
||
|
||
```json
|
||
{
|
||
"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):**
|
||
|
||
```json
|
||
{
|
||
"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):**
|
||
|
||
```json
|
||
{
|
||
"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:**
|
||
|
||
```bash
|
||
# 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):**
|
||
|
||
```json
|
||
{
|
||
"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):**
|
||
|
||
```json
|
||
{
|
||
"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:**
|
||
|
||
```bash
|
||
# 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):**
|
||
|
||
```json
|
||
{
|
||
"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):**
|
||
|
||
```json
|
||
{
|
||
"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:**
|
||
|
||
```bash
|
||
# 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:**
|
||
|
||
```bash
|
||
# 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):**
|
||
|
||
```json
|
||
{
|
||
"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:**
|
||
|
||
```bash
|
||
# 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):**
|
||
|
||
```json
|
||
{
|
||
"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):**
|
||
|
||
```json
|
||
{
|
||
"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:**
|
||
|
||
```bash
|
||
# 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):**
|
||
|
||
```json
|
||
{
|
||
"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):**
|
||
|
||
```json
|
||
{
|
||
"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:**
|
||
|
||
```bash
|
||
# 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):**
|
||
|
||
```json
|
||
{
|
||
"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):**
|
||
|
||
```json
|
||
{
|
||
"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:**
|
||
|
||
```bash
|
||
# 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):**
|
||
|
||
```json
|
||
{
|
||
"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):**
|
||
|
||
```json
|
||
{
|
||
"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):**
|
||
|
||
```json
|
||
{
|
||
"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:** Soft-delete a character (marks as inactive rather than removing).
|
||
|
||
**Request:**
|
||
|
||
```bash
|
||
# 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):**
|
||
|
||
```json
|
||
{
|
||
"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):**
|
||
|
||
```json
|
||
{
|
||
"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:**
|
||
|
||
```bash
|
||
# 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):**
|
||
|
||
```json
|
||
{
|
||
"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):**
|
||
|
||
```json
|
||
{
|
||
"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):**
|
||
|
||
```json
|
||
{
|
||
"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:**
|
||
|
||
```bash
|
||
# 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):**
|
||
|
||
```json
|
||
{
|
||
"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):**
|
||
|
||
```json
|
||
{
|
||
"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:**
|
||
|
||
```bash
|
||
# httpie
|
||
http GET localhost:5000/api/v1/classes
|
||
|
||
# curl
|
||
curl http://localhost:5000/api/v1/classes
|
||
```
|
||
|
||
**Success Response (200 OK):**
|
||
|
||
```json
|
||
{
|
||
"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:**
|
||
|
||
```bash
|
||
# httpie
|
||
http GET localhost:5000/api/v1/classes/vanguard
|
||
|
||
# curl
|
||
curl http://localhost:5000/api/v1/classes/vanguard
|
||
```
|
||
|
||
**Success Response (200 OK):**
|
||
|
||
```json
|
||
{
|
||
"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):**
|
||
|
||
```json
|
||
{
|
||
"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:**
|
||
|
||
```bash
|
||
# httpie
|
||
http GET localhost:5000/api/v1/origins
|
||
|
||
# curl
|
||
curl http://localhost:5000/api/v1/origins
|
||
```
|
||
|
||
**Success Response (200 OK):**
|
||
|
||
```json
|
||
{
|
||
"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):**
|
||
|
||
```bash
|
||
# 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):**
|
||
|
||
```json
|
||
{
|
||
"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):**
|
||
|
||
```json
|
||
{
|
||
"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):**
|
||
|
||
```bash
|
||
# 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):**
|
||
|
||
```json
|
||
{
|
||
"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):**
|
||
|
||
```json
|
||
{
|
||
"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:**
|
||
|
||
```bash
|
||
# httpie
|
||
http GET localhost:5000/api/v1/game/skills
|
||
|
||
# curl
|
||
curl http://localhost:5000/api/v1/game/skills
|
||
```
|
||
|
||
**Success Response (200 OK):**
|
||
|
||
```json
|
||
{
|
||
"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:**
|
||
|
||
```bash
|
||
# httpie
|
||
http GET localhost:5000/api/v1/game/difficulties
|
||
|
||
# curl
|
||
curl http://localhost:5000/api/v1/game/difficulties
|
||
```
|
||
|
||
**Success Response (200 OK):**
|
||
|
||
```json
|
||
{
|
||
"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:**
|
||
|
||
```bash
|
||
# httpie
|
||
http GET localhost:5000/api/v1/origins
|
||
|
||
# curl
|
||
curl http://localhost:5000/api/v1/origins
|
||
```
|
||
|
||
**Success Response (200 OK):**
|
||
|
||
```json
|
||
{
|
||
"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
|
||
|
||
---
|
||
|
||
## Testing Workflows
|
||
|
||
### Complete Registration Flow
|
||
|
||
1. **Register new user:**
|
||
```bash
|
||
http POST localhost:5000/api/v1/auth/register \
|
||
email="newuser@example.com" \
|
||
password="SecurePass123!" \
|
||
name="New User"
|
||
```
|
||
|
||
2. **Check email for verification link**
|
||
- Look for email from Appwrite
|
||
- Extract `userId` and `secret` from verification URL
|
||
|
||
3. **Verify email:**
|
||
```bash
|
||
http GET "localhost:5000/api/v1/auth/verify-email?userId=XXX&secret=YYY"
|
||
```
|
||
|
||
4. **Login:**
|
||
```bash
|
||
http --session=newuser POST localhost:5000/api/v1/auth/login \
|
||
email="newuser@example.com" \
|
||
password="SecurePass123!" \
|
||
remember_me:=false
|
||
```
|
||
|
||
5. **Verify session is active:**
|
||
- Session cookie should be set
|
||
- Can now access protected routes
|
||
|
||
---
|
||
|
||
### Complete Password Reset Flow
|
||
|
||
1. **Request password reset:**
|
||
```bash
|
||
http POST localhost:5000/api/v1/auth/forgot-password \
|
||
email="hero@example.com"
|
||
```
|
||
|
||
2. **Check email for reset link**
|
||
- Look for email from Appwrite
|
||
- Extract `userId` and `secret` from reset URL
|
||
|
||
3. **Reset password:**
|
||
```bash
|
||
http POST localhost:5000/api/v1/auth/reset-password \
|
||
user_id="XXX" \
|
||
secret="YYY" \
|
||
password="NewSecurePass123!"
|
||
```
|
||
|
||
4. **Login with new password:**
|
||
```bash
|
||
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:**
|
||
|
||
```bash
|
||
# Should return 401 Unauthorized
|
||
http POST localhost:5000/api/v1/auth/logout
|
||
```
|
||
|
||
**With authentication:**
|
||
|
||
```bash
|
||
# 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
|
||
|
||
1. **Login first (required):**
|
||
```bash
|
||
http --session=user1 POST localhost:5000/api/v1/auth/login \
|
||
email="hero@example.com" \
|
||
password="SecurePass123!"
|
||
```
|
||
|
||
2. **Browse available classes:**
|
||
```bash
|
||
http GET localhost:5000/api/v1/classes
|
||
```
|
||
|
||
3. **Browse available origins:**
|
||
```bash
|
||
http GET localhost:5000/api/v1/origins
|
||
```
|
||
|
||
4. **Create a new character:**
|
||
```bash
|
||
http --session=user1 POST localhost:5000/api/v1/characters \
|
||
name="Thorin Ironforge" \
|
||
class_id="vanguard" \
|
||
origin_id="soul_revenant"
|
||
```
|
||
|
||
5. **View all your characters:**
|
||
```bash
|
||
http --session=user1 GET localhost:5000/api/v1/characters
|
||
```
|
||
|
||
6. **View character details (replace char_123 with actual character_id from step 4):**
|
||
```bash
|
||
http --session=user1 GET localhost:5000/api/v1/characters/char_123
|
||
```
|
||
|
||
7. **Unlock a skill (when character has skill points from leveling):**
|
||
```bash
|
||
http --session=user1 POST localhost:5000/api/v1/characters/char_123/skills/unlock \
|
||
skill_id="shield_wall"
|
||
```
|
||
|
||
8. **Respec skills (when needed, costs level × 100 gold):**
|
||
```bash
|
||
http --session=user1 POST localhost:5000/api/v1/characters/char_123/skills/respec
|
||
```
|
||
|
||
9. **Delete a character:**
|
||
```bash
|
||
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:**
|
||
|
||
```json
|
||
{
|
||
"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:**
|
||
|
||
```json
|
||
{
|
||
"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:**
|
||
|
||
```json
|
||
{
|
||
"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:**
|
||
|
||
```json
|
||
{
|
||
"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:
|
||
|
||
```bash
|
||
# 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
|
||
|
||
```bash
|
||
# 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
|
||
|
||
```bash
|
||
# httpie (automatic)
|
||
http POST localhost:5000/api/v1/auth/register ...
|
||
|
||
# curl (with jq)
|
||
curl ... | jq .
|
||
```
|
||
|
||
### Verbose Output
|
||
|
||
```bash
|
||
# 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)
|
||
|
||
```bash
|
||
# 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
|
||
|
||
```bash
|
||
# 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
|
||
|
||
```bash
|
||
# 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
|
||
|
||
```bash
|
||
# 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
|
||
|
||
```bash
|
||
# 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
|