Table of Contents
🔐 Authentication
Most endpoints require JWT authentication. Include the token in the Authorization header:
Authorization: Bearer <your_access_token>
After successful login or registration, you'll receive an access_token that should be used for authenticated requests.
🌐 Base URL
All API endpoints are prefixed with:
http://localhost:5000
🔑 Auth Endpoints
Register a new customer account. Only customers can self-register.
Request Payload
| Field | Type | Required | Description |
|---|---|---|---|
email |
string | Yes | User's email address (must be unique) |
password |
string | Yes | User's password (will be hashed) |
full_name |
string | Yes | User's full name |
id_number |
string | Yes | National ID number (must be unique) |
phone_number |
string | No | Phone number |
county |
string | No | County/region |
town |
string | No | Town/city |
street |
string | No | Street address |
Example Request:
POST /auth/register
Content-Type: application/json
{
"email": "customer@example.com",
"password": "securepassword123",
"full_name": "John Doe",
"id_number": "12345678",
"phone_number": "+254712345678",
"county": "Nairobi",
"town": "Westlands",
"street": "123 Main Street"
}
Response
201 Created - Success
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": 1,
"full_name": "John Doe",
"id_number": "12345678",
"email": "customer@example.com",
"phone_number": "+254712345678",
"role": "customer",
"county": "Nairobi",
"town": "Westlands",
"street": "123 Main Street",
"created_at": "2025-01-15T10:30:00",
"updated_at": "2025-01-15T10:30:00"
}
}
400 Bad Request - Missing required fields
{
"message": "Missing required fields"
}
409 Conflict - Email already registered
{
"message": "Email already registered"
}
Login with email or phone number and password. Works for all user roles (admin, customer, employee, delivery).
Request Payload
| Field | Type | Required | Description |
|---|---|---|---|
email |
string | No* | User's email address (either email or phone_number required) |
phone_number or phone |
string | No* | User's phone number (either email or phone_number required) |
password |
string | Yes | User's password |
* Either email or phone_number must be provided
Example Request (Email):
POST /auth/login
Content-Type: application/json
{
"email": "customer@example.com",
"password": "securepassword123"
}
Example Request (Phone):
POST /auth/login
Content-Type: application/json
{
"phone_number": "+254712345678",
"password": "securepassword123"
}
Response
200 OK - Success
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": 1,
"full_name": "John Doe",
"id_number": "12345678",
"email": "customer@example.com",
"phone_number": "+254712345678",
"role": "customer",
"county": "Nairobi",
"town": "Westlands",
"street": "123 Main Street",
"created_at": "2025-01-15T10:30:00",
"updated_at": "2025-01-15T10:30:00"
}
}
400 Bad Request - Missing credentials
{
"message": "Email or phone and password are required"
}
401 Unauthorized - Invalid credentials
{
"message": "Invalid credentials"
}
Get the current authenticated user's information.
Response
200 OK - Success
{
"user": {
"id": 1,
"full_name": "John Doe",
"id_number": "12345678",
"email": "customer@example.com",
"phone_number": "+254712345678",
"role": "customer",
"county": "Nairobi",
"town": "Westlands",
"street": "123 Main Street",
"created_at": "2025-01-15T10:30:00",
"updated_at": "2025-01-15T10:30:00"
}
}
404 Not Found - User not found
{
"message": "User not found"
}
Alias for /auth/me endpoint. Returns the current authenticated user's profile information.
Response
Same as /auth/me
Request a password reset. If the email exists, a reset link will be sent (implementation pending).
Request Payload
| Field | Type | Required | Description |
|---|---|---|---|
email |
string | Yes | User's email address |
Example Request:
POST /auth/forgot-password
Content-Type: application/json
{
"email": "customer@example.com"
}
Response
202 Accepted - Request accepted
{
"message": "If the email exists, password reset will be sent"
}
400 Bad Request - Missing email
{
"message": "Email is required"
}
Logout the current session.
Response
200 OK - Success
{
"message": "Logged out"
}
Logout from all sessions (implementation pending).
Response
200 OK - Success
{
"message": "All sessions logged out"
}
🔔 Alerts Endpoints
Get all alerts for the current user. Alerts are filtered based on user role and user ID. Available to all roles (admin, customer, employee, delivery).
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
page |
integer | No | Page number (default: 1) |
per_page |
integer | No | Items per page (default: 20) |
unread_only |
boolean | No | Filter only unread alerts (default: false) |
Example Request:
GET /alerts?page=1&per_page=20&unread_only=false
Authorization: Bearer <your_access_token>
Response
200 OK - Success
{
"alerts": [
{
"id": 1,
"title": "Welcome to Our Grocery Store!",
"message": "Hi John Doe, welcome to our grocery store!",
"target_role": "customer",
"target_user_id": 1,
"is_read": false,
"created_at": "2025-01-15T10:30:00",
"read_at": null
}
],
"pagination": {
"page": 1,
"per_page": 20,
"total": 1,
"pages": 1,
"has_next": false,
"has_prev": false
}
}
404 Not Found - User not found
{
"message": "User not found"
}
Get detailed information about a specific alert. User must have access to the alert based on role and user ID.
Response
200 OK - Success
{
"alert": {
"id": 1,
"title": "Welcome to Our Grocery Store!",
"message": "Hi John Doe, welcome to our grocery store!",
"target_role": "customer",
"target_user_id": 1,
"is_read": false,
"created_at": "2025-01-15T10:30:00",
"read_at": null
}
}
404 Not Found - Alert not found
{
"message": "Alert not found"
}
403 Forbidden - Access denied
{
"message": "Access denied"
}
Mark a specific alert as read. If the alert is already read, the request still succeeds.
Response
200 OK - Success
{
"message": "Alert marked as read",
"alert": {
"id": 1,
"title": "Welcome to Our Grocery Store!",
"message": "Hi John Doe, welcome to our grocery store!",
"target_role": "customer",
"target_user_id": 1,
"is_read": true,
"created_at": "2025-01-15T10:30:00",
"read_at": "2025-01-15T11:00:00"
}
}
404 Not Found - Alert not found
{
"message": "Alert not found"
}
403 Forbidden - Access denied
{
"message": "Access denied"
}
Mark all unread alerts for the current user as read. Only affects alerts the user has access to.
Response
200 OK - Success
{
"message": "5 alerts marked as read",
"count": 5
}
404 Not Found - User not found
{
"message": "User not found"
}
Get the count of unread alerts for the current user. Useful for displaying badge counts.
Response
200 OK - Success
{
"unread_count": 5
}
404 Not Found - User not found
{
"message": "User not found"
}
📝 Notes
- All timestamps are in ISO 8601 format (UTC)
- JWT tokens expire based on
JWT_ACCESS_TOKEN_EXPIRESconfiguration (default: 3600 seconds = 1 hour) - All password fields are hashed using bcrypt before storage
- User roles:
admin,customer,employee,delivery - When a customer registers, they automatically receive a welcome alert and admin receives a new registration notification
- Alerts are filtered by user role and user ID. Users only see alerts where:
target_rolematches their role OR is "all", ANDtarget_user_idis null (for all users) OR matches their user ID - Alerts are ordered by creation date (newest first)