IdleLingo API

API Documentation

Reference for integrating apps and learning tools with the IdleLingo platform.

Overview

IdleLingo is an API-first platform for Japanese and Chinese character learning. Client applications integrate through structured HTTP endpoints for accounts, player sessions, world state, inventory, and progression data.

All API responses use JSON. Successful responses include "success": true. Errors return an appropriate HTTP status with "success": false, an error_code, and a message.

Base URLs

Development http://127.0.0.1:5000
Production https://idlelingo.com

Authentication

IdleLingo supports two authentication layers:

Account sessions — Flask-Login cookie sessions created via POST /api/auth/register or POST /api/auth/login. Required for /api/auth/logout and /api/auth/me.

Player sessions — Bearer tokens issued by POST /api/players/session. Pass the token via Authorization: Bearer <token>, the X-Session-Token header, or a session_token field in the JSON body. Required for player, world, and inventory endpoints marked Player session below.

Health & Observability

IdleLingo exposes two health endpoints: a human-facing service status page and a machine-readable JSON endpoint for integrations and health monitors.

GET /health is the public availability page with friendly service indicators. GET /api/health returns JSON and preserves ok and service for existing clients.

Responses include current service status, database connectivity, timestamps, and version metadata.

Every response includes an X-Request-ID header. Clients may send the same header to correlate their logs with IdleLingo server logs. The value is reused when safe; otherwise the server generates a short ID.

API request summaries are logged safely by default — passwords, tokens, cookies, Authorization headers, and session secrets are never written to logs. Optional payload logging is disabled by default (IDLELINGO_API_LOG_PAYLOADS=false) and only records sanitized JSON when explicitly enabled.

GET /health
Purpose
Human-facing service status page with friendly availability indicators.
Auth
Public.
GET /api/health
Purpose
Machine-readable health snapshot for clients and monitoring.
Auth
Public. HEAD is supported for lightweight health checks.
Response example
json
{
  "ok": true,
  "service": "idlelingo",
  "status": "operational",
  "api": {
    "status": "operational",
    "source": "app.health.get_health_snapshot"
  },
  "database": {
    "status": "operational"
  },
  "server_time_utc": "2026-06-09T20:15:30Z",
  "last_checked_utc": "2026-06-09T20:15:30Z",
  "environment": "development",
  "version": "0.1.0",
  "request_id": "abc123"
}

Client Applications

GET /api/clients
Purpose
List registered client applications.
Auth
Public.
Response example
json
{
  "success": true,
  "clients": [
    {
      "id": "kanji_slayer",
      "name": "Kanji Slayer",
      "status": "active",
      "created_at": "2025-01-01T00:00:00Z",
      "updated_at": "2025-01-01T00:00:00Z"
    }
  ]
}
GET /api/clients/<client_id>
Purpose
Fetch a single client application by ID.
Auth
Public.
Response example
json
{
  "success": true,
  "client": {
    "id": "kanji_slayer",
    "name": "Kanji Slayer",
    "status": "active",
    "created_at": "2025-01-01T00:00:00Z",
    "updated_at": "2025-01-01T00:00:00Z"
  }
}

Accounts

POST /api/auth/register
Purpose
Create an IdleLingo account and start a login session.
Auth
Public.
Request body

Email is optional. Password must be at least 6 characters.

json
{
  "username": "player_one",
  "email": "player@example.com",
  "password": "securepass"
}
Response example
json
{
  "success": true,
  "user": {
    "user_id": 1,
    "username": "player_one",
    "email": "player@example.com",
    "created_at": "2025-01-01T00:00:00Z"
  }
}
POST /api/auth/login
Purpose
Authenticate with username or email and password.
Auth
Public.
Request body

Use username instead of email if preferred.

json
{
  "email": "player@example.com",
  "password": "securepass",
  "remember": true
}
Response example
json
{
  "success": true,
  "user": {
    "user_id": 1,
    "username": "player_one",
    "email": "player@example.com",
    "created_at": "2025-01-01T00:00:00Z"
  }
}
POST /api/auth/logout
Purpose
End the current account session.
Auth
Account session (cookie).
Response example
json
{
  "success": true
}
GET /api/auth/me
Purpose
Return the authenticated account profile.
Auth
Account session (cookie).
Response example
json
{
  "success": true,
  "user": {
    "user_id": 1,
    "username": "player_one",
    "email": "player@example.com",
    "created_at": "2025-01-01T00:00:00Z"
  }
}

Sessions

POST /api/players/session
Purpose
Create or refresh a player session for a client application.
Auth
Public. Optional account session or existing player session token.
Request body

Omit username to create a guest session. Pass an existing session token to refresh without creating a new player.

json
{
  "username": "adventurer",
  "client_application_id": "kanji_slayer"
}
Response example
json
{
  "success": true,
  "client_application": { "id": "kanji_slayer", "name": "..." },
  "player": {
    "player_id": "plr_abc123",
    "username": "adventurer",
    "is_guest": false,
    "client_application_id": "kanji_slayer"
  },
  "session_token": "...",
  "session": { "player_id": "plr_abc123", "session_token": "..." }
}

