PyScape-Basic provides both REST and WebSocket APIs for frontend-backend communication.
- REST API — Stateless queries, data fetching (runs on port 5000)
- WebSocket API — Real-time events (runs on port 8080)
REST API: http://localhost:5000
WebSocket: ws://localhost:8080
Authentication: Bearer Token (Supabase JWT)
All requests require a valid Supabase JWT token:
// Frontend example
const token = session.access_token;
const headers = {
Authorization: `Bearer ${token}`
};Login with email and password.
Request:
{
"email": "user@example.com",
"password": "password123"
}Response:
{
"user": { "id": "uuid", "email": "user@example.com" },
"session": { "access_token": "jwt_token" }
}Create a new user account.
Request:
{
"email": "user@example.com",
"password": "password123",
"username": "john_dev"
}Response:
{
"user": { "id": "uuid", "email": "user@example.com", "username": "john_dev" },
"session": { "access_token": "jwt_token" }
}Logout current user session.
Response:
{ "message": "Logout successful" }Fetch coding problems with optional filters.
Query Parameters:
difficulty—easy,medium,hardlanguage—python,javascript,java,cpptags— Comma-separated skill tagslimit— Number of results (default: 20)offset— Pagination offset (default: 0)
Response:
{
"problems": [
{
"id": "uuid",
"title": "Two Sum",
"description": "Given an array of integers...",
"difficulty": "easy",
"language": "python",
"tags": ["arrays", "hash-table"]
}
],
"total": 150
}Fetch a specific problem.
Response:
{
"id": "uuid",
"title": "Two Sum",
"description": "Given an array of integers...",
"difficulty": "easy",
"starter_code": "def twoSum(nums, target):\n # Your code here",
"tags": ["arrays", "hash-table"]
}Note: solution_code and test_cases are NOT returned to users.
Submit code for a problem.
Request:
{
"problem_id": "uuid",
"code": "def twoSum(nums, target):\n # Solution code",
"language": "python"
}Response:
{
"id": "uuid",
"status": "accepted",
"runtime_ms": 45,
"memory_kb": 12800,
"test_results": [
{ "test_case": 1, "passed": true, "output": "[0,1]" },
{ "test_case": 2, "passed": true, "output": "[1,2]" }
],
"xp_earned": 100
}Possible Status Values:
accepted— All tests passed, XP awardedwrong_answer— Test output mismatchcompile_error— Syntax errortimeout— Execution exceeded time limitruntime_error— Exception during execution
Get user's submission history.
Response:
{
"submissions": [
{
"id": "uuid",
"problem_id": "uuid",
"problem_title": "Two Sum",
"status": "accepted",
"created_at": "2025-06-01T10:30:00Z"
}
]
}Get user profile information.
Response:
{
"id": "uuid",
"username": "john_dev",
"email": "john@example.com",
"xp_total": 1500,
"level": 3,
"avatar_url": "https://...",
"interests": ["Python", "Machine Learning"],
"created_at": "2025-01-15T00:00:00Z"
}Update user profile.
Request:
{
"username": "john_dev_pro",
"avatar_url": "https://..."
}Response:
{
"id": "uuid",
"username": "john_dev_pro",
"avatar_url": "https://..."
}Generate personalized learning roadmap from topics.
Request:
{
"topics": ["Python Basics", "Machine Learning", "Data Science"]
}Response:
{
"id": "uuid",
"topics": ["Python Basics", "Machine Learning", "Data Science"],
"skills": {
"Python Basics": {
"level": 1,
"lessons": ["intro_to_python", "variables_types", "control_flow"]
},
"Machine Learning": {
"level": 2,
"lessons": ["supervised_learning", "unsupervised_learning"]
}
},
"levels": [
{ "level": 1, "xp_required": 0 },
{ "level": 2, "xp_required": 500 }
]
}Fetch user's roadmap.
Response:
{
"id": "uuid",
"topics": ["Python Basics", "Machine Learning"],
"skills": { ... },
"levels": [ ... ],
"generated_at": "2025-06-01T00:00:00Z"
}Fetch lesson content and questions.
Response:
{
"id": "uuid",
"title": "Introduction to Python",
"type": "reading",
"content": "# Intro\nPython is a high-level...",
"quiz_questions": [
{
"id": "q1",
"question": "What is Python?",
"options": ["A", "B", "C"],
"correct_answer": 0
}
]
}Mark lesson as complete and earn XP.
Response:
{
"xp_earned": 50,
"new_total_xp": 1550,
"level_up": false
}Get current user's duel statistics.
Response:
{
"total_duels": 25,
"wins": 18,
"losses": 7,
"win_rate": 0.72,
"current_streak": 3,
"best_streak": 8,
"rank": 42
}Get global leaderboard.
Response:
{
"leaderboard": [
{
"rank": 1,
"username": "pro_coder",
"wins": 250,
"win_rate": 0.85
},
{
"rank": 2,
"username": "john_dev",
"wins": 180,
"win_rate": 0.72
}
]
}Get user's portfolio.
Response:
{
"user": { "username": "john_dev", "xp_total": 1500 },
"projects": [
{
"id": "uuid",
"project_name": "Sentiment Analyzer",
"description": "ML project analyzing text sentiment",
"skills": ["Python", "NLP", "Scikit-learn"],
"metrics": { "accuracy": 0.87, "f1_score": 0.85 },
"created_at": "2025-05-20T00:00:00Z"
}
]
}Export portfolio as PDF.
Request:
{
"format": "pdf"
}Response:
- Returns PDF file as binary
// Frontend example
const ws = new WebSocket('ws://localhost:8080');
ws.onopen = () => {
// Send auth message
ws.send(JSON.stringify({
type: 'auth',
token: 'jwt_token'
}));
};Join matchmaking queue.
{
"type": "join-queue",
"difficulty": "intermediate",
"language": "python"
}Opponent found, duel starting.
{
"type": "match-found",
"duel_id": "uuid",
"opponent": {
"username": "opponent_user",
"level": 5
},
"problem": {
"id": "uuid",
"title": "Two Sum",
"description": "Given an array...",
"time_limit_seconds": 900
},
"starts_at": "2025-06-01T10:30:30Z"
}Submit code during duel.
{
"type": "code-submit",
"duel_id": "uuid",
"code": "def twoSum(nums, target):\n ..."
}Result of code submission.
{
"type": "code-result",
"player": "self",
"status": "accepted",
"passed_tests": 5,
"total_tests": 5,
"xp_earned": 100
}Real-time opponent progress.
{
"type": "opponent-progress",
"opponent": "opponent_user",
"passed_tests": 3,
"total_tests": 5,
"status": "solving"
}Abandon duel.
{
"type": "forfeit",
"duel_id": "uuid"
}Duel finished.
{
"type": "duel-complete",
"winner": "opponent_user",
"player1": {
"username": "john_dev",
"passed_tests": 3,
"time_seconds": 245
},
"player2": {
"username": "opponent_user",
"passed_tests": 5,
"time_seconds": 180
}
}Send chat message during duel.
{
"type": "send-message",
"duel_id": "uuid",
"message": "Good luck!"
}Receive message from opponent.
{
"type": "receive-message",
"from": "opponent_user",
"message": "Thanks! You too!",
"timestamp": "2025-06-01T10:32:15Z"
}All endpoints return consistent error format:
{
"error": "Description of error",
"code": "ERROR_CODE",
"status": 400
}Common Error Codes:
UNAUTHORIZED(401) — Missing/invalid JWTFORBIDDEN(403) — Access deniedNOT_FOUND(404) — Resource not foundINVALID_INPUT(400) — Bad request dataINTERNAL_ERROR(500) — Server error
Example:
{
"error": "Problem not found",
"code": "NOT_FOUND",
"status": 404
}API calls are rate-limited to prevent abuse:
- Authenticated users: 1000 requests/hour
- Per IP: 100 requests/minute
Rate limit headers included in responses:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1625097600
See also:
- DEVELOPMENT.md — Setup guide
- ARCHITECTURE.md — System design
- DATABASE.md — Data schema