A FastAPI-based REST API for accessing educational institution data across multiple schools and databases. It provides standardized access to student, course, financial aid, LLM recommendation, and analysis-ready data, plus a flexible data upload pipeline.
- Multiple Institution Support – Unified access to 5 educational institution databases
- Standardized Endpoints – Consistent API structure across all institutions
- Unified Querying –
/unifiedendpoints to query any database/table from a single entrypoint - Pagination & Filtering – Built-in support for large datasets and common filters
- Data Uploads – Upload CSV/Excel to append data with dynamic column mapping
- Analysis-Ready Tables – Access cleaned, enriched, and join-ready views per school
- Python 3.8+
- MySQL/MariaDB
- pip (Python package manager)
-
Clone the repository
git clone https://github.com/syntex-data/devcolor-backend-schools.git cd devcolor-backend-schools -
Set up a virtual environment
python -m venv venv .\venv\Scripts\Activate.ps1 # Windows source venv/bin/activate # Linux/Mac
-
Install dependencies
pip install -r requirements.txt
-
Configure environment variables
Copy
.env.exampleto.envand update it with your database credentials:DB_HOST=your_database_host DB_USER=your_username DB_PASSWORD=your_password DB_PORT=3306
Start the development server from the project root:
uvicorn api.main:app --reloadThe API will be available at http://localhost:8000.
Once the server is running, the interactive docs are available at:
- Swagger UI:
http://localhost:8000/docs - ReDoc:
http://localhost:8000/redoc
The main FastAPI app is defined in api/main.py and includes routers for:
| Prefix | Description |
|---|---|
/al |
Bishop State Community College |
/csusb |
California State University San Bernardino |
/kctcs |
Kentucky Community and Technical College System |
/ky |
Thomas More University |
/oh |
University of Akron |
/upload |
Data upload endpoints |
/unified |
Unified querying across all databases/tables |
The root endpoint (GET /) returns API info, available databases, and key endpoint prefixes.
| Code | Full Name | Database Name |
|---|---|---|
| AL | Bishop State Community College | Bishop_State_Community_College |
| CSUSB | California State University, San Bernardino | California_State_University_San_Bernardino |
| KCTCS | Kentucky Community and Technical College System | Kentucky_Community_and_Technical_College_System |
| KY | Thomas More University | Thomas_More_University |
| OH | University of Akron | University_of_Akron |
Each school has its own router mounted under a lowercase prefix (e.g. /al, /csusb). Every prefix exposes the same set of endpoints, shown below using OH – University of Akron as an example.
GET /oh/– Database infoGET /oh/cohorts– List cohort recordsGET /oh/courses– List course recordsGET /oh/financial-aid– List financial aid recordsGET /oh/llm-recommendations– List LLM recommendation recordsGET /oh/analysis-ready– List analysis-ready records (fromar_oh)GET /oh/{table_name}/count– Count records in a specific table, wheretable_nameis one ofcohort,course,financial_aid,llm_recommendations,ar_oh
The same pattern applies to /al, /csusb, /kctcs, and /ky.
The /unified router lets you query any database/table from a single endpoint, instead of going through school-specific routes.
Query data with pagination and optional filters.
Query parameters:
| Parameter | Required | Notes |
|---|---|---|
database |
Yes | AL, CSUSB, KCTCS, KY, OH |
table |
Yes | cohort, course, financial_aid, llm_recommendations, analysis_ready |
limit |
No | Default 100, max 1000 |
offset |
No | Default 0 |
student_guid |
No | |
cohort |
No | |
academic_year |
No | |
institution_id |
No |
Examples:
/unified/data?database=KY&table=cohort&limit=10/unified/data?database=AL&table=course&student_guid=ABC123/unified/data?database=CSUSB&table=analysis_ready&cohort=2020
Returns the count of records matching the same filter set as /unified/data.
Lists all available databases with codes and full names.
Uploads are handled by the /upload router and support CSV/Excel files with dynamic column mapping.
Returns metadata about the upload system, including:
- Supported formats: CSV, Excel (
.csv,.xlsx,.xls) - Supported tables:
cohort,course,financial_aid - Supported databases:
AL,CSUSB,KCTCS,KY,OH - Required fields per table
- Rules for unknown/dynamic columns
Uploads a CSV or Excel file to append data to a specific table.
Path parameters:
database: one ofAL,CSUSB,KCTCS,KY,OHtable: one ofcohort,course,financial_aid
Requirements:
- File must be
.csv,.xlsx, or.xls - Must include a
dataset_typecolumn with valuesR(real data) orS(synthetic data) - Must include all required fields for the target table
- Up to 10 unknown columns will be mapped to
new_field1–new_field10
Response includes: success flag, target table, rows inserted/total rows, upload timestamp, file name, and column mapping details (including unknown columns).
Returns template information for a specific table (cohort, course, or financial_aid), including required fields and all available fields.
Most list endpoints support:
limit– number of records to return (default: 100, max: 1000)offset– number of records to skip (default: 0)
Example:
GET /al/cohorts?limit=10&offset=20Standard HTTP status codes indicate success or failure:
200 OK– Request was successful400 Bad Request– Invalid request parameters404 Not Found– Resource not found500 Internal Server Error– Server error (including DB connection issues)
Database connections are configured in db_operations/connection.py and use environment variables declared in .env:
DB_HOST=your_database_host
DB_USER=your_username
DB_PASSWORD=your_password
DB_PORT=3306The DATABASES mapping defines the available databases and their names.
Each institutional database includes, at minimum:
cohort– Detailed cohort and student-level attributescourse– Course enrollment and performance detailsfinancial_aid– Financial aid and cost-of-attendance datallm_recommendations– LLM-generated recommendations and related metadataar_*– Analysis-ready tables, e.g.ar_al,ar_csusb,ar_kctcs,ar_ky,ar_oh
Common characteristics across tables:
- Auto-incrementing
idprimary key schoolcolumn (e.g.AL,CSUSB,KCTCS,KY,OH) for join-ready structure- Shared keys such as
Student_GUID,Institution_ID,Cohort,Academic_Yearenabling cross-table joins
Example join:
SELECT *
FROM course c
JOIN cohort co
ON c.school = co.school
WHERE c.school = 'AL';Synthetic data generation and upload utilities ensure that all required tables can be populated even when an LLM backend is not available.
This is the current default way to run the API, either on a developer machine or a self-managed server.
docker build -f docker/Dockerfile -t devcolor-backend:latest .
docker run -p 8000:8000 --env-file .env devcolor-backend:latest# Start services
docker-compose -f docker/docker-compose.yml up -d
# Stop services
docker-compose -f docker/docker-compose.yml downDocker images are built and published to Amazon ECR automatically via the GitHub Actions workflow defined in .github/workflows/docker-build.yml.
Triggers: pushes to main/develop, and pull requests targeting main.
What the workflow does:
- Configures AWS credentials (region
us-west-2) - Logs in to Amazon ECR
- Builds the image from
docker/Dockerfile - Tags and pushes it to the
devcolor00-schoolECR repository as:latest
Required GitHub secrets:
AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY
Deploying the pushed image with App Runner:
The workflow includes a commented-out step to trigger a deployment on AWS App Runner once the image lands in ECR. To enable it:
- Create an App Runner service pointing at the
devcolor00-schoolECR repository - Configure the service's environment variables (
DB_HOST,DB_USER,DB_PASSWORD,DB_PORT) and, if the database lives in a VPC, attach a VPC connector so App Runner can reach it - Add an
APPRUNNER_SERVICE_ARNsecret to the repository - Uncomment the
Deploy to App Runnerstep in.github/workflows/docker-build.yml
Once enabled, every push to main will build, push, and redeploy the service automatically.
Manual push to ECR (without the CI workflow):
aws ecr get-login-password --region us-west-2 | docker login --username AWS --password-stdin <account-id>.dkr.ecr.us-west-2.amazonaws.com
docker build -f docker/Dockerfile -t <account-id>.dkr.ecr.us-west-2.amazonaws.com/devcolor00-school:latest .
docker push <account-id>.dkr.ecr.us-west-2.amazonaws.com/devcolor00-school:latestdevcolor-backend/
├── api/
│ ├── __init__.py
│ ├── main.py # FastAPI app and router registration
│ ├── schemas.py # Pydantic models
│ └── routers/
│ ├── __init__.py
│ ├── al.py # AL endpoints
│ ├── csusb.py # CSUSB endpoints
│ ├── kctcs.py # KCTCS endpoints
│ ├── ky.py # KY endpoints
│ ├── oh.py # OH endpoints
│ ├── unified.py # Unified querying endpoints
│ └── upload.py # Data upload endpoints
├── db_operations/
│ ├── __init__.py
│ ├── connection.py # DB connection utilities and health checks
│ ├── db_setup.py # Database setup and table creation
│ ├── add_dynamic_columns.py # Migration for dynamic upload columns
│ ├── upload_handler.py # Upload processing logic
│ ├── generate_db_summary.py # Database summary generation
│ ├── populate_all_ar_tables.py # Populate analysis-ready tables
│ ├── populate_ar_ky.py # Populate KY analysis-ready table
│ └── populate_ar_oh.py # Populate OH analysis-ready table
├── docker/
│ ├── Dockerfile
│ └── docker-compose.yml
├── testscripts/
│ ├── check_databases.py
│ ├── check_schema.py
│ ├── check_tables.py
│ ├── count_records.py
│ └── test_new_endpoints.py
├── main.py # Optional helper/entry script
├── requirements.txt # Python dependencies
├── README.md # This file
├── .github/ # GitHub configuration (CI workflows, etc.)
└── database_schema.json # Exported database schema