API Reference#

The FastAPI application called “app”.

Application#

FastAPI application entry point.

Creates the FastAPI application instance, configures CORS middleware, registers the API router, and defines the application lifespan for startup/shutdown hooks.

app.main.custom_generate_unique_id(route)#

Generate a deterministic OpenAPI operation ID for a route.

The ID is formed as "{tag}-{route_name}", using the first tag assigned to the route or "default" when no tags are present.

Return type:

str

Args:

route: The APIRoute to generate an ID for.

Returns:

A unique string identifier for the route’s OpenAPI operation.

app.main.lifespan(app)#

Manage application startup and shutdown events.

On startup the data-import pipeline is triggered (subject to environment-variable flags). Shutdown is currently a no-op.

Return type:

AsyncGenerator[None, None]

Args:

app: The FastAPI application instance.

Yields:

Control to the running application between startup and shutdown.

Routes#

app.api.routes.items.create_item(*, session, current_user, item_in)#

Create new item.

Return type:

Any

app.api.routes.items.delete_item(session, current_user, id)#

Delete an item.

Return type:

Message

app.api.routes.items.read_item(session, current_user, id)#

Get item by ID.

Return type:

Any

app.api.routes.items.read_items(session, current_user, skip=0, limit=100)#

Retrieve items.

Return type:

Any

app.api.routes.items.update_item(*, session, current_user, id, item_in)#

Update an item.

Return type:

Any

app.api.routes.login.force_password_reset_for_users(session, body)#

Force password reset for a targeted list of users or all active users.

Return type:

Message

app.api.routes.login.login_access_token(session, form_data)#

OAuth2 compatible token login, get an access token for future requests

Return type:

Token

app.api.routes.login.recover_password(email, session)#

Password Recovery

Return type:

Message

app.api.routes.login.recover_password_html_content(email, session)#

HTML Content for Password Recovery

Return type:

Any

app.api.routes.login.reset_password(session, body)#

Reset password

Return type:

Message

app.api.routes.login.test_token(current_user)#

Test access token

Return type:

Any

class app.api.routes.private.PrivateUserCreate(**data)#

Bases: BaseModel

email: str#
full_name: str#
is_verified: bool#
model_config: ClassVar[ConfigDict] = {}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

password: str#
app.api.routes.private.create_user(user_in, session)#

Create a new user.

Return type:

Any

app.api.routes.users.create_user(*, session, user_in)#

Create new user.

Return type:

Any

app.api.routes.users.delete_user(session, current_user, user_id)#

Delete a user.

Return type:

Message

app.api.routes.users.delete_user_me(session, current_user)#

Delete own user.

Return type:

Any

app.api.routes.users.read_user_by_id(user_id, session, current_user)#

Get a specific user by id.

Return type:

Any

app.api.routes.users.read_user_me(current_user)#

Get current user.

Return type:

Any

app.api.routes.users.read_users(session, skip=0, limit=100)#

Retrieve users.

Return type:

Any

app.api.routes.users.register_user(session, user_in)#

Create new user without the need to be logged in.

Return type:

Any

app.api.routes.users.update_password_me(*, session, body, current_user)#

Update own password.

Return type:

Any

app.api.routes.users.update_user(*, session, user_id, user_in)#

Update a user.

Return type:

Any

app.api.routes.users.update_user_me(*, session, user_in, current_user)#

Update own user.

Return type:

Any

async app.api.routes.utils.health_check()#
Return type:

bool

app.api.routes.utils.test_email(email_to)#

Test emails.

Return type:

Message

app.api.routes.censusdata.count_of_census_data(session, current_user, skip=0, limit=100)#

Retrieve census data.

Return type:

Any

app.api.routes.censusdata.create_census_data(*, session, current_user, census_data_in)#

Create new census data.

Return type:

Any

app.api.routes.censusdata.delete_census_data(*, session, current_user, id)#

Delete census data by ID.

Return type:

Any

app.api.routes.censusdata.read_census_data(session, current_user, id)#

Get census data by ID.

Return type:

Any

app.api.routes.censusdata.update_census_data(*, session, current_user, id, census_data_in)#

Update census data by ID.

Return type:

Any

app.api.routes.schools.read_schools(session, q=None, skip=0, limit=10)#

Retrieve schools.

Return type:

Any

app.api.routes.schools.read_schools_summary(session, q=None, skip=0, limit=10)#

Retrieve schools with a summarized view.

Return type:

Any

app.api.routes.academic_indicators.create_academic_indicator(*, session, current_user, indicator_in)#

Create new academic indicator. Superuser only.

Return type:

Any

app.api.routes.academic_indicators.delete_academic_indicator(session, current_user, id)#

Delete an academic indicator. Superuser only.

Return type:

Message

app.api.routes.academic_indicators.get_dashboard_data(session, q=Query(PydanticUndefined))#

Get aggregated dashboard data for a specific CDS code. Returns the ‘ALL’ student group data for the most recent reporting year.

Return type:

Any

