REST API v1

API Reference

Programmatically create decks, add flashcards, and import files. Works with ChatGPT, Claude, and any tool that speaks HTTP.

Quick Start

# Add a flashcard to your deck
curl -X POST https://www.iwill.study/api/v1/cards \
  -H "Authorization: Bearer isk_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{"deck":"Spanish B1","cards":[{"front":"however","back":"sin embargo"}]}'

Authentication

REST API requests require a Bearer token. Generate an API key in Settings → API Keys.

Authorization: Bearer isk_your_api_key_here

The full key is shown only once when it is created. Store it securely, never put it in client-side source code, and use a dedicated key for each integration. Deck/language scope controls where new cards are written; it is not a general permission boundary.

Base URL

https://www.iwill.study/api/v1

Rate Limits

PlanCards via APIDecks
Free100 cards/day5 decks
ProUnlimitedUnlimited

Generate cards with OpenAI

Paste this prompt into ChatGPT or send it as the user input in an OpenAI API request. It defines the outcome, quality bar, JSON contract, and validation rules expected by the cards endpoint.

Create 20 high-quality flashcards for learning [LANGUAGE] at [LEVEL] level.

Outcome:
- Focus on practical, high-frequency vocabulary and phrases.
- Make each front a single, unambiguous recall cue.
- Make each back a concise translation or answer.
- Include one natural usage example in "context".
- Add 1-3 useful lowercase tags per card.
- Do not create duplicate or near-duplicate cards.

Return exactly one valid JSON object matching this shape:
{
  "deck": "[Language] [Level]",
  "cards": [
    {
      "front": "word, phrase, or question",
      "back": "translation or answer",
      "context": "one natural example with a short clarification if needed",
      "tags": ["level", "topic"]
    }
  ]
}

Output rules:
- Return JSON only: no Markdown fences, commentary, or trailing commas.
- Use double quotes for every key and string.
- Replace every placeholder with real content.
- Verify the JSON is valid before responding.

Replace the bracketed values before sending. Then POST the returned JSON to /api/v1/cards using the Bearer key shown in the request examples below.

OpenAI Responses API with the MCP server

Server-side OpenAI requests can pass the iwill.study key in an HTTP header, so it does not need to appear in the connector URL. Keep both keys in environment variables or a server-side secret manager.

curl https://api.openai.com/v1/responses \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "model": "gpt-5.6-sol",
  "input": "Use the iwill.study app to create 20 [LANGUAGE] flashcards at [LEVEL] level about [TOPIC]. Use concise recall cues, accurate answers, one natural usage example per card, and useful tags. Avoid duplicates. Save the cards to a deck named \"[Language] [Level] — [Topic]\" and report how many were created or skipped.",
  "tools": [
    {
      "type": "mcp",
      "server_label": "iwill_study",
      "server_description": "Create and manage language-learning flashcards in iwill.study.",
      "server_url": "https://www.iwill.study/api/mcp",
      "headers": {
        "Authorization": "Bearer isk_your_api_key_here"
      },
      "require_approval": "always"
    }
  ]
}'

AI connectors (MCP)

Connect ChatGPT or Claude directly to your iwill.study account. The remote MCP server exposes read and write tools for decks and cards.

ChatGPT / OpenAI

  1. In an eligible ChatGPT workspace, enable developer mode under Settings → Apps → Advanced settings.
  2. Open Settings → Apps → Create, name the app iwill.study, and use the generated MCP URL below.
  3. Choose no additional authentication because the dedicated key is already part of this MCP URL, then scan the tools.
OpenAI setup and availability →

Claude

  1. Open Settings → Integrations → Add custom connector.
  2. Set the name to iwill.study.
  3. Use the generated URL as the remote MCP server URL.

Keys are shown only once when created, so saved keys cannot be filled in here. This field stays in your browser. Use a dedicated key, optionally scope its card destination, and revoke it if the connector URL is exposed.

https://www.iwill.study/api/mcp?key=isk_your_api_key_here

Available tools

ToolDescription
list_decksList all your decks with card counts
add_cardsAdd flashcards to a deck (auto-creates deck if needed, deduplicates)
get_cardsFetch all cards from a specific deck
create_deckCreate a new empty deck

Prompt after connecting

Use the iwill.study app to create 20 [LANGUAGE] flashcards at [LEVEL] level about [TOPIC]. Use concise recall cues, accurate answers, one natural usage example per card, and useful tags. Avoid duplicates. Save the cards to a deck named "[Language] [Level] — [Topic]" and report how many were created or skipped.

Endpoints

GET/api/v1/decks

List all decks belonging to the authenticated user, with card counts.

Authentication

Bearer token (API key)

Example Request

curl https://www.iwill.study/api/v1/decks \
  -H "Authorization: Bearer isk_your_api_key_here"

Response

{
  "decks": [
    {
      "id": "uuid",
      "title": "Spanish B1",
      "description": "",
      "language": "Spanish",
      "source": "api",
      "created_at": "2026-03-14T...",
      "card_count": 42
    }
  ]
}
POST/api/v1/decks

Create a new empty deck.

Authentication

Bearer token (API key)

Request Body

