Skip to content

Latest commit

 

History

History
657 lines (534 loc) · 9.31 KB

File metadata and controls

657 lines (534 loc) · 9.31 KB

Flashcard API Documentation

Complete REST API documentation for the flashcard backend.

Base URL

http://localhost:3001/api

Authentication

Most endpoints require a JWT token. Include it in the Authorization header:

Authorization: Bearer <your-jwt-token>

Endpoints

🔐 Authentication

Register New User

POST /auth/register

Body:

{
  "email": "user@example.com",
  "username": "john_doe",
  "password": "secure_password123"
}

Response (201):

{
  "user": {
    "id": "uuid",
    "email": "user@example.com",
    "username": "john_doe",
    "createdAt": "2024-01-15T10:00:00.000Z"
  },
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Login

POST /auth/login

Body:

{
  "email": "user@example.com",
  "password": "secure_password123"
}

Response (200):

{
  "user": {
    "id": "uuid",
    "email": "user@example.com",
    "username": "john_doe"
  },
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Get Current User

GET /auth/me

Headers:

Authorization: Bearer <token>

Response (200):

{
  "id": "uuid",
  "email": "user@example.com",
  "username": "john_doe",
  "createdAt": "2024-01-15T10:00:00.000Z"
}

📚 Decks

List All Decks

GET /decks

Headers:

Authorization: Bearer <token>

Response (200):

[
  {
    "id": "deck-uuid-1",
    "name": "Spanish Vocabulary",
    "description": "Common Spanish words",
    "createdAt": "2024-01-15T10:00:00.000Z",
    "updatedAt": "2024-01-15T10:00:00.000Z",
    "userId": "user-uuid",
    "_count": {
      "cards": 25
    }
  }
]

Get Single Deck

GET /decks/:deckId

Headers:

Authorization: Bearer <token>

Response (200):

{
  "id": "deck-uuid",
  "name": "Spanish Vocabulary",
  "description": "Common Spanish words",
  "createdAt": "2024-01-15T10:00:00.000Z",
  "updatedAt": "2024-01-15T10:00:00.000Z",
  "userId": "user-uuid",
  "_count": {
    "cards": 25
  }
}

Create Deck

POST /decks

Headers:

Authorization: Bearer <token>
Content-Type: application/json

Body:

{
  "name": "Spanish Vocabulary",
  "description": "Common Spanish words"
}

Response (201):

{
  "id": "deck-uuid",
  "name": "Spanish Vocabulary",
  "description": "Common Spanish words",
  "createdAt": "2024-01-15T10:00:00.000Z",
  "updatedAt": "2024-01-15T10:00:00.000Z",
  "userId": "user-uuid"
}

Update Deck

PATCH /decks/:deckId

Headers:

Authorization: Bearer <token>
Content-Type: application/json

Body:

{
  "name": "Updated Deck Name",
  "description": "Updated description"
}

Response (200):

{
  "id": "deck-uuid",
  "name": "Updated Deck Name",
  "description": "Updated description",
  "createdAt": "2024-01-15T10:00:00.000Z",
  "updatedAt": "2024-01-15T11:00:00.000Z",
  "userId": "user-uuid"
}

Delete Deck

DELETE /decks/:deckId

Headers:

Authorization: Bearer <token>

Response (204):

No content

🎴 Cards

List Cards in Deck

GET /cards/deck/:deckId

Headers:

Authorization: Bearer <token>

Response (200):

[
  {
    "id": "card-uuid-1",
    "front": "Hola",
    "back": "Hello",
    "easeFactor": 2.5,
    "interval": 0,
    "repetitions": 0,
    "dueDate": "2024-01-15T10:00:00.000Z",
    "createdAt": "2024-01-15T10:00:00.000Z",
    "updatedAt": "2024-01-15T10:00:00.000Z",
    "deckId": "deck-uuid"
  }
]

Get Single Card

GET /cards/:cardId

Headers:

Authorization: Bearer <token>

Response (200):

{
  "id": "card-uuid",
  "front": "Hola",
  "back": "Hello",
  "easeFactor": 2.5,
  "interval": 0,
  "repetitions": 0,
  "dueDate": "2024-01-15T10:00:00.000Z",
  "createdAt": "2024-01-15T10:00:00.000Z",
  "updatedAt": "2024-01-15T10:00:00.000Z",
  "deckId": "deck-uuid",
  "deck": {
    "id": "deck-uuid",
    "name": "Spanish Vocabulary",
    "userId": "user-uuid"
  }
}

Create Card

POST /cards

Headers:

Authorization: Bearer <token>
Content-Type: application/json

Body:

{
  "deckId": "deck-uuid",
  "front": "Hola",
  "back": "Hello"
}

Response (201):

{
  "id": "card-uuid",
  "front": "Hola",
  "back": "Hello",
  "easeFactor": 2.5,
  "interval": 0,
  "repetitions": 0,
  "dueDate": "2024-01-15T10:00:00.000Z",
  "createdAt": "2024-01-15T10:00:00.000Z",
  "updatedAt": "2024-01-15T10:00:00.000Z",
  "deckId": "deck-uuid"
}

Update Card

PATCH /cards/:cardId

Headers:

Authorization: Bearer <token>
Content-Type: application/json

Body:

{
  "front": "¡Hola!",
  "back": "Hello!"
}

Response (200):

{
  "id": "card-uuid",
  "front": "¡Hola!",
  "back": "Hello!",
  "easeFactor": 2.5,
  "interval": 0,
  "repetitions": 0,
  "dueDate": "2024-01-15T10:00:00.000Z",
  "createdAt": "2024-01-15T10:00:00.000Z",
  "updatedAt": "2024-01-15T11:00:00.000Z",
  "deckId": "deck-uuid"
}

Delete Card

DELETE /cards/:cardId

Headers:

Authorization: Bearer <token>

Response (204):

No content

🧠 Study

Get Due Cards for Specific Deck

GET /study/deck/:deckId/due

Headers:

Authorization: Bearer <token>

Response (200):

{
  "card": {
    "id": "card-uuid",
    "front": "Hola",
    "back": "Hello",
    "easeFactor": 2.5,
    "interval": 0,
    "repetitions": 0,
    "dueDate": "2024-01-15T10:00:00.000Z",
    "createdAt": "2024-01-15T10:00:00.000Z",
    "updatedAt": "2024-01-15T10:00:00.000Z",
    "deckId": "deck-uuid"
  }
}

Response when no cards due:

{
  "card": null,
  "message": "No cards due for review"
}

Get All Due Cards (All Decks)

GET /study/due

Headers:

Authorization: Bearer <token>

Response (200):

{
  "count": 12,
  "cards": [
    {
      "id": "card-uuid-1",
      "front": "Hola",
      "back": "Hello",
      "easeFactor": 2.5,
      "interval": 0,
      "repetitions": 0,
      "dueDate": "2024-01-15T10:00:00.000Z",
      "deckId": "deck-uuid-1",
      "deck": {
        "id": "deck-uuid-1",
        "name": "Spanish Vocabulary"
      }
    }
  ]
}

Submit Answer

POST /study/answer

Headers:

Authorization: Bearer <token>
Content-Type: application/json

Body:

{
  "cardId": "card-uuid",
  "quality": 4
}

Quality Scale (SM-2 Algorithm):

  • 5 - Perfect response
  • 4 - Correct response after hesitation
  • 3 - Correct response with difficulty
  • 2 - Incorrect; correct answer seemed easy to recall
  • 1 - Incorrect; correct answer remembered
  • 0 - Complete blackout

Response (200):

{
  "card": {
    "id": "card-uuid",
    "front": "Hola",
    "back": "Hello",
    "easeFactor": 2.6,
    "interval": 1,
    "repetitions": 1,
    "dueDate": "2024-01-16T10:00:00.000Z",
    "createdAt": "2024-01-15T10:00:00.000Z",
    "updatedAt": "2024-01-15T10:30:00.000Z",
    "deckId": "deck-uuid"
  },
  "nextReview": "2024-01-16T10:00:00.000Z"
}

Get Study Statistics

GET /study/stats

Headers:

Authorization: Bearer <token>

Response (200):

{
  "totalCards": 150,
  "dueCards": 12,
  "reviewsToday": 25,
  "totalDecks": 5
}

Error Responses

400 Bad Request

{
  "error": [
    {
      "code": "invalid_type",
      "expected": "string",
      "received": "undefined",
      "path": ["email"],
      "message": "Required"
    }
  ]
}

401 Unauthorized

{
  "error": "Invalid or expired token"
}

404 Not Found

{
  "error": "Deck not found"
}

500 Internal Server Error

{
  "error": "Internal server error"
}

Example Usage with cURL

Complete Workflow

# 1. Register
TOKEN=$(curl -s -X POST http://localhost:3001/api/auth/register \
  -H "Content-Type: application/json" \
  -d '{"email":"test@example.com","username":"test","password":"password123"}' \
  | jq -r '.token')

# 2. Create deck
DECK_ID=$(curl -s -X POST http://localhost:3001/api/decks \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Spanish","description":"Spanish words"}' \
  | jq -r '.id')

# 3. Create card
CARD_ID=$(curl -s -X POST http://localhost:3001/api/cards \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"deckId\":\"$DECK_ID\",\"front\":\"Hola\",\"back\":\"Hello\"}" \
  | jq -r '.id')

# 4. Get due cards
curl -s -X GET http://localhost:3001/api/study/due \
  -H "Authorization: Bearer $TOKEN" | jq '.'

# 5. Answer card (quality 4 = good)
curl -s -X POST http://localhost:3001/api/study/answer \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"cardId\":\"$CARD_ID\",\"quality\":4}" | jq '.'

Rate Limiting

Currently no rate limiting is implemented. In production, consider adding:

  • express-rate-limit for API endpoints
  • Per-user limits on deck/card creation

CORS

CORS is currently open (*). Update in production:

// src/index.ts
app.use(cors({
  origin: 'https://your-frontend-domain.com',
  credentials: true
}));