app.api.routes.academic_indicators.get_dashboard_summary(session, cds=Query(PydanticUndefined), reportingyear=Query(2025), studentgroup=Query(ALL))#

Get all indicator summaries for a school/district/state.

Returns summary data for all 8 accountability indicators for the specified CDS code, reporting year, and student group.

Return type:

Any

app.api.routes.academic_indicators.get_equity_report(session, cds=Query(PydanticUndefined), indicator=Query(PydanticUndefined), reportingyear=Query(2025))#

Get student group breakdown for an indicator.

Returns color-coded performance data for all student groups within a school/district/state for a specific indicator.

Return type:

Any

app.api.routes.academic_indicators.get_last_viewed_cds(current_user)#

Get the user’s last viewed CDS code.

Return type:

dict[str, str | None]

app.api.routes.academic_indicators.read_academic_indicator(session, id)#

Get academic indicator by ID.

Return type:

Any

app.api.routes.academic_indicators.read_academic_indicators(session, skip=0, limit=100, cds=Query(None), studentgroup=Query(None), reportingyear=Query(None))#

Retrieve academic indicators with optional filters.

Return type:

Any

app.api.routes.academic_indicators.update_academic_indicator(*, session, current_user, id, indicator_in)#

Update an academic indicator. Superuser only.

Return type:

Any

app.api.routes.academic_indicators.update_user_preferences(session, current_user, preferences)#

Update user preferences including last viewed school.

Return type:

Any

Core#

class app.core.config.Settings(_case_sensitive=None, _nested_model_default_partial_update=None, _env_prefix=None, _env_prefix_target=None, _env_file=PosixPath('.'), _env_file_encoding=None, _env_ignore_empty=None, _env_nested_delimiter=None, _env_nested_max_split=None, _env_parse_none_str=None, _env_parse_enums=None, _cli_prog_name=None, _cli_parse_args=None, _cli_settings_source=None, _cli_parse_none_str=None, _cli_hide_none_type=None, _cli_avoid_json=None, _cli_enforce_required=None, _cli_use_class_docs_for_groups=None, _cli_exit_on_error=None, _cli_prefix=None, _cli_flag_prefix_char=None, _cli_implicit_flags=None, _cli_ignore_unknown_args=None, _cli_kebab_case=None, _cli_shortcuts=None, _secrets_dir=None, _build_sources=None, **values)#

Bases: BaseSettings

Use the top level .env file (one level above ./backend/). Access not expires in 60 minutes * 24 hours * 8 days = 8 days

ACCESS_TOKEN_EXPIRE_MINUTES: int#
API_V1_STR: str#
BACKEND_CORS_ORIGINS: Annotated[list[AnyUrl] | str, BeforeValidator(func=parse_cors, json_schema_input_type=PydanticUndefined)]#
CLOUD_SQL_INSTANCE_CONNECTION_NAME: str | None#
DATABASE_URL: str | None#
DB_CONNECTION_MODE: Literal['auto', 'local', 'cloudsql']#
EMAILS_FROM_EMAIL: EmailStr | None#
EMAILS_FROM_NAME: str | None#
EMAIL_RESET_TOKEN_EXPIRE_HOURS: int#
EMAIL_TEST_USER: EmailStr#
ENVIRONMENT: Literal['local', 'staging', 'production']#
FIRST_SUPERUSER: EmailStr#
FIRST_SUPERUSER_PASSWORD: str#
FRONTEND_HOST: str#
POSTGRES_DB: str | None#
POSTGRES_PASSWORD: str | None#
POSTGRES_PORT: int#
POSTGRES_SERVER: str | None#
POSTGRES_USER: str | None#
PROJECT_NAME: str#
SECRET_KEY: str#
SENTRY_DSN: HttpUrl | None#
SMTP_HOST: str | None#
SMTP_PASSWORD: str | None#
SMTP_PORT: int#
SMTP_SSL: bool#
SMTP_TLS: bool#
SMTP_USER: str | None#
property SQLALCHEMY_DATABASE_URI: str#
property all_cors_origins: list[str]#
property emails_enabled: bool#
model_config: ClassVar[SettingsConfigDict] = {'arbitrary_types_allowed': True, 'case_sensitive': False, 'cli_avoid_json': False, 'cli_enforce_required': False, 'cli_exit_on_error': True, 'cli_flag_prefix_char': '-', 'cli_hide_none_type': False, 'cli_ignore_unknown_args': False, 'cli_implicit_flags': False, 'cli_kebab_case': False, 'cli_parse_args': None, 'cli_parse_none_str': None, 'cli_prefix': '', 'cli_prog_name': None, 'cli_shortcuts': None, 'cli_use_class_docs_for_groups': False, 'enable_decoding': True, 'env_file': '/home/runner/work/app-capanel-doc/app-capanel-doc/.env', 'env_file_encoding': None, 'env_ignore_empty': True, 'env_nested_delimiter': None, 'env_nested_max_split': None, 'env_parse_enums': None, 'env_parse_none_str': None, 'env_prefix': '', 'env_prefix_target': 'variable', 'extra': 'ignore', 'json_file': None, 'json_file_encoding': None, 'nested_model_default_partial_update': False, 'protected_namespaces': ('model_validate', 'model_dump', 'settings_customise_sources'), 'secrets_dir': None, 'toml_file': None, 'validate_default': True, 'yaml_config_section': None, 'yaml_file': None, 'yaml_file_encoding': None}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