FieldTypeRequiredDescription
titlestringYesDeck title (max 200 chars)
descriptionstringNoDeck description
languagestringNoTarget language (e.g. "Spanish")

Example Request

curl -X POST https://www.iwill.study/api/v1/decks \
  -H "Authorization: Bearer isk_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{"title":"Spanish B1","description":"Writing connectors","language":"Spanish"}'

Response

{
  "deck": {
    "id": "uuid",
    "title": "Spanish B1",
    "description": "",
    "language": "Spanish",
    "source": "api",
    "created_at": "2026-03-14T..."
  }
}
DELETE/api/v1/decks

Delete a deck and all its cards.

Authentication

Bearer token (API key)

Query Parameters

ParameterTypeRequiredDescription
idstringYesDeck ID to delete

Example Request

curl -X DELETE "https://www.iwill.study/api/v1/decks?id=DECK_ID" \
  -H "Authorization: Bearer isk_your_api_key_here"

Response

{ "success": true }
GET/api/v1/cards

List all cards in a specific deck.

Authentication

Bearer token (API key)

Query Parameters

ParameterTypeRequiredDescription
deck_idstringYesDeck ID to fetch cards from

Example Request

curl "https://www.iwill.study/api/v1/cards?deck_id=DECK_ID" \
  -H "Authorization: Bearer isk_your_api_key_here"

Response

{
  "cards": [
    {
      "id": "uuid",
      "front": "however",
      "back": "sin embargo",
      "tags": ["b1", "connectors"],
      "context": "Formal writing: 'The results, however, were unexpected.'",
      "source": "api",
      "created_at": "2026-03-14T..."
    }
  ]
}
POST/api/v1/cards

Add cards to a deck. Specify an existing deck by ID, or provide a title to find-or-create a deck.

Authentication

Bearer token (API key)

Request Body

FieldTypeRequiredDescription
deck_idstringNoExisting deck UUID. Use this to add cards to a specific deck.
deckstringNoDeck title (max 200 chars). Creates deck if not found. Required if deck_id is not provided.
sourcestringNoOptional source label: web, mobile, api, chatgpt, claude-mcp, import, or preset
cardsarrayYesArray of card objects (max 500 per request)
cards[].frontstringYesFront side text (max 5000 chars)
cards[].backstringYesBack side text (max 5000 chars)
cards[].tagsstring[]NoOptional tags for the card
cards[].contextstringNoUsage examples, cultural notes, or contextual info (max 10,000 chars)

Example Request

curl -X POST https://www.iwill.study/api/v1/cards \
  -H "Authorization: Bearer isk_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "deck": "Spanish B1",
    "source": "chatgpt",
    "cards": [
      {
        "front": "however",
        "back": "sin embargo",
        "context": "The results, however, were unexpected.",
        "tags": ["b1", "connectors"]
      }
    ]
  }'

Response

{
  "deck_id": "uuid",
  "created": 2,
  "skipped": 1,
  "rate_limited": 0
}

Duplicates are automatically skipped — cards with the same front text (case-insensitive) already in the deck won't be added again. Provide deck_id for an existing deck or deck to find/create by title; if both are sent, deck_id takes precedence. A scoped key overrides the requested deck. Free plan: max 100 cards/day via API.

PATCH/api/v1/cards

Update or move cards. Use this to move cards between decks (preserving review history), edit card content, or update context and tags.

Authentication

Bearer token (API key)

Request Body

FieldTypeRequiredDescription
card_idsstring[]YesArray of card UUIDs to update (max 500)
updates.deck_idstringNoTarget deck UUID — moves cards to this deck
updates.frontstringNoNew front text (max 5,000 chars)
updates.backstringNoNew back text (max 5,000 chars)
updates.tagsstring[]NoNew tags array
updates.contextstring | nullNoNew context/examples (max 10,000 chars), or null to clear

Example Request

curl -X PATCH https://www.iwill.study/api/v1/cards \
  -H "Authorization: Bearer isk_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "card_ids": ["CARD_ID"],
    "updates": {"deck_id": "TARGET_DECK_ID"}
  }'

Response

{ "updated": 3 }

Moving cards between decks preserves all FSRS review history. You can combine a move with field updates in a single request.

POST/api/v1/import

Import flashcards from an Anki (.apkg) or CSV/TSV file.

Authentication

Bearer token (API key)

Request Body

FieldTypeRequiredDescription
fileFileYesUpload via multipart/form-data. Accepted: .apkg, .csv, .tsv, .txt

Example Request

curl -X POST https://www.iwill.study/api/v1/import \
  -H "Authorization: Bearer isk_your_api_key_here" \
  -F "file=@my_deck.csv"

Response

{
  "deck_id": "uuid",
  "imported": 150
}

CSV files should have two columns: front and back. The filename (without extension) is used as the deck name.

Error Codes

StatusMeaning
400Bad request — invalid or missing parameters
401Unauthorized — missing or invalid API key
403Forbidden — plan limit reached or operation is not allowed
404Not found — resource doesn't exist or doesn't belong to you
429Rate limited — daily card limit exceeded (free plan)
500Server error — please try again or contact support