Documentation

What's what

Before anything else — here's how the pieces fit together.

Cards are the individual question-and-answer pairs. Every card has a front (the question or prompt) and a back (the answer).

Decks are collections of cards on a single topic — like "PSYC 1011 Midterm" or "Organic Chemistry: Reactions." You study a deck, share a deck, and manage cards inside a deck.

Courses are Dal course pages, like BIOL 1010 or STAT 1060. Each course page shows all the public decks Dal students have contributed for that course. You don't own a course — it's a shared community space. Anyone can add their deck to a course, and the community helps keep the cards accurate.

Collections are your own private folders. If you want to group your personal decks together (e.g. "Fall semester" or "Finals prep"), you can put them in a collection. Collections are just for your own organization — they're not visible to anyone else.


Three ways to create a deck

1. Generate with AI — right inside the app

Go to New deck and pick the Generate with AI tab. Paste in your lecture notes, slides, or any study material and the app will turn it into a full deck instantly. This is the fastest option for most people — no copying prompts, no uploading files.

2. Use any AI outside the app, then import

If you'd rather use ChatGPT, Claude, Gemini, or any other AI on your own, use the prompt template below. Copy it, replace [TOPIC] with your subject, and paste it into any AI. It will output a JSON file in exactly the right format. Then go to New deck → Import JSON and drop the file in (or paste the JSON directly).

This is useful when you want more control over the prompt, or when you already have a long document open in another AI tool.

Prompt template
Your task is to output a JSON data file — nothing else. Do not build an app, do not write HTML or JavaScript, do not create a UI. Just produce a JSON object containing flashcard data about [TOPIC].