app.core.config.parse_cors(v)#
Return type:

list[str] | str

app.core.database.init_db(session)#

Creates one superuser.

Return type:

None

app.core.security.create_access_token(subject, expires_delta)#
Return type:

str

app.core.security.get_password_hash(password)#
Return type:

str

app.core.security.verify_password(plain_password, hashed_password)#
Return type:

tuple[bool, str | None]

Data models and CRUD#

class app.model.models.Message(**data)#

Bases: SQLModel

Generic message

message: str#
model_config: ClassVar[ConfigDict] = {'from_attributes': True, 'registry': PydanticUndefined}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class app.model.models.Token(**data)#

Bases: SQLModel

A JSON payload containing the access token.

access_token: str#
model_config: ClassVar[ConfigDict] = {'from_attributes': True, 'registry': PydanticUndefined}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

token_type: str#
class app.model.models.TokenPayload(**data)#

Bases: SQLModel

The contents of the JWT token.

model_config: ClassVar[ConfigDict] = {'from_attributes': True, 'registry': PydanticUndefined}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

sub: str | None#
app.service.crud.authenticate(*, session, email, password)#
Return type:

User | None

app.service.crud.create_item(*, session, item_in, owner_id)#
Return type:

Item

app.service.crud.create_school(*, session, school_create)#
Return type:

School

app.service.crud.create_user(*, session, user_create)#
Return type:

User

app.service.crud.get_user_by_email(*, session, email)#
Return type:

User | None

app.service.crud.update_user(*, session, db_user, user_in)#
Return type:

Any

Utilities#

General-purpose utilities for the application.

Provides helpers for environment-variable parsing, email rendering and delivery, JWT token generation/verification, and datetime helpers.

class app.core.utils.EmailData(html_content, subject)#

Bases: object

Container for a rendered email ready to be sent.

Attributes:

html_content: The rendered HTML body of the email. subject: The subject line of the email.

html_content: str#
subject: str#
app.core.utils.env_bool(name, default)#

Read an environment variable and interpret it as a boolean.

Truthy values are "1", "true", "yes", "y", and "on" (case-insensitive). Anything else is considered falsy.

Return type:

bool

Args:

name: Name of the environment variable. default: Value to return when the variable is not set.

Returns:

The parsed boolean, or default when the variable is absent.

app.core.utils.generate_new_account_email(email_to, username, password)#

Generate a welcome email for a newly created account.

Return type:

EmailData

Args:

email_to: Recipient email address. username: The new user’s login name. password: The new user’s initial password.

Returns:

An EmailData instance with the rendered welcome email.

app.core.utils.generate_password_reset_token(email)#

Create a signed JWT for password-reset flows.

The token contains exp, nbf, and sub claims and is signed with the application’s SECRET_KEY.

Return type:

str

Args:

email: The user’s email address, stored as the sub claim.

Returns:

The encoded JWT string.

app.core.utils.generate_reset_password_email(email_to, email, token)#

Generate a password-reset email containing a one-time link.

Return type:

EmailData

Args:

email_to: Recipient email address. email: The username / email displayed in the email body. token: JWT token embedded in the reset link.

Returns:

An EmailData instance with the rendered reset email.

app.core.utils.generate_test_email(email_to)#

Generate a test email for verifying SMTP configuration.

Return type:

EmailData

Args:

email_to: Recipient email address.

Returns:

An EmailData instance with the rendered test email.

app.core.utils.get_datetime_utc()#

Return the current UTC datetime.

Return type:

datetime

Returns:

A timezone-aware datetime.datetime in UTC.

app.core.utils.parse_csv_set(raw)#

Parse a comma-separated string into a set of stripped, non-empty values.

Return type:

set[str] | None

Args:

raw: The raw comma-separated string (e.g. "2024, 2025").

Returns:

A set[str] of the parsed values, or None if the result would be empty.

app.core.utils.render_email_template(*, template_name, context)#

Render a Jinja2 email template to an HTML string.

Templates are loaded from the email-templates/build/ directory relative to the app package.

Return type:

str

Args:

template_name: Filename of the template (e.g. "test_email.html"). context: Dictionary of variables to pass into the template.

Returns:

The rendered HTML string.

app.core.utils.send_email(*, email_to, subject='', html_content='')#

Send an email via SMTP using the application settings.

Raises an AssertionError if email sending is not configured.

Return type:

None

Args:

email_to: Recipient email address. subject: Email subject line. html_content: Rendered HTML body.

app.core.utils.verify_password_reset_token(token)#

Decode and validate a password-reset JWT.

Return type:

str | None

Args:

token: The JWT string to verify.

Returns:

The sub claim (email) if the token is valid, or None if verification fails.