Skip to content

API Reference

Complete reference for all API endpoints in the 2Sigma Backend.

Base URL

http://localhost:8000/api/v1

Interactive Documentation

Authentication

Most endpoints require JWT authentication using the Bearer token scheme.

Adding Authentication Header

Authorization: Bearer YOUR_ACCESS_TOKEN

Getting Tokens

See Authentication Endpoints below.

API Endpoint Groups

  • Authentication - Registration, login, token refresh
  • Users - User management and profiles
  • Universities - University and department management
  • Courses - Course definitions and offerings
  • Enrollments - Course enrollment management
  • Modules - Hierarchical course content structure
  • Content - Learning materials (videos, quizzes, labs)
  • Content Types - Admin content type management
  • Progress - Module and content progress tracking
  • Chat - AI tutoring chat sessions
  • Prompts - Langfuse-style prompt management
  • Admin - Administrative operations

Authentication

Check Email Availability

POST /auth/check-email

Check if an email is available for registration.

Request Body:

{
  "email": "user@example.com"
}

Response:

{
  "available": true
}

Register User

POST /auth/register

Register a new user account.

Request Body:

{
  "email": "user@example.com",
  "password": "SecurePass123",
  "full_name": "John Doe",
  "locale": "en",
  "time_zone": "UTC"
}

Response:

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "bearer"
}

Register with Onboarding

POST /auth/register-with-onboarding

Register user with complete profile and preferences.

Request Body:

{
  "email": "user@example.com",
  "password": "SecurePass123",
  "full_name": "John Doe",
  "profile": {
    "date_of_birth": "2000-01-01",
    "learning_goal": "CAREER_ADVANCEMENT",
    "study_level": "UNDERGRADUATE",
    "grade": "SOPHOMORE"
  },
  "subject_preferences": [1, 2, 3]
}

Login

POST /auth/login

Login with email and password.

Request Body:

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

Response: Same as register (tokens)

Refresh Token

POST /auth/refresh

Get new access token using refresh token.

Headers:

Authorization: Bearer YOUR_REFRESH_TOKEN

Response: New access and refresh tokens


Users

Get Current User

GET /users/me

Get authenticated user's profile.

Auth: Required

Response:

{
  "id": 1,
  "email": "user@example.com",
  "full_name": "John Doe",
  "is_active": true,
  "locale": "en",
  "time_zone": "UTC",
  "current_streak_days": 5,
  "last_activity_date": "2026-01-20",
  "created_at": "2026-01-01T00:00:00Z"
}

Get User Overview

GET /users/me/overview

Get dashboard overview with enrollments, recommendations, and stats.

Auth: Required

Response:

{
  "active_enrollments": [...],
  "recommended_courses": [...],
  "recent_activity": [...],
  "stats": {
    "completed_courses": 5,
    "current_streak": 3
  }
}

Update Current User

PUT /users/me

Update authenticated user's profile.

Auth: Required

Request Body:

{
  "full_name": "Jane Doe",
  "locale": "es",
  "time_zone": "America/New_York"
}

Get User by ID

GET /users/{user_id}

Auth: Required

List Users

GET /users/?skip=0&limit=100

Auth: Required


Courses

List Courses

GET /courses/?university_id=1&skip=0&limit=100

List all courses, optionally filtered by university.

Query Parameters: - university_id (optional) - Filter by university - skip (default: 0) - Pagination offset - limit (default: 100) - Results per page

Response:

[
  {
    "id": 1,
    "title": "Introduction to Computer Science",
    "code": "CS101",
    "description": "Fundamentals of programming",
    "level": "INTRODUCTORY",
    "credit_hours": 3,
    "is_published": true,
    "university_id": 1,
    "department_id": 1
  }
]

Get Course

GET /courses/{course_id}

Get detailed course information.

Create Course

POST /courses/

Auth: Required

Request Body:

{
  "title": "Data Structures",
  "code": "CS201",
  "description": "Study of data structures",
  "level": "INTERMEDIATE",
  "credit_hours": 4,
  "university_id": 1,
  "department_id": 1,
  "primary_subject_id": 1
}

Update Course

PUT /courses/{course_id}

Auth: Required

Delete Course

DELETE /courses/{course_id}

Auth: Required

List Course Offerings

GET /courses/{course_id}/offerings

Get all offerings (terms/instances) for a course.

Create Course Offering

POST /courses/{course_id}/offerings

Auth: Required

Request Body:

{
  "term_name": "Spring 2026",
  "starts_at": "2026-01-15T00:00:00Z",
  "ends_at": "2026-05-15T00:00:00Z",
  "enrollment_start": "2025-12-01T00:00:00Z",
  "enrollment_end": "2026-01-31T00:00:00Z",
  "visibility": "PUBLIC"
}

Get Course Statistics

GET /courses/{course_id}/stats

Auth: Required


Enrollments

Get My Enrollments

GET /enrollments/my-enrollments

Get current user's course enrollments.

Auth: Required

Response:

