Backend REST API developed to support a mobile pilgrim tracking application for journeys to Aparecida, Brazil.
The system provides a secure and scalable foundation for registering pilgrims, organizing them into groups, authenticating users, sharing real-time location information, and managing group administrators.
Portfolio Project β This repository demonstrates backend architecture, REST API development, authentication, database modeling, security practices, and asynchronous programming with Python.
Long-distance pilgrimages involve groups of people traveling together, often over several days and through areas where maintaining awareness of each participant's location can be difficult.
The goal of this project is to provide a backend capable of supporting a mobile application where:
- Pilgrims can join a specific group.
- Each pilgrim receives a unique access code.
- Users can authenticate securely.
- The mobile application can periodically send GPS coordinates.
- Pilgrims can see the latest known location of other members of their group.
- Group administrators can manage participants.
- Different groups remain isolated from one another.
The architecture was designed around a multi-tenant model, where each pilgrim belongs to a specific group (tenant).
The main technical goals of this project are:
- Build a clean REST API using FastAPI
- Implement asynchronous database operations
- Design a multi-tenant data model
- Provide secure authentication using JWT
- Protect access codes using bcrypt
- Implement role-based authorization for administrators
- Support GPS location updates
- Isolate location data between different groups
- Protect authentication endpoints against brute-force attempts
- Keep configuration and secrets outside the source code
The application follows a simple API-centric architecture:
ββββββββββββββββββββββββ
β Mobile App β
β β
β Pilgrim / Admin UI β
ββββββββββββ¬ββββββββββββ
β
β HTTPS / REST
βΌ
ββββββββββββββββββββββββββββββββ
β FastAPI β
β β
β ββββββββββββ ββββββββββββββ β
β β Auth β β Users β β
β ββββββββββββ ββββββββββββββ β
β β
β ββββββββββββ ββββββββββββββ β
β β Location β β Admin β β
β ββββββββββββ ββββββββββββββ β
ββββββββββββββββ¬ββββββββββββββββ
β
β SQLAlchemy Async
βΌ
ββββββββββββββββββββββββββββββββ
β PostgreSQL β
β β
β tenants β
β users β
ββββββββββββββββββββββββββββββββ
The API uses SQLAlchemy's asynchronous engine and PostgreSQL through the asyncpg driver.
A tenant represents a pilgrim group.
Each tenant contains:
- Group information
- A unique join code
- An account limit
- Its associated pilgrims
- Administrators
Tenant
β
βββ Admin
β
βββ Pilgrim
β βββ Last known location
β
βββ Pilgrim
β βββ Last known location
β
βββ Pilgrim
βββ Last known location
This structure allows the API to ensure that location data is only exposed to members of the same group.
Authentication was designed around a simple flow suitable for a mobile application.
QR / Join Code
β
βΌ
βββββββββββββββββ
β Register User β
βββββββββ¬ββββββββ
β
βΌ
6-digit Access
Code
β
βΌ
βββββββββββββββββ
β Login β
βββββββββ¬ββββββββ
β
βΌ
JWT Token
β
βΌ
Authenticated API
Requests
Pilgrim accounts receive a randomly generated 6-digit access code.
The API never stores the code in plain text. It stores only a bcrypt hash and returns the plain-text code only when the account is created or its code is reset.
Successful authentication generates a JWT containing the user and tenant identifiers.
{
"sub": "user_id",
"tenant_id": 123,
"exp": "expiration_timestamp"
}The current implementation uses a long-lived token with a 365-day expiration period, designed to avoid repeatedly asking mobile users to authenticate.
Security was considered as part of the API design rather than as an afterthought.
Instead of requiring traditional passwords, pilgrims use a generated access code that is stored using bcrypt hashing.
Protected endpoints require:
Authorization: Bearer <access_token>Location queries are scoped to the authenticated user's tenant.
This prevents a user belonging to one group from retrieving the location of users belonging to another group.
The login endpoint is limited to:
5 requests / minute / IP
This reduces the risk of brute-force attacks against the 6-digit access code.
The first administrator is created using a server-side setup key.
The key is obtained from an environment variable and is never intended to be distributed to the mobile application.
The current database consists primarily of two entities.
tenants
βββ id
βββ full_name
βββ slug
βββ join_code
βββ max_accounts
βββ created_at
βββ updated_at
users
βββ id
βββ username
βββ tenant_id
βββ access_code_hash
βββ is_admin
βββ last_latitude
βββ last_longitude
βββ last_seen_at
βββ created_at
βββ updated_at
The user model stores the latest known location rather than an entire location history.
This keeps the initial implementation simple and efficient for the core use case.
The mobile application sends the user's current coordinates to:
POST /locationExample:
{
"latitude": -22.8469,
"longitude": -45.2297
}The API updates:
last_latitudelast_longitudelast_seen_at
Other members of the same group can then be retrieved through:
GET /pessoasExample response:
[
{
"id": 15,
"username": "john.doe",
"latitude": -22.8469,
"longitude": -45.2297,
"last_seen_at": "2026-08-13T18:30:00Z"
}
]This endpoint provides the mobile application with the information required to display group members on a map.
| Method | Endpoint | Auth | Description |
|---|---|---|---|
POST |
/tenant |
β | Create a pilgrim group |
GET |
/tenant/{join_code}/exists |
β | Check group existence |
POST |
/user |
β | Register a pilgrim |
GET |
/users |
β | List users |
POST |
/login |
β | Authenticate |
GET |
/me |
JWT | Get current user |
POST |
/location |
JWT | Update location |
GET |
/pessoas |
JWT | Get group locations |
POST |
/admin/bootstrap |
Setup Key | Create first admin |
POST |
/user/{id}/promote |
Admin | Promote user |
POST |
/user/{id}/reset-code |
Admin | Reset access code |
1. User opens the mobile application
β
βΌ
2. Scans the group's QR Code
β
βΌ
3. API validates the group
β
βΌ
4. User creates their account
β
βΌ
5. API generates a 6-digit access code
β
βΌ
6. User logs in
β
βΌ
7. API returns JWT
β
βΌ
8. Mobile app stores the token securely
β
βΌ
9. App periodically sends GPS coordinates
β
βΌ
10. App retrieves other group members
β
βΌ
11. Locations are displayed on the map
Python + FastAPI
FastAPI provides the REST API layer, request validation, dependency injection, authentication integration, and automatic OpenAPI documentation.
PostgreSQL
Used as the primary relational database.
SQLAlchemy Async
Database operations are implemented using asynchronous SQLAlchemy sessions.
JWT + bcrypt
JWT handles authenticated sessions while bcrypt protects user access codes.
SlowAPI
Used to protect the login endpoint against excessive authentication attempts.
- Python 3.10+
- PostgreSQL
- pip
- Git
git clone <repository-url>
cd pilgrim_tracker_apppython -m venv .venvsource .venv/bin/activate.venv\Scripts\activatepip install -r requirements.txtCreate a .env file:
DB_USER=postgres
DB_PASSWORD=your_password
DB_HOST=localhost
DB_PORT=5432
DB_NAME=pilgrim_tracking
JWT_SECRET=your_secure_jwt_secret
ADMIN_SETUP_KEY=your_secure_admin_setup_keyGenerate a secure JWT secret with:
openssl rand -hex 32Never commit .env to the repository.
Start the development server:
uvicorn main:app --reloadThe API will be available at:
http://localhost:8000
Interactive API documentation:
http://localhost:8000/docs
Alternative documentation:
http://localhost:8000/redoc
FastAPI automatically generates interactive Swagger/OpenAPI documentation.
Once the API is running, open:
/docs
This allows developers to:
- Explore endpoints
- Inspect request schemas
- Test authenticated endpoints
- Review response models
- Understand API contracts
The current implementation focuses on the core functionality required by the mobile application.
Possible future improvements include:
Currently only the latest location is stored.
A future version could introduce:
location_history
βββ id
βββ user_id
βββ latitude
βββ longitude
βββ recorded_at
This would enable:
- Route visualization
- Journey replay
- Distance calculations
- Historical analysis
The current implementation can use polling to retrieve updated locations.
A future version could introduce WebSockets for real-time location updates.
Mobile App
β
β WebSocket
βΌ
FastAPI
β
βΌ
Connected Group Members
Potential improvements include:
- Refresh tokens
- Token revocation
- Device/session management
- More granular permissions
A future web dashboard could provide:
- Participant management
- Live map
- Last-seen monitoring
- Group statistics
- User administration
- Route monitoring
Before deploying the API to production, the following areas should be reviewed:
- HTTPS/TLS
- Database migrations
- Database backups
- Production logging
- Monitoring
- Error tracking
- Restricted CORS configuration
- Strong secret management
- API authentication hardening
- Location privacy policies
- Input validation for geographic coordinates
- Secure mobile token storage
- Protection of administrative endpoints
The current CORS configuration allows all origins for development convenience and should be reviewed for production environments.
aparecida-pilgrim-api/
β
βββ app/
β βββ main.py
β βββ models/
β βββ schemas/
β βββ routes/
β βββ services/
β βββ auth/
β
βββ tests/
β
βββ .env.example
βββ .gitignore
βββ requirements.txt
βββ README.md
βββ LICENSE
The structure above represents a recommended evolution of the current implementation as the project grows.
This project demonstrates practical backend engineering concepts including:
- REST API design
- Asynchronous Python
- FastAPI dependency injection
- PostgreSQL integration
- SQLAlchemy ORM
- Multi-tenant architecture
- JWT authentication
- Password/access-code hashing
- Role-based authorization
- Rate limiting
- Geographic data handling
- Environment-based configuration
- API validation with Pydantic
- Automatic OpenAPI documentation
- Database constraint handling
This project was developed as a backend foundation for a mobile application focused on pilgrim safety, group coordination, and location awareness during journeys to Aparecida.
The implementation prioritizes a simple user experience while demonstrating backend concerns such as authentication, authorization, tenant isolation, database design, and secure handling of credentials.
The project is also structured to allow future expansion into real-time tracking, historical route visualization, administrative dashboards, and analytics.
This project is proprietary software.
The source code is publicly available for portfolio, study and evaluation.
Viewing the source code does not grant permission to copy, modify, distribute, sublicense, or use the software commercially without prior written permission from the copyright holder.
All rights reserved.
For professional inquiries, collaboration, or access to additional project information, please contact the author through the contact information available on the GitHub profile.