Spaces:
Sleeping
Project Manager Dashboard - API Reference
Version: 1.0
Last Updated: 2025-11-19
Audience: Frontend Development Team
Overview
This document provides all API endpoints needed to build a comprehensive Project Manager (PM) dashboard. The PM role requires visibility across sales, operations, finance, and resources to orchestrate daily field service operations.
PM Core Responsibilities
- Convert sales orders to work tickets
- Assign tickets to field agents
- Approve expenses and manage finances
- Track inventory and resources
- Generate payroll and invoices
- Monitor team performance
Dashboard Layout Structure
Recommended Sections
- Today's Overview - Key metrics at a glance
- Financial Snapshot - Cash position and pending payments
- Quick Actions - Common PM tasks
- Pending Sales Orders - Orders awaiting conversion
- Active Tickets - Work in progress
- Pending Approvals - Expenses, payroll, invoices
- Inventory Status - Stock levels and alerts
- Map View - Geographic visualization
- Team Status - Agent availability
API Endpoints by Feature
1. Dashboard Overview Statistics
Get Platform Dashboard Stats
GET /api/v1/analytics/platform-admin/dashboard
Authorization: Bearer {token}
Response Fields:
users- User statistics (total, active, by role)organizations- Client and contractor countstickets- Ticket counts by status and typeprojects- Project statisticsassignments- Assignment statisticsrecent_activity- Latest 10 audit logssystem_health- 30-day trends
Use Case: Main dashboard metrics widget
2. Sales Order Management
List Sales Orders
GET /api/v1/sales-orders
Authorization: Bearer {token}
Query Parameters:
- skip (int, default: 0)
- limit (int, default: 50, max: 100)
- project_id (UUID, optional)
- status (string, optional) - "pending", "processed", "cancelled", "duplicate"
- project_region_id (UUID, optional)
- sales_agent_id (UUID, optional)
- from_date (date, optional)
- to_date (date, optional)
- pending_processing (boolean, optional) - Show only pending orders
- customer_phone (string, optional)
Response:
items[]- Array of sales orders with computed propertiestotal- Total countskip,limit- Pagination info
Key Fields per Item:
id,order_number,customer_name,customer_preferred_packagepackage_price,installation_address_line1,installation_latitude,installation_longitudestatus,project_title,region_name,sales_agent_nameis_pending,has_ticket,can_promote_to_ticket
Get Sales Order Statistics
GET /api/v1/sales-orders/stats
Authorization: Bearer {token}
Query Parameters:
- project_id (UUID, optional)
- project_region_id (UUID, optional)
- sales_agent_id (UUID, optional)
Response: Metrics on orders by status, region, agent
Assign Sales Order to Region
POST /api/v1/sales-orders/{sales_order_id}/assign-region
Authorization: Bearer {token}
Content-Type: application/json
Body:
{
"project_region_id": "uuid"
}
Promote Sales Order to Ticket (Single)
POST /api/v1/sales-orders/{sales_order_id}/promote
Authorization: Bearer {token}
Content-Type: application/json
Body:
{
"priority": "normal",
"scheduled_date": "2025-01-20",
"scheduled_time_slot": "morning",
"work_description": "Install fiber",
"notes": "Customer prefers morning"
}
Response:
message,sales_order_id,ticket_id,ticket_name,status
Bulk Promote Sales Orders to Tickets
POST /api/v1/sales-orders/bulk-promote
Authorization: Bearer {token}
Content-Type: application/json
Body:
{
"sales_order_ids": ["uuid1", "uuid2"],
"priority": "normal",
"notes": "Batch promotion"
}
Response:
total,successful,failed,errors[],created_ticket_ids[]
3. Ticket Management
List Tickets
GET /api/v1/tickets
Authorization: Bearer {token}
Query Parameters:
- skip (int, default: 0)
- limit (int, default: 50, max: 100)
- project_id (UUID, optional)
- status (enum, optional) - "open", "assigned", "in_progress", "pending_review", "completed", "cancelled"
- ticket_type (enum, optional) - "installation", "support", "infrastructure"
- priority (enum, optional) - "low", "normal", "high", "urgent"
- project_region_id (UUID, optional)
- source (enum, optional) - "sales_order", "incident", "task"
- from_date (date, optional)
- to_date (date, optional)
- is_overdue (boolean, optional)
Response:
tickets[]- Array of ticketstotal,skip,limit
Key Fields per Ticket:
id,ticket_name,status,priority,ticket_typework_description,scheduled_date,scheduled_time_slotproject_title,region_name,customer_nameis_overdue,can_be_assigned
Get Ticket Statistics
GET /api/v1/tickets/stats
Authorization: Bearer {token}
Query Parameters:
- project_id (UUID, optional)
- project_region_id (UUID, optional)
Response:
- Counts by status, type, priority
overdue_tickets,avg_completion_time_hours,completion_rate
Update Ticket
PUT /api/v1/tickets/{ticket_id}
Authorization: Bearer {token}
Content-Type: application/json
Body:
{
"priority": "urgent",
"work_description": "Updated description",
"notes": "Additional notes"
}
Reschedule Ticket
POST /api/v1/tickets/{ticket_id}/reschedule
Authorization: Bearer {token}
Content-Type: application/json
Body:
{
"scheduled_date": "2025-01-25",
"scheduled_time_slot": "afternoon",
"reason": "Customer requested later date"
}
Cancel Ticket
POST /api/v1/tickets/{ticket_id}/cancel
Authorization: Bearer {token}
Content-Type: application/json
Body:
{
"reason": "Customer cancelled service"
}
4. Ticket Assignment & Dispatch
List Ticket Assignments
GET /api/v1/ticket-assignments
Authorization: Bearer {token}
Query Parameters:
- skip (int, default: 0)
- limit (int, default: 50)
- ticket_id (UUID, optional)
- user_id (UUID, optional)
- status (string, optional)
- project_id (UUID, optional)
- from_date (date, optional)
- to_date (date, optional)
Get Available Agents for Assignment
GET /api/v1/ticket-assignments/available-agents
Authorization: Bearer {token}
Query Parameters:
- ticket_id (UUID, required)
Response: List of agents available to be assigned to the ticket
Assign Ticket to Agent
POST /api/v1/ticket-assignments
Authorization: Bearer {token}
Content-Type: application/json
Body:
{
"ticket_id": "uuid",
"user_id": "uuid",
"notes": "Assigned to John"
}
Reassign Ticket
POST /api/v1/ticket-assignments/{assignment_id}/reassign
Authorization: Bearer {token}
Content-Type: application/json
Body:
{
"new_user_id": "uuid",
"reason": "Original agent unavailable"
}
5. Expense Management
List Expenses
GET /api/v1/expenses
Authorization: Bearer {token}
Query Parameters:
- page (int, default: 1)
- page_size (int, default: 50, max: 100)
- ticket_id (UUID, optional)
- assignment_id (UUID, optional)
- approval_status (string, optional) - "pending", "approved", "rejected"
- payment_status (string, optional) - "pending", "paid"
- from_date (date, optional)
- to_date (date, optional)
Response:
items[]- Array of expensestotal,page,page_size
Key Fields per Expense:
id,expense_type,amount,currencydescription,receipt_urlapproval_status,payment_statussubmitted_by_name,approved_by_name
Get Expense Statistics
GET /api/v1/expenses/stats
Authorization: Bearer {token}
Query Parameters:
- ticket_id (UUID, optional)
- assignment_id (UUID, optional)
Response: Total expenses, pending approvals, payment status breakdown
Approve/Reject Expense
POST /api/v1/expenses/{expense_id}/approve
Authorization: Bearer {token}
Content-Type: application/json
Body:
{
"approved": true,
"notes": "Approved - receipt verified"
}
Mark Expense as Paid
POST /api/v1/expenses/{expense_id}/mark-paid
Authorization: Bearer {token}
Content-Type: application/json
Body:
{
"payment_date": "2025-01-20",
"payment_method": "mobile_money",
"payment_reference": "TXN123456",
"notes": "Paid via M-Pesa"
}
6. Financial Management
List Financial Transactions
GET /api/v1/finance
Authorization: Bearer {token}
Query Parameters:
- skip (int, default: 0)
- limit (int, default: 50, max: 100)
- project_id (UUID, optional)
- transaction_type (string, optional) - "inflow", "outflow"
- status (string, optional) - "pending", "approved", "paid", "rejected", "cancelled"
- category (string, optional)
- from_date (date, optional)
- to_date (date, optional)
- pending_approval (boolean, optional)
Get Cash Flow Summary
GET /api/v1/finance/cash-flow/{project_id}
Authorization: Bearer {token}
Query Parameters:
- from_date (date, optional)
- to_date (date, optional)
Response:
- Total inflows, outflows, net cash flow
- Breakdown by category
- Pending transactions
Create Financial Transaction
POST /api/v1/finance
Authorization: Bearer {token}
Content-Type: application/json
Body:
{
"project_id": "uuid",
"transaction_type": "outflow",
"amount": 50000,
"currency": "KES",
"category": "equipment_purchase",
"description": "Purchased 50 ONTs",
"transaction_date": "2025-01-20"
}
Approve Transaction
POST /api/v1/finance/{transaction_id}/approve
Authorization: Bearer {token}
Content-Type: application/json
Body:
{
"notes": "Approved by PM"
}
7. Contractor Invoice Management
List Contractor Invoices
GET /api/v1/invoices
Authorization: Bearer {token}
Query Parameters:
- skip (int, default: 0)
- limit (int, default: 100, max: 500)
- contractor_id (UUID, optional)
- client_id (UUID, optional)
- project_id (UUID, optional)
- status (string, optional) - "draft", "sent", "partially_paid", "paid", "cancelled"
- overdue_only (boolean, optional)
- unpaid_only (boolean, optional)
- latest_versions_only (boolean, default: true)
Response:
invoices[]- Array of invoicestotal,skip,limit
Key Fields per Invoice:
id,invoice_number,contractor_name,client_namesubtotal_amount,tax_amount,total_amountamount_paid,amount_duestatus,due_date,is_overdue
Create Contractor Invoice
POST /api/v1/invoices
Authorization: Bearer {token}
Content-Type: application/json
Body:
{
"contractor_id": "uuid",
"client_id": "uuid",
"project_id": "uuid",
"invoice_date": "2025-01-20",
"due_date": "2025-02-20",
"currency": "KES",
"tax_rate": 16.0,
"notes": "Monthly invoice"
}
Response: Created invoice with auto-generated invoice number
Add Line Item to Invoice
POST /api/v1/invoices/{invoice_id}/line-items
Authorization: Bearer {token}
Content-Type: application/json
Body:
{
"line_item_type": "ticket",
"ticket_id": "uuid",
"description": "Installation service",
"quantity": 1,
"unit_price": 5000,
"amount": 5000
}
Note: Creates new invoice version
Record Payment
POST /api/v1/invoices/{invoice_id}/payments
Authorization: Bearer {token}
Content-Type: application/json
Body:
{
"amount": 50000,
"payment_date": "2025-01-20",
"payment_method": "bank_transfer",
"payment_reference": "TXN123456",
"notes": "Partial payment"
}
Response: Updated invoice with new payment recorded
8. Inventory Management
List Main Office Inventory
GET /api/v1/inventory
Authorization: Bearer {token}
Query Parameters:
- page (int, default: 1)
- page_size (int, default: 50, max: 100)
- project_id (UUID, optional)
- item_type (string, optional) - "tool", "equipment", "consumable", "ppe"
- status (string, optional)
- is_active (boolean, optional)
- search (string, optional)
Response:
items[]- Inventory batchestotal,page,page_size
Key Fields per Item:
id,equipment_type,equipment_name,item_typequantity_received,quantity_available,quantity_distributedstatus,received_date
Create Inventory Batch
POST /api/v1/inventory
Authorization: Bearer {token}
Content-Type: application/json
Body:
{
"project_id": "uuid",
"equipment_type": "ONT",
"equipment_name": "Huawei HG8145V5",
"item_type": "equipment",
"quantity_received": 100,
"received_date": "2025-01-20",
"supplier_name": "TechSupply Ltd",
"unit_cost": 2500,
"currency": "KES"
}
List Regional Distributions
GET /api/v1/inventory/distributions
Authorization: Bearer {token}
Query Parameters:
- page (int, default: 1)
- page_size (int, default: 50)
- project_id (UUID, optional)
- region_id (UUID, optional)
- inventory_id (UUID, optional)
- item_type (string, optional)
- is_active (boolean, optional)
Response: Inventory distributed to regional hubs
Distribute Inventory to Regional Hub
POST /api/v1/inventory/distributions
Authorization: Bearer {token}
Content-Type: application/json
Body:
{
"inventory_id": "uuid",
"project_region_id": "uuid",
"quantity_distributed": 20,
"distributed_date": "2025-01-20",
"notes": "Distribution to Nairobi hub"
}
List Inventory Assignments (Issued to Agents)
GET /api/v1/inventory/assignments
Authorization: Bearer {token}
Query Parameters:
- page (int, default: 1)
- page_size (int, default: 50)
- user_id (UUID, optional)
- region_id (UUID, optional)
- status (string, optional)
- is_returned (boolean, optional)
- ticket_id (UUID, optional)
Response: Equipment issued to field agents
9. Payroll Management
List Payroll Records
GET /api/v1/payroll
Authorization: Bearer {token}
Query Parameters:
- skip (int, default: 0)
- limit (int, default: 50, max: 100)
- user_id (UUID, optional)
- project_id (UUID, optional)
- period_start (date, optional)
- period_end (date, optional)
- status (string, optional)
Response:
items[]- Payroll recordstotal,skip,limit
Key Fields per Record:
id,user_name,period_start,period_endtotal_earnings,deductions,net_paystatus,payment_status
Generate Payroll
POST /api/v1/payroll/generate
Authorization: Bearer {token}
Content-Type: application/json
Body:
{
"project_id": "uuid",
"period_start": "2025-01-01",
"period_end": "2025-01-31",
"user_ids": ["uuid1", "uuid2"]
}
Response: Generated payroll records
Approve Payroll
POST /api/v1/payroll/{payroll_id}/approve
Authorization: Bearer {token}
Content-Type: application/json
Body:
{
"notes": "Approved for payment"
}
10. Timesheet Management
List Timesheets
GET /api/v1/timesheets
Authorization: Bearer {token}
Query Parameters:
- skip (int, default: 0)
- limit (int, default: 50, max: 100)
- user_id (UUID, optional)
- project_id (UUID, optional)
- from_date (date, optional)
- to_date (date, optional)
- status (string, optional) - "present", "absent", "on_leave", "sick_leave", "half_day"
Get Timesheet Statistics
GET /api/v1/timesheets/stats
Authorization: Bearer {token}
Query Parameters:
- user_id (UUID, optional)
- project_id (UUID, optional)
- from_date (date, optional)
- to_date (date, optional)
Response: Attendance metrics, days worked, absences
11. User Management
List Users
GET /api/v1/users
Authorization: Bearer {token}
Query Parameters:
- skip (int, default: 0)
- limit (int, default: 50, max: 100)
- role (string, optional)
- client_id (UUID, optional)
- contractor_id (UUID, optional)
- is_active (boolean, optional)
- status (string, optional)
- search (string, optional)
Response:
users[]- Array of userstotal,skip,limit
Search Users
GET /api/v1/users/search
Authorization: Bearer {token}
Query Parameters:
- q (string, required) - Search query
- role (string, optional)
- limit (int, default: 20)
Response: Matching users (useful for assignment dropdowns)
Invite New User
POST /api/v1/invitations
Authorization: Bearer {token}
Content-Type: application/json
Body:
{
"email": "john@example.com",
"name": "John Doe",
"phone": "+254712345678",
"role": "field_agent",
"contractor_id": "uuid"
}
12. Map & Location Services
Get Map Entities
GET /api/v1/map/entities
Authorization: Bearer {token}
Query Parameters:
- project_id (UUID, required)
- entity_types (array, optional) - ["customers", "tickets", "sales_orders", "agents", "regions"]
- status (string, optional)
Response:
customers[]- Customer locationstickets[]- Ticket locationssales_orders[]- Sales order locationsagents[]- Agent current locationsregions[]- Regional hub locations
Use Case: Render all entities on map view
Get Regional Hub Locations
GET /api/v1/map/regions/{project_id}
Authorization: Bearer {token}
Query Parameters:
- include_inactive (boolean, default: false)
Response: Regional hubs with coordinates, coverage radius, active tickets/agents count
Get Journey Details
GET /api/v1/map/journey/{assignment_id}
Authorization: Bearer {token}
Response:
- Timeline (start, arrival, completion times)
- GPS breadcrumb trail (array of coordinates with timestamps)
- Journey statistics (distance, duration, speed)
- Location information
Use Case: Track agent movement during work assignment
Find Nearest Regional Hub
GET /api/v1/map/nearest-region
Authorization: Bearer {token}
Query Parameters:
- project_id (UUID, required)
- latitude (float, required)
- longitude (float, required)
- max_distance_km (float, optional)
Response: Nearest regional hub with distance
13. Task Management
List Tasks
GET /api/v1/tasks
Authorization: Bearer {token}
Query Parameters:
- skip (int, default: 0)
- limit (int, default: 50, max: 100)
- project_id (UUID, optional)
- status (string, optional) - "pending", "assigned", "in_progress", "completed", "cancelled", "blocked"
- assigned_to (UUID, optional)
- priority (string, optional)
- from_date (date, optional)
- to_date (date, optional)
Create Task
POST /api/v1/tasks
Authorization: Bearer {token}
Content-Type: application/json
Body:
{
"project_id": "uuid",
"task_type": "installation",
"title": "Install fiber cable",
"description": "Install cable from pole A to B",
"priority": "high",
"due_date": "2025-01-25",
"assigned_to": "uuid"
}
14. Customer Management
List Customers
GET /api/v1/customers
Authorization: Bearer {token}
Query Parameters:
- skip (int, default: 0)
- limit (int, default: 50, max: 100)
- client_id (UUID, optional)
- search (string, optional)
- phone (string, optional)
Get Customer Details
GET /api/v1/customers/{customer_id}
Authorization: Bearer {token}
Response: Customer profile with all related data (subscriptions, tickets, sales orders)
15. Notifications
List Notifications
GET /api/v1/notifications
Authorization: Bearer {token}
Query Parameters:
- skip (int, default: 0)
- limit (int, default: 50)
- is_read (boolean, optional)
- type (string, optional)
Get Unread Count
GET /api/v1/notifications/unread-count
Authorization: Bearer {token}
Response: { "count": 5 }
Mark Notification as Read
PUT /api/v1/notifications/{notification_id}/read
Authorization: Bearer {token}
Authentication
All endpoints require Bearer token authentication:
Authorization: Bearer {access_token}
Token Refresh:
POST /api/v1/auth/refresh
Content-Type: application/json
Body:
{
"refresh_token": "your_refresh_token"
}
Response:
{
"access_token": "new_access_token",
"refresh_token": "new_refresh_token",
"token_type": "bearer",
"expires_in": 3600
}
Error Handling
All endpoints follow standard HTTP status codes:
200 OK- Success201 Created- Resource created204 No Content- Success with no response body400 Bad Request- Invalid input401 Unauthorized- Missing or invalid token403 Forbidden- Insufficient permissions404 Not Found- Resource not found409 Conflict- Duplicate or conflicting resource422 Unprocessable Entity- Validation error500 Internal Server Error- Server error
Error Response Format:
{
"detail": "Error message here"
}
Pagination
List endpoints use offset-based pagination:
Request:
skip- Number of items to skip (default: 0)limit- Number of items to return (default: 50, max varies by endpoint)
Response:
items[]orusers[]or similar - Array of resultstotal- Total count of itemsskip- Current offsetlimit- Current limit
Date/Time Formats
- Dates: ISO 8601 format
YYYY-MM-DD(e.g.,2025-01-20) - DateTimes: ISO 8601 with timezone
YYYY-MM-DDTHH:MM:SSZ(e.g.,2025-01-20T14:30:00Z) - Time Slots:
"morning","afternoon","evening","any"
Filtering Best Practices
- Combine filters - Most list endpoints support multiple filters simultaneously
- Use pagination - Always paginate large result sets
- Cache where appropriate - Dashboard stats can be cached for 1-5 minutes
- Real-time updates - Use polling or WebSockets for live data (tickets, assignments)
Common UI Patterns
Dashboard Widgets
- Fetch stats on page load
- Refresh every 30-60 seconds for live data
- Show loading skeletons during fetch
List Views
- Implement infinite scroll or traditional pagination
- Add filters in sidebar or top bar
- Show total count and current range
Map Views
- Lazy load entities based on viewport
- Cluster markers when zoomed out
- Show details on marker click
Approval Workflows
- Show pending count badge
- Provide bulk approve/reject actions
- Confirm destructive actions (reject, cancel)
Performance Recommendations
- Lazy load - Don't fetch all data at once
- Debounce searches - Wait 300ms before searching
- Cache reference data - Roles, statuses, regions rarely change
- Optimize map rendering - Use clustering for large datasets
- Batch operations - Use bulk endpoints when available
Support & Questions
For API questions or issues:
- Backend Team Lead: [Contact Info]
- API Documentation:
/api/v1/docs(Swagger UI) - Base URL:
https://api.swiftops.example.com
End of Document