[
  {
    "id": 1,
    "user_id": 1,
    "course_offering_id": 1,
    "status": "ACTIVE",
    "enrolled_at": "2026-01-01T00:00:00Z",
    "course_offering": {
      "term_name": "Spring 2026",
      "course": {
        "title": "CS101",
        "code": "CS101"
      }
    }
  }
]

Enroll in Course

POST /enrollments/

Auth: Required

Request Body:

{
  "course_offering_id": 1
}

Update Enrollment Status

PUT /enrollments/{enrollment_id}

Auth: Required

Request Body:

{
  "status": "COMPLETED"
}


Modules

Modules form a hierarchical tree structure for course content organization.

List Course Modules

GET /modules/courses/{course_id}/modules

Get all modules for a course (flat list).

List Root Modules

GET /modules/courses/{course_id}/modules/root

Get only top-level modules (entry points).

Get Module

GET /modules/{module_id}

Get Child Modules

GET /modules/{module_id}/children

Get direct children of a module.

Create Module

POST /modules/

Auth: Required

Request Body:

{
  "course_id": 1,
  "parent_module_id": null,
  "title": "Week 1: Introduction",
  "description": "Course introduction",
  "module_type": "UNIT",
  "sequence_index": 0
}

Module Types: COURSE_ROOT, UNIT, CHAPTER, LESSON, TOPIC, SECTION, LAB, QUIZ

Reorder Modules

POST /modules/reorder

Auth: Required

Request Body:

{
  "module_ids": [3, 1, 2]
}


Content

Content items are learning materials within modules.

List Module Content

GET /content/modules/{module_id}/content

Get all content items for a module.

Get Content Item

GET /content/{content_id}

Response:

{
  "id": 1,
  "module_id": 1,
  "title": "Introduction Video",
  "content_type_id": 1,
  "content_type": {
    "name": "video",
    "label": "Video"
  },
  "description": "Course intro video",
  "data_json": {
    "video_url": "https://...",
    "duration": 600
  },
  "sequence_index": 0,
  "estimated_duration_seconds": 600
}

Create Content

POST /content/

Auth: Required

Request Body:

{
  "module_id": 1,
  "course_id": 1,
  "content_type_id": 1,
  "title": "Lecture Video",
  "description": "First lecture",
  "data_json": {
    "video_url": "https://example.com/video.mp4"
  },
  "estimated_duration_seconds": 1800,
  "sequence_index": 0
}


Progress

Track user progress through modules and content.

Get My Module Progress

GET /progress/modules/my-progress?course_offering_id=1

Auth: Required

Create/Update Module Progress

POST /progress/modules

Auth: Required

Request Body:

{
  "module_id": 1,
  "course_offering_id": 1,
  "progress_percent": 50,
  "completed_at": null
}

Get My Content Progress

GET /progress/content/my-progress?course_offering_id=1

Auth: Required

Create/Update Content Progress

POST /progress/content

Auth: Required

Request Body:

{
  "content_item_id": 1,
  "course_offering_id": 1,
  "progress_percent": 100,
  "completed_at": "2026-01-20T10:30:00Z"
}


Chat

AI-powered tutoring chat sessions.

List Chat Sessions

GET /chat/sessions

Auth: Required

Create Chat Session

POST /chat/sessions

Auth: Required

Request Body:

{
  "content_item_id": 1
}

Get Chat Session

GET /chat/sessions/{session_id}

Auth: Required

Send Message (Streaming)

POST /chat/sessions/{session_id}/messages

Auth: Required

Response: Server-Sent Events (SSE) stream

Request Body:

{
  "content": "Explain recursion"
}

Generate Greeting

POST /chat/sessions/{session_id}/greeting

Auth: Required

Generate AI greeting for new session.

Share Session

POST /chat/sessions/{session_id}/share

Auth: Required

Response:

{
  "share_token": "abc123def456",
  "share_url": "/api/v1/chat/share/abc123def456"
}

Get Shared Session (Public)

GET /chat/share/{share_token}

Auth: Not required


Prompts

Langfuse-style versioned prompt management with label-based version resolution (admin feature).

List Prompts

GET /prompts/?name=tutor&label=production&tag=math&page=1&page_size=20

Auth: Required (INSTRUCTOR+)

Query Parameters: - name (optional) - Filter by name (ILIKE) - label (optional) - Filter by label - tag (optional) - Filter by tag - page (default: 1) - page_size (default: 20)

Response: Prompts grouped by name with aggregated versions, labels, and tags.

{
  "data": [
    {
      "name": "General Protocol",
      "type": "text",
      "versions": [1, 2, 3],
      "labels": ["production", "latest"],
      "tags": ["core", "protocol"],
      "last_updated_at": "2026-02-06T10:00:00Z"
    }
  ],
  "total": 1,
  "page": 1,
  "page_size": 20
}

Get Prompt by Name

GET /prompts/{prompt_name}?label=production

Auth: Required (INSTRUCTOR+)

Query Parameters: - version (optional int) - Resolve specific version - label (optional str) - Resolve by label (default: production) - Cannot specify both version and label

Response: Includes resolved prompt text with all dependencies inlined.

