Backend API server for the Busition platform, built with FastAPI and SQLAlchemy.
The service exposes versioned REST APIs for user authentication, shuttle schedule lookup, route and station management, organization join-code flows, and driver/passenger operations. The current codebase primarily targets the v1_5 API while still keeping several deprecated Firebase/DynamoDB-based endpoints for backward compatibility.
- Framework: FastAPI
- Language: Python
- ORM: SQLAlchemy
- Database: PostgreSQL
- Migration tool: Alembic
- Authentication: OAuth2 password flow with JWT
- External integrations:
- Firebase Admin SDK
- AWS DynamoDB (legacy endpoints)
- Naver Maps Directions API
- JWT-based authentication for Busition Console, Driver, Driver-for-Org, Mate, and docs access
- Versioned API delivery through
fastapi-versioning - Schedule lookup by platform and run-day management
- Route CRUD and route path generation via Naver Maps Directions API
- Station CRUD, bulk update, bulk delete, and station recreation
- Passenger manifest lookup for a specific route/station pair
- Organization join-code creation, lookup, deletion, and join flow
- Organization-scoped driver account management
.
├── app
│ ├── api
│ │ └── endpoints
│ ├── core
│ ├── db
│ ├── keyfile
│ ├── tests
│ └── main.py
├── alembic
├── nginx
├── Dockerfile
├── Jenkinsfile
└── requirements.txt
app/main.py: FastAPI application entry pointapp/api/api.py: top-level router registrationapp/api/endpoints/: versioned API modulesapp/core/: application settings and external service helpersapp/db/: database session, models, and schemasapp/tests/: test filesalembic/: migration environment and revision historynginx/default.conf: reverse proxy example forapi.busition.com
- Python 3.11 recommended
- PostgreSQL database
- Additional local credentials for the current startup path:
- Firebase Admin SDK service-account JSON
- AWS credentials used by legacy DynamoDB-backed endpoints
- Naver Cloud Platform Maps Directions API keys
python3 -m venv .venv
source .venv/bin/activatepip install -r requirements.txtCreate a local environment file:
cp app/.env.example app/.envSet the following values in app/.env:
| Variable | Required | Description |
|---|---|---|
SQLALCHEMY_DATABASE_URL |
Yes | PostgreSQL connection string used by SQLAlchemy |
SECRET_KEY |
Yes | JWT signing key |
ALGORITHM |
Yes | JWT algorithm, for example HS256 |
ACCESS_TOKEN_EXPIRE_MINUTES |
Yes | Access token expiration time in minutes |
The current application imports some credential-backed modules during startup, so the following files should exist locally before you run the server:
app/keyfile/aws_key.pyapp/keyfile/naver_api_key.pyapp/keyfile/busition-firebase-adminsdk-p6mxk-7c99130ac8.json
In other words, even if you do not plan to call every external-service endpoint, you may still need local placeholder or real credential files until the startup imports are refactored.
uvicorn app.main:app --reloadBy default, Uvicorn serves the app on http://127.0.0.1:8000.
- Swagger UI:
http://127.0.0.1:8000/latest/docs - ReDoc:
http://127.0.0.1:8000/latest/redoc - OpenAPI JSON:
http://127.0.0.1:8000/latest/openapi.json
The project uses fastapi-versioning, so routes are exposed under versioned prefixes such as:
v1_5v1_4v1_3v1_2v1_0
The latest docs endpoints are enabled for API exploration.
Base prefix: /users
POST /latest/users/token: issue an access tokenGET /latest/users/me: return the current authenticated userGET /latest/users/type: list supported auth typesPOST /latest/users: sign up a new userPOST /latest/users/driver-for-org: create an organization-only driver accountGET /latest/users/email: check email availability
Base prefix: /schedules
- Get schedules by platform: console, driver, mate-individual, mate-org
- Read, update, and delete run-day settings per route
Base prefix: /routes
- Get route geometry and station data
- Create routes
- Update routes
- Delete routes
Base prefix: /stations
- List stations for a route
- Create stations in bulk
- Update a single station
- Update stations in bulk
- Delete one or many stations
- Delete all stations for a route
- Recreate all stations for a route
Base prefix: /passengers
- Get passenger manifests for a route/station pair
Base prefix: /organizations
- Join an organization using a join code
- Create a join code
- Get the current join code
- Delete the current join code
Base prefix: /drivers
- List all drivers in the current organization
- Separate organization-only driver accounts from unified Busition driver accounts
- Attach an existing Busition driver account to an organization
The repository still contains deprecated endpoints for legacy Firebase/DynamoDB workflows:
/users-test/signup/signin
These remain in the codebase for backward compatibility and should not be treated as the primary API surface for new work.
The API uses OAuth2 password flow. To get a token for the docs flow:
curl -X POST "http://127.0.0.1:8000/latest/users/token?busition_platform=docs" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "username=your-email@example.com&password=your-password"Example response:
{
"access_token": "your-jwt-token",
"token_type": "bearer"
}Use the returned bearer token in the Authorization header for protected endpoints.
SQLAlchemy models live in app/db/models.py, and Alembic configuration lives in alembic.ini and alembic/.
To apply migrations:
alembic upgrade headTo create a new migration:
alembic revision --autogenerate -m "describe your change"Run the test suite with:
python3 -m pytest app/test_main.py app/testsSome tests in this repository cover legacy API versions, so make sure your local database state and credentials are consistent with the code paths you want to exercise.
Build the image:
docker build -t busition-api-server .Run the container:
docker run -d \
--name busition-api-server \
-p 8001:8001 \
-e SQLALCHEMY_DATABASE_URL="postgresql://user:password@host:5432/dbname" \
-e SECRET_KEY="replace-me" \
-e ALGORITHM="HS256" \
-e ACCESS_TOKEN_EXPIRE_MINUTES="10" \
-v "$(pwd)/app/keyfile:/busition-api-server/app/keyfile" \
--restart unless-stopped \
busition-api-serverThe container starts Uvicorn on port 8001.
Jenkinsfilecontains a Docker-based deployment pipelinenginx/default.confshows an example reverse proxy configuration forapi.busition.com- The reverse proxy forwards traffic to the application running on
localhost:8001
- Route path generation currently depends on the Naver Maps Directions API and supports up to 15 waypoints in the present implementation
- Several legacy endpoints still rely on Firebase and DynamoDB
- The repository expects secrets and service credentials to be supplied locally or through deployment environment configuration
- Keep
.envfiles and credential files out of version control in real deployments
This project is licensed under the GNU Affero General Public License v3.0 only (AGPL-3.0-only).