MTG Online Backend

A Python FastAPI application that processes Magic: The Gathering card data from MTGJSON and stores it in PostgreSQL, with Redis for caching.

Overview

This project provides a backend API for a Magic: The Gathering Online platform. It downloads and processes MTGJSON v5 dataset dumps, loads them into a PostgreSQL database, and exposes REST endpoints for card data, user authentication, deck management, and game state.

Key Features

  • MTGJSON Data Pipeline — Downloads AllPrintings.psql, AllIdentifiers.json, Keywords.json, CardTypes.json, and AllDeckFiles.zip from MTGJSON v5 on startup or via a POST /refresh endpoint.
  • Dual PostgreSQL — Two databases: mtgonline for the application (users, decks, auth) and mtgdata for MTG card data.
  • Redis Caching — Used for card lookup caching and interaction pipeline state.
  • Card Import Feature — Users can import their card collection (fuzzy matching enabled) for deckbuilding constraints.
  • REST API/docs (Swagger) available at runtime.

Architecture

mtgonline/
├── backend/                  # FastAPI application
│   ├── app/
│   │   ├── core/             # Settings, database engines, Redis client
│   │   ├── models/           # SQLAlchemy ORM models (app + MTG)
│   │   ├── routers/          # API route modules
│   │   ├── schemas/          # Pydantic request/response schemas
│   │   ├── services/         # Business logic (MTGJSON manager, card DB, game server)
│   │   └── main.py           # FastAPI app entry point
│   ├── scripts/              # Utility scripts (downloads, migrations, checks)
│   ├── Dockerfile
│   └── requirements.txt
├── docker-compose.dev.yml    # Development stack (Postgres x2, Redis, Backend)
├── docker-compose.yml        # Production stack
├── scripts/                  # Shared utility scripts
└── README.md

Data Flow

  1. On startup, the backend connects to PostgreSQL (both instances) and Redis.
  2. It checks mtg_refresh_log in the mtgdata database for existing data.
  3. If no data exists, it downloads MTGJSON files from https://mtgjson.com/api/v5/, unzips if needed, and upserts them into mtgdata tables (mtg_sets, mtg_cards, etc.).
  4. The data is then available via REST endpoints.

API Endpoints

Card Import (New)

Method Endpoint Description
GET /api/v1/card-import/status Get current card import status
POST /api/v1/card-import/ Import/update card collection
DELETE /api/v1/card-import/ Delete card import
GET /api/v1/card-import/summary Get import summary with match results

Card Import Request Body:

{
  "card_names": ["Lightning Bolt", "Shock", "Thoughtseize"]
}

Card Import Response:

{
  "message": "Imported 3 cards successfully",
  "card_count": 3,
  "card_names": ["Lightning Bolt", "Shock", "Thoughtseize"],
  "imported_at": "2026-07-24T04:12:00"
}

User Data Endpoints

Method Endpoint Description
GET /api/v1/user-data/profile Get user profile
PUT /api/v1/user-data/profile Update user profile
GET /api/v1/user-data/collection Get user card collection
GET /api/v1/user-data/groups List user groups
GET /api/v1/user-data/networks List user networks
GET /api/v1/user-data/preferences Get user preferences
PUT /api/v1/user-data/preferences Update user preferences
GET /api/v1/user-data/activity Get user activity log
GET /api/v1/user-data/replays List user replays
GET /api/v1/user-data/replays/{replay_id} Get replay details

Deck Management Endpoints

Method Endpoint Description
GET /api/v1/decks/ List user decks
POST /api/v1/decks/ Create new deck
GET /api/v1/decks/{deck_id} Get deck details
PUT /api/v1/decks/{deck_id} Update deck
DELETE /api/v1/decks/{deck_id} Delete deck
POST /api/v1/decks/{deck_id}/cards Add card to deck
PUT /api/v1/decks/{deck_id}/cards/{card_id} Update deck card
DELETE /api/v1/decks/{deck_id}/cards/{card_id} Remove card from deck
GET /api/v1/decks/{deck_id}/cards List deck cards
POST /api/v1/decks/{deck_id}/finalize Finalize deck (DRAFT → FINAL)
POST /api/v1/decks/search/cards Search cards for deckbuilding
GET /api/v1/decks/precedents/ List deck precedents
POST /api/v1/decks/precedents/ Create precedent
GET /api/v1/decks/precedents/{precedent_id} Get precedent details
POST /api/v1/decks/precedents/{precedent_id}/use Use/clone precedent
GET /api/v1/decks/suggestions/ List card suggestions
POST /api/v1/decks/suggestions/ Add card suggestion

Quick Start

Prerequisites

  • Docker and Docker Compose

Run the Stack

cd /home/wall-o/projects/mtgonline

# Start all services (Postgres x2, Redis, Backend)
docker compose -f docker-compose.dev.yml up -d

# View logs
docker compose -f docker-compose.dev.yml logs -f backend

The backend will automatically download MTGJSON data on first startup (this may take several minutes).

Access

Service Address
Backend API http://localhost:5555
Swagger Docs http://localhost:5555/docs
Health Check http://localhost:5555/health
PostgreSQL (app) localhost:5432
PostgreSQL (MTG) localhost:5433
Redis localhost:6379

Manual Data Refresh

# Trigger a manual MTGJSON refresh
curl -X POST http://localhost:5555/refresh

Card Import Feature

Users can import their card collection to enable deckbuilding with owned cards. The feature includes fuzzy matching for typos.

Import Cards

curl -X POST http://localhost:5555/api/v1/card-import/ \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "card_names": ["Lightning Bolt", "Shock", "Thoughtseize"]
  }'

Check Import Status

curl http://localhost:5555/api/v1/card-import/status \
  -H "Authorization: Bearer <token>"

Get Import Summary

curl http://localhost:5555/api/v1/card-import/summary \
  -H "Authorization: Bearer <token>"

Delete Import

curl -X DELETE http://localhost:5555/api/v1/card-import/ \
  -H "Authorization: Bearer <token>"

Environment Variables

Variable Default Description
DATABASE_URL postgresql+asyncpg://mtgonline_user:mtgonline_password@postgres:5432/mtgonline Primary database connection
MTG_DATABASE_URL postgresql+asyncpg://mtgonline_user:mtgonline_password@mtgdata:5432/mtgdata MTG data database connection
REDIS_URL redis://redis:6379 Redis connection
DATA_DIR /app/data Directory for MTGJSON files
DEBUG False Enable debug logging

Docker Cleanup

# Stop and remove all containers
docker compose -f docker-compose.dev.yml down

# Remove images and prune
docker system prune -a --volumes

License

MIT

S
Description
No description provided
Readme
24 MiB
Languages
C++ 80.4%
Python 15.7%
CMake 1.8%
Shell 0.9%
C 0.9%
Other 0.1%