{
  "id": 5,
  "name": "Video Tutor",
  "version": 3,
  "type": "text",
  "prompt": "You are a helpful tutor for {{title}}...\n@@@langfusePrompt:name=General Protocol|label=production@@@",
  "config": {},
  "labels": ["production"],
  "tags": ["tutor", "video"],
  "commit_message": "Added protocol reference",
  "created_by": "42",
  "created_at": "2026-02-06T10:00:00Z",
  "updated_at": "2026-02-06T10:00:00Z",
  "dependencies": [
    {"child_name": "General Protocol", "child_version": null, "child_label": "production"}
  ],
  "resolved_prompt": "You are a helpful tutor for {{title}}...\nFollow these rules: ...",
  "resolution_graph": {"root": {"name": "Video Tutor", "version": 3, "id": 5}, "dependencies": {}}
}

Get All Versions

GET /prompts/{prompt_name}/versions?page=1&page_size=20

Auth: Required (INSTRUCTOR+)

Response:

{
  "versions": [
    {
      "id": 5,
      "name": "Video Tutor",
      "version": 3,
      "labels": ["production", "latest"],
      "commit_message": "Added protocol reference",
      "created_by": "42",
      "creator": "Jane Doe",
      "created_at": "2026-02-06T10:00:00Z"
    }
  ],
  "total": 3
}

Create Prompt

POST /prompts/

Auth: Required (INSTRUCTOR+)

Request Body:

{
  "name": "Video Tutor",
  "prompt": "You are a helpful tutor for {{title}}...",
  "config": {},
  "labels": ["production"],
  "tags": ["tutor", "video"],
  "commit_message": "Initial version"
}

Response: 201 Created with PromptResponse

Notes: - Version auto-increments per prompt name - latest label is auto-assigned to new versions - Dependencies are parsed from @@@langfusePrompt:...@@@ tags in prompt text - Tags are synchronized across all versions of a prompt name

Set Labels

PATCH /prompts/{prompt_name}/versions/{version}/labels

Auth: Required (INSTRUCTOR+; PLATFORM_ADMIN for protected labels)

Request Body:

{
  "labels": ["production", "staging"]
}

Notes: - latest cannot be manually set (auto-managed) - Labels are unique per prompt name — setting a label on one version removes it from others

Update Tags

PATCH /prompts/{prompt_name}/tags

Auth: Required (INSTRUCTOR+)

Request Body:

{
  "tags": ["core", "protocol", "v2"]
}

Response: {"success": true}

Note: Updates tags on ALL versions of the prompt name.

Delete Prompt (All Versions)

DELETE /prompts/{prompt_name}

Auth: Required (PLATFORM_ADMIN only)

Response: 204 No Content

Note: Blocked if other prompts depend on any version/label of this prompt.

Delete Prompt Version

DELETE /prompts/{prompt_name}/versions/{version}

Auth: Required (PLATFORM_ADMIN only)

Response: 204 No Content

Note: If the deleted version had the latest label, it is reassigned to the next highest version.

Get All Labels

GET /prompts/labels

Auth: Required (INSTRUCTOR+)

Response: ["production", "latest", "staging", "experiment-a"]

Get All Names

GET /prompts/names

Auth: Required (INSTRUCTOR+)

Response: [{"name": "General Protocol", "id": 1}, {"name": "Video Tutor", "id": 5}]

GET /prompts/link-options

Auth: Required (INSTRUCTOR+)

Response: Used by the prompt reference insertion dialog.

[
  {
    "name": "General Protocol",
    "versions": [1, 2, 3],
    "labels": ["production", "latest"]
  }
]

Preview Prompt

POST /prompts/preview

Auth: Required (INSTRUCTOR+)

Request Body:

{
  "prompt_text": "Hello {{title}}, @@@langfusePrompt:name=General Protocol|label=production@@@",
  "variables": {"title": "Math 101"}
}

Response:

{
  "rendered_prompt": "Hello Math 101, Follow these rules: ...",
  "variables_used": ["title"],
  "dependencies_found": [
    {"child_name": "General Protocol", "child_version": null, "child_label": "production"}
  ]
}


Admin

Administrative operations.

Update AWS Credentials

POST /admin/aws-credentials

Auth: Required (admin)

Request Body:

{
  "aws_access_key_id": "AKIAIOSFODNN7EXAMPLE",
  "aws_secret_access_key": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
  "aws_session_token": "optional"
}

Credentials are encrypted and stored in database.

Check AWS Credentials Status

GET /admin/aws-credentials/status

Auth: Required (admin)

Test AWS Bedrock Connection

POST /admin/aws-credentials/test

Auth: Required (admin)


Error Responses

All endpoints follow consistent error format:

{
  "detail": "Error message"
}

Status Codes: - 200 - Success - 201 - Created - 204 - No Content (successful deletion) - 400 - Bad Request (invalid data) - 401 - Unauthorized (missing/invalid token) - 403 - Forbidden (insufficient permissions) - 404 - Not Found - 422 - Validation Error - 500 - Internal Server Error

Validation Error Example:

{
  "detail": [
    {
      "loc": ["body", "email"],
      "msg": "value is not a valid email address",
      "type": "value_error.email"
    }
  ]
}

Next Steps