Player / Profile Data

GET /api/players/me
Purpose
Return the active player profile and session context.
Auth
Player session.
Response example
json
{
  "success": true,
  "player": {
    "player_id": "plr_abc123",
    "username": "adventurer",
    "display_name": "adventurer",
    "is_guest": false,
    "world_id": "world_1",
    "stats": { "playtime_seconds": 0 }
  }
}

Inventory

GET /api/players/me/inventory
Purpose
Return inventory, bank, and item order for the active player.
Auth
Player session.
Response example
json
{
  "success": true,
  "inventory": { "daily_mystery_box": 1 },
  "bank": { "items": {}, "order": [] },
  "item_order": ["daily_mystery_box"]
}

Drops / Rewards

POST /api/worlds/<world_id>/items/drop
Purpose
Drop items from player inventory into a world scene.
Auth
Player session.
Request body

Optional item_instance_id to drop a specific stack.

json
{
  "item_id": "daily_mystery_box",
  "quantity": 1,
  "scene_key": "starter_village",
  "position": { "x": 128.0, "y": 256.0 }
}
Response example
json
{
  "success": true,
  "removed_from_inventory": { "daily_mystery_box": 1 },
  "drop": {
    "drop_id": "drop_...",
    "world_id": "world_1",
    "scene_key": "starter_village",
    "item_id": "daily_mystery_box",
    "quantity": 1,
    "position": { "x": 128.0, "y": 256.0 },
    "state": "available"
  }
}
POST /api/worlds/<world_id>/items/pickup
Purpose
Pick up a world item drop into player inventory.
Auth
Player session.
Request body
json
{
  "drop_id": "drop_abc123"
}
Response example
json
{
  "success": true,
  "drop": { "drop_id": "drop_abc123", "state": "picked_up" },
  "inventory": { "daily_mystery_box": 1 },
  "bank_overflow": {}
}

Learning Models

Learning content and per-learner glyph progress are persisted through LearningGlyph, PlayerGlyphProgress, and QuestProgress models.

Clients integrate character literacy and progression through player sessions, world state, inventory, and the account workflows documented in this reference.

Worlds

GET /api/worlds
Purpose
List available worlds for the default client application.
Auth
Public.
Response example
json
{
  "success": true,
  "worlds": [
    {
      "world_id": "world_1",
      "name": "World 1",
      "status": "online",
      "players_online": 0,
      "endpoint": "http://127.0.0.1:5000/api/worlds/world_1"
    }
  ]
}
GET /api/worlds/status
Purpose
Return aggregate world health and online player counts.
Auth
Public.
Response example
json
{
  "success": true,
  "server_time_msec": 1710000000000,
  "overall_status": "healthy",
  "worlds": [
    {
      "world_id": "world_1",
      "status": "online",
      "players_online": 0,
      "healthy": true
    }
  ]
}
POST /api/worlds/<world_id>/join
Purpose
Join a world and mark the player session as online.
Auth
Player session.
Response example
json
{
  "success": true,
  "world": { "world_id": "world_1", "name": "World 1" },
  "session": { "player_id": "plr_abc123", "world_id": "world_1", "joined": true }
}
POST /api/worlds/<world_id>/heartbeat
Purpose
Send a presence heartbeat and optional scene key update.
Auth
Player session.
Request body
json
{
  "scene_key": "starter_village"
}
Response example
json
{
  "success": true,
  "world_id": "world_1",
  "server_time_msec": 1710000000000,
  "status": "online"
}
GET /api/worlds/<world_id>/state
Purpose
Return world state including available item drops for the current scene.
Auth
Player session.
Response example
json
{
  "success": true,
  "world_id": "world_1",
  "scene_key": "starter_village",
  "drops": {}
}
GET /api/worlds/<world_id>/scenes/<scene_key>/state
Purpose
Return scene-specific state including available drops.
Auth
Player session.
Response example
json
{
  "success": true,
  "world_id": "world_1",
  "scene_key": "starter_village",
  "drops": {}
}

Error Format

Failed requests return JSON with HTTP 4xx or 5xx status codes:

json
{
  "success": false,
  "error_code": "UNAUTHORIZED",
  "message": "Missing or invalid session token."
}

Example Requests

Create a player session

bash
curl -X POST http://127.0.0.1:5000/api/players/session \
  -H "Content-Type: application/json" \
  -d '{"username": "adventurer", "client_application_id": "kanji_slayer"}'

Join a world

bash
curl -X POST http://127.0.0.1:5000/api/worlds/world_1/join \
  -H "Authorization: Bearer <session_token>" \
  -H "Content-Type: application/json"

Fetch player inventory

bash
curl http://127.0.0.1:5000/api/players/me/inventory \
  -H "Authorization: Bearer <session_token>"

Versioning

The IdleLingo API is unversioned. All paths are prefixed with /api/.

This reference documents the current public API surface for accounts, sessions, worlds, inventory, learning models, and platform health.