Skip to main content

Overview

The Timeback Python SDK provides TimebackFastAPI, a ready-made FastAPI integration that creates an APIRouter with all Timeback routes.

Installation

pip install "timeback-sdk[fastapi]"

Server Setup

Timeback instance

Create a module that configures the Timeback instance. TimebackFastAPI is callable as a FastAPI dependency via Depends(timeback):
import os

from timeback.server import (
    TimebackConfig,
    ApiCredentials,
    SsoIdentityConfig,
)
from timeback.server.adapters.fastapi import TimebackFastAPI


def get_user(request):
    session = get_session(request)  # Your session logic
    return {"id": session.user_id, "email": session.email}


def on_callback_success(ctx):
    set_session(id=ctx.user["id"], email=ctx.user["email"])
    return ctx.redirect(ctx.state.get("return_to", "/"))


def on_callback_error(ctx):
    return ctx.redirect("/?error=sso_failed")


timeback = TimebackFastAPI(TimebackConfig(
    env="staging",
    api=ApiCredentials(
        client_id=os.environ["TIMEBACK_API_CLIENT_ID"],
        client_secret=os.environ["TIMEBACK_API_CLIENT_SECRET"],
    ),
    identity=SsoIdentityConfig(
        mode="sso",
        client_id=os.environ["TIMEBACK_SSO_CLIENT_ID"],
        client_secret=os.environ["TIMEBACK_SSO_CLIENT_SECRET"],
        redirect_uri="http://localhost:8000/api/timeback/identity/callback",
        get_user=get_user,
        on_callback_success=on_callback_success,
        on_callback_error=on_callback_error,
    ),
))

App initialization

Mount the Timeback router on your FastAPI app:
app/main.py
from fastapi import FastAPI

from app.timeback import timeback

app = FastAPI()
app.include_router(timeback.router, prefix="/api/timeback")
No lifespan or async setup needed — TimebackFastAPI is fully initialized at construction time.

Usage

Use Depends(timeback) in your own routes for server-side operations like recording activity completion or fetching user data:
app/routes/activities.py
from fastapi import APIRouter, Depends
from timeback.server import TimebackInstance

from app.timeback import timeback

router = APIRouter(prefix="/api/activities")


@router.put("/{activity_id}/complete")
async def complete_activity(
    activity_id: str,
    tb: TimebackInstance = Depends(timeback),
):
    activity = await load_activity(activity_id)
    progress = await load_progress(activity_id)

    await tb.activity.record({
        "user": {"email": progress.student_email},
        "activity": {
            "id": activity.slug,
            "name": activity.name,
            "course": {"code": activity.course_code},
        },
        "metrics": {
            "xp_earned": progress.xp_earned,
            "total_questions": progress.total_questions,
            "correct_questions": progress.correct_questions,
        },
        "run_id": progress.run_id,
    })

    return {"status": "completed"}
You can also use the timeback.user namespace to verify users or fetch profiles without going through the HTTP handlers:
app/routes/users.py
from fastapi import APIRouter, Depends
from timeback.server import TimebackInstance

from app.timeback import timeback

router = APIRouter(prefix="/api/users")


@router.get("/check/{email}")
async def check_user(
    email: str,
    tb: TimebackInstance = Depends(timeback),
):
    result = await tb.user.verify(email)
    return result


@router.get("/profile/{email}")
async def get_profile(
    email: str,
    tb: TimebackInstance = Depends(timeback),
):
    profile = await tb.user.get_profile(email)
    return profile
See stateful activities for the full server-side completion workflow, and user profile for details on verify() and get_profile().
The lessons namespace is also available via Depends(timeback):
app/routes/lessons.py
from fastapi import APIRouter, Depends
from timeback.server import TimebackInstance

from app.timeback import timeback

router = APIRouter(prefix="/api/lessons")


@router.get("/")
async def list_lessons(tb: TimebackInstance = Depends(timeback)):
    return await tb.lessons.list()


@router.post("/{lesson_id}/start")
async def start_lesson(
    lesson_id: str,
    student_id: str,
    tb: TimebackInstance = Depends(timeback),
):
    return await tb.lessons.start({"student": student_id, "lesson": lesson_id})
See the Managed Lessons reference for all server-side operations (list, start, next, submit, complete, attempts, attemptDetails), parameters, and return types.

Next Steps

Managed Lessons

Server-side lessons API reference

Custom Activities

Track learning sessions

Client Adapters

Frontend setup (React, Vue, Svelte, Solid)

Identity

Authentication options