Output it as a downloadable deck.json file if your interface supports it, otherwise wrap it in a ```json code block. No explanation before or after.

{
  "name": "string — the deck title",
  "description": "string — one sentence description",
  "coverImage": "string (optional) — a relevant Unsplash image URL",
  "cards": [
    {
      "front": {
        "title": "string — the question or concept (required)",
        "description": "string (optional) — extra context on the front"
      },
      "back": {
        "title": "string — the answer (required)",
        "description": "string (optional) — explanation or detail",
        "image": "string (optional) — a relevant Unsplash image URL for this card"
      }
    }
  ]
}

Rules:
- Output the JSON data only — no code, no apps, no HTML, no JavaScript
- front.title and back.title are required for every card
- Use clear, concise language
- Aim for 10–20 cards
- For image fields, use real Unsplash URLs in the format:
  https://images.unsplash.com/photo-[ID]?w=800&q=80
  Pick images that genuinely match the card content
- If [TOPIC] has not been replaced with a real topic, stop and ask the user what topic they want

3. Use the API directly

If you're a developer, running scripts, or building tools, you can create decks programmatically via the REST API. Generate an API key in Settings → API Keys and POST directly to /api/decks. The rest of this page documents everything the API can do.


Authentication

All API endpoints are authenticated with Bearer API keys. Generate a key in Settings under API Keys, then pass it as an Authorization header on every request.

Authorization: Bearer YOUR_API_KEY

Keys are scoped to your account. All write operations (create, update, delete) require a valid key. Some read operations (fetching public decks and course collections) work without authentication.

Decks

List your decks

GET/api/decksAPI key required

Returns all decks owned by your account, sorted by most recently updated.

Response (200)
{
  "decks": [
    {
      "id": "cm1abc123",
      "title": "Cell Biology",
      "description": "Key concepts from BIOL 2030",
      "visibility": "PRIVATE",
      "coverImage": null,
      "cardCount": 24,
      "collectionIds": ["cm1coll456"],
      "createdAt": "2024-09-01T12:00:00Z",
      "updatedAt": "2024-09-15T08:30:00Z"
    }
  ]
}

Error codes

401Missing or invalid API key

Create a deck

POST/api/decksAPI key required

Creates a new deck with cards in a single request. External image URLs in coverImage and back.image are mirrored to storage automatically.

Request body fields

namestringrequired
descriptionstringoptional
visibilityenumoptional
coverImagestring URLoptional
cards[].front.titlestringrequired
cards[].front.descriptionstringoptional
cards[].back.titlestringrequired
cards[].back.descriptionstringoptional
cards[].back.imagestring URLoptional
Request body
{
  "name": "Solar System",
  "description": "Key facts about the planets.",
  "visibility": "PUBLIC",
  "coverImage": "https://images.unsplash.com/photo-111?w=1200&q=80",
  "cards": [
    {
      "front": { "title": "How many planets are in the solar system?" },
      "back": {
        "title": "8",
        "description": "Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune."
      }
    },
    {
      "front": { "title": "What is the largest planet?" },
      "back": { "title": "Jupiter" }
    }
  ]
}
Response (201)
{
  "id": "cm1abc123",
  "title": "Solar System",
  "cardCount": 2,
  "visibility": "PUBLIC",
  "editUrl": "https://flashcardbrowser.com/decks/cm1abc123/edit"
}
curl
curl -X POST https://flashcardbrowser.com/api/decks \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Solar System",
    "visibility": "PRIVATE",
    "cards": [
      {
        "front": { "title": "How many planets are in the solar system?" },
        "back": { "title": "8" }
      }
    ]
  }'
fetch
const res = await fetch("https://flashcardbrowser.com/api/decks", {
  method: "POST",
  headers: {
    "Authorization": "Bearer YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    name: "Solar System",
    visibility: "PRIVATE",
    cards: [
      {
        front: { title: "How many planets are in the solar system?" },
        back: { title: "8" },
      },
    ],
  }),
});

const deck = await res.json();
// { id, title, cardCount, visibility, editUrl }

Error codes

400Invalid JSON body
401Missing or invalid API key
422Missing required field — see error message for details

Get a deck

GET/api/decks/:idAPI key optional

Returns a deck and its full card list. Public decks are accessible without authentication. Private decks require the owner's API key.

Response (200)
{
  "id": "cm1abc123",
  "title": "Solar System",
  "description": "Key facts about the planets.",
  "visibility": "PUBLIC",
  "coverImage": "https://...",
  "cardCount": 2,
  "ownerName": "Alice",
  "collectionIds": [],
  "createdAt": "2024-09-01T12:00:00Z",
  "updatedAt": "2024-09-15T08:30:00Z",
  "cards": [
    { "id": "cm1card1", "question": "How many planets...", "answer": "8", "imageUrl": null, "position": 0 },
    { "id": "cm1card2", "question": "What is the largest planet?", "answer": "Jupiter", "imageUrl": null, "position": 1 }
  ]
}

Note on card format: Cards in this response use question/answer fields. This differs from the front/back structure used when creating a deck — see the format note in the Cards section.

Error codes

401Deck is private — provide the owner's API key
404Deck not found

Update a deck

PATCH/api/decks/:idAPI key required

Update one or more metadata fields on a deck you own. All body fields are optional — send only what you want to change.

Request body fields

titlestringoptional
descriptionstringoptional
visibilityenumoptional
coverImagestringoptional
Request body
{
  "title": "Updated Title",
  "description": "Updated description.",
  "visibility": "PUBLIC",
  "coverImage": null
}
Response (200)
{
  "id": "cm1abc123",
  "title": "Updated Title",
  "description": "Updated description.",
  "visibility": "PUBLIC",
  "coverImage": null,
  "updatedAt": "2024-09-20T10:00:00Z"
}

Error codes

401Missing or invalid API key
403Deck belongs to a different user
404Deck not found
422No valid fields to update

Delete a deck

DELETE/api/decks/:idAPI key required

Permanently deletes a deck and all its cards. This cannot be undone.

Returns 204 No Content on success.

Error codes

401Missing or invalid API key
403Deck belongs to a different user
404Deck not found

Export a deck

GET/api/decks/:id/exportAPI key optional

Downloads a deck as a .json file in the same format accepted by Import JSON. Useful for backing up a deck, sharing it, or re-importing it elsewhere. Public decks are accessible without authentication; private decks require the owner's API key.

The response is sent as a file download (Content-Disposition: attachment) with a filename derived from the deck title.

Response (200)
{
  "name": "Solar System",
  "description": "Key facts about the planets.",
  "coverImage": "https://...",
  "cards": [
    {
      "id": "cm1card1",
      "front": { "title": "How many planets are in the solar system?" },
      "back": { "title": "8" }
    },
    {
      "id": "cm1card2",
      "front": { "title": "What is the largest planet?" },
      "back": { "title": "Jupiter" }
    }
  ]
}

Error codes

401Deck is private — provide the owner's API key
404Deck not found

Cards

Format note: When creating a deck (POST /api/decks), cards use a front/back structure. When reading or writing individual cards, they use question/answer directly.

| Context | Shape | |---------|-------| | POST /api/decks — bulk create | { front: { title, description? }, back: { title, description?, image? } } | | POST /api/decks/:id/cards — add one | { question, answer, imageUrl? } | | GET /api/decks/:id — returned cards | { id, question, answer, imageUrl, position } |

List cards

GET/api/decks/:id/cardsAPI key optional

Lists all visible cards in a deck. Same auth rules as Get a deck: public decks need no auth, private decks require the owner's key. Hidden cards (flagged by the community) are excluded.

Response (200)
{
  "cards": [
    { "id": "cm1card1", "question": "How many planets...", "answer": "8", "imageUrl": null, "position": 0, "createdAt": "...", "updatedAt": "..." },
    { "id": "cm1card2", "question": "Largest planet?", "answer": "Jupiter", "imageUrl": null, "position": 1, "createdAt": "...", "updatedAt": "..." }
  ]
}

Error codes

401Deck is private — provide the owner's API key
404Deck not found

Add a card

POST/api/decks/:id/cardsAPI key required

Adds a single card to a deck you own. If position is omitted the card is appended after the last existing card.

Request body fields

questionstringrequired
answerstringrequired
imageUrlstringoptional
positionnumberoptional
Request body
{
  "question": "What is the speed of light?",
  "answer": "299,792,458 m/s (approximately 3 × 10⁸ m/s)",
  "imageUrl": null
}
Response (201)
{
  "id": "cm1card99",
  "question": "What is the speed of light?",
  "answer": "299,792,458 m/s (approximately 3 × 10⁸ m/s)",
  "imageUrl": null,
  "position": 2,
  "createdAt": "2024-09-20T10:00:00Z"
}

Error codes

401Missing or invalid API key
403Deck belongs to a different user
404Deck not found
422Missing required field: question or answer

Update a card

PATCH/api/decks/:id/cards/:cardIdAPI key required

Updates a card's question, answer, or image. All fields are optional — send only what you want to change.

Request body fields

questionstringoptional
answerstringoptional
imageUrlstringoptional
Request body
{
  "question": "What is the approximate speed of light?",
  "answer": "3 × 10⁸ m/s"
}
Response (200)
{
  "id": "cm1card99",
  "question": "What is the approximate speed of light?",
  "answer": "3 × 10⁸ m/s",
  "imageUrl": null,
  "position": 2,
  "updatedAt": "2024-09-21T09:00:00Z"
}

Error codes

401Missing or invalid API key
403Deck belongs to a different user
404Deck or card not found
422No valid fields to update

Delete a card

DELETE/api/decks/:id/cards/:cardIdAPI key required

Permanently deletes a card. Returns 204 No Content on success.

Error codes

401Missing or invalid API key
403Deck belongs to a different user
404Deck or card not found

Collections

Collections are groups of decks. There are two kinds:

  • Personal collections — created by you, visible only to your account. courseCode is null.
  • Course collections — admin-managed groups linked to a Dal course code (e.g. "INFO 2390"). Publicly readable by anyone.

A deck can belong to at most one personal collection and any number of course collections simultaneously.

List collections

GET/api/collectionsAPI key required

Returns your personal collections (excluding course collections).

Response (200)
{
  "collections": [
    {
      "id": "cm1coll1",
      "name": "My Notes",
      "courseCode": null,
      "deckCount": 3,
      "createdAt": "2024-08-01T00:00:00Z",
      "updatedAt": "2024-09-01T00:00:00Z"
    }
  ]
}

To list all course collections globally, add ?type=course:

GET/api/collections?type=courseAPI key required
Response (200)
{
  "collections": [
    {
      "id": "cm1course1",
      "name": "Introduction to Data Science",
      "courseCode": "INFO 2390",
      "deckCount": 5,
      "createdAt": "2024-08-01T00:00:00Z",
      "updatedAt": "2024-09-01T00:00:00Z"
    }
  ]
}

Error codes

401Missing or invalid API key

Create a collection

POST/api/collectionsAPI key required

Creates a new personal collection. To bootstrap a course collection for a Dal course that doesn't exist yet, include courseCode — this creates the collection and adds an empty community deck automatically.

Request body fields

namestringrequired
courseCodestringoptional

Personal collection

Request body
{ "name": "BIOL 2030 – Cell Biology" }
Response (201)
{
  "id": "cm1coll1",
  "name": "BIOL 2030 – Cell Biology",
  "courseCode": null,
  "deckCount": 0,
  "createdAt": "2024-09-01T12:00:00Z",
  "updatedAt": "2024-09-01T12:00:00Z"
}

Course collection

Request body
{
  "name": "Cell Biology",
  "courseCode": "BIOL 2030"
}
Response (201)
{
  "id": "cm1course2",
  "name": "Cell Biology",
  "courseCode": "BIOL 2030",
  "deckCount": 1,
  "createdAt": "2024-09-01T12:00:00Z",
  "updatedAt": "2024-09-01T12:00:00Z"
}

Course collections are community-owned — any verified Dal student can create one, but only admins can rename or delete them. You can create at most 3 course collections per 24 hours.

Error codes

401Missing or invalid API key
409A collection for that course code already exists — see id in response
422Missing required field: name
429Rate limit exceeded — max 3 course collections per 24 hours

Get a collection

GET/api/collections/:idAPI key optional

Returns a collection and its full deck list. Course collections are publicly readable — no auth needed. Personal collections require the owner's API key.

Response (200)
{
  "id": "cm1coll1",
  "name": "My Notes",
  "courseCode": null,
  "createdAt": "2024-08-01T00:00:00Z",
  "updatedAt": "2024-09-01T00:00:00Z",
  "decks": [
    {
      "id": "cm1abc123",
      "title": "Cell Biology",
      "description": "Key concepts from BIOL 2030",
      "visibility": "PRIVATE",
      "coverImage": null,
      "cardCount": 24,
      "ownerName": "Alice",
      "addedAt": "2024-09-01T12:00:00Z"
    }
  ]
}

Error codes

403Personal collection — provide the owner's API key
404Collection not found

Rename a collection

PATCH/api/collections/:idAPI key required

Request body fields

namestringrequired
Request body
{ "name": "New Name" }
Response (200)
{
  "id": "cm1coll1",
  "name": "New Name",
  "courseCode": null,
  "updatedAt": "2024-09-20T10:00:00Z"
}

Error codes

401Missing or invalid API key
403Collection belongs to a different user, or is a course collection (admin only)
404Collection not found
422Missing required field: name

Delete a collection

DELETE/api/collections/:idAPI key required

Deletes the collection. Decks inside are not deleted — they are simply unlinked. Returns 204 No Content on success. Course collections can only be deleted by admins.

Error codes

401Missing or invalid API key
403Collection belongs to a different user, or is a course collection (admin only)
404Collection not found

Add deck to collection

PUT/api/collections/:id/decks/:deckIdAPI key required

Adds a deck to a collection. Both the collection and the deck must belong to your account. Idempotent — adding a deck already in the collection is a no-op.

If the deck is already in another personal collection it is moved automatically. Course collection memberships are never affected.

Response (200)
{ "collectionId": "cm1coll1", "deckId": "cm1abc123" }

Error codes

401Missing or invalid API key
403Collection or deck belongs to a different user
404Collection or deck not found

Remove deck from collection

DELETE/api/collections/:id/decks/:deckIdAPI key required

Removes a deck from a collection. The deck itself is not deleted. Returns 204 No Content on success.

Error codes

401Missing or invalid API key
403Collection belongs to a different user
404Deck is not in this collection

Status codes

All endpoints follow standard HTTP conventions.

Status codes

200Success
201Created
204Success — no body returned
400Invalid JSON body
401Missing or invalid API key
403Forbidden — resource belongs to a different user
404Resource not found
422Validation error — check the error field in the response body for details
5xxServer error — wait a moment and retry