Skip to content

Build generalizable Anki (.apkg) import script #13

Description

@shalgrim

Summary

We need a reusable script that can import cards from any Anki .apkg file into production via the API. Currently we did a one-off bash script for an OAuth deck — this should be a proper, generalizable tool.

Requirements

  • Takes an .apkg file path as input
  • Supports a --dry-run flag (default behavior) that reports how many cards would be created without making any API calls
  • Requires --no-dry-run to actually create the cards
  • Reads the API key from NOTE_TAKER_PLUS_API_KEY_PROD env var
  • Defaults API URL to https://note-taker-plus-production.up.railway.app with an option to override
  • Tags imported cards (e.g., with the deck name from the apkg file, plus an anki-import tag)
  • Reports success/failure per card

Technical notes on .apkg extraction

An .apkg file is a zip archive containing:

  • collection.anki21b — a zstd-compressed SQLite database (modern Anki format)
  • collection.anki2 — legacy SQLite DB (just contains a "please upgrade" message in newer exports)
  • media — JSON mapping of media file references
  • meta — metadata

To extract cards:

  1. Unzip the .apkg file
  2. Decompress collection.anki21b with zstd -d (available via brew install zstd, no Python packages needed)
  3. Query the resulting SQLite DB: SELECT flds FROM notes;
  4. The flds column contains fields separated by the \x1f (unit separator) character — first field is front, second is back
  5. HTML tags like <br> are used for line breaks in the content

API details

  • Endpoint: POST /cards
  • Auth: X-API-Key header
  • Payload:
    {
      "front": "question text",
      "back": "answer text",
      "tags": ["tag1", "tag2"]
    }
  • Success: 201 Created
  • Cards are created with active status and initialized for spaced repetition automatically

Suggested implementation

Python script in the repo root (or a scripts/ dir) using only stdlib (zipfile, sqlite3, subprocess for zstd, urllib or httpx). Avoid installing packages into system Python — use a venv if needed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions