Create Work Order
Create a new work order in the Centro Access system.
Endpoint
POST /api/v1/external/workorders/
Headers
| Header | Value | Required |
|---|---|---|
Authorization | Api-Key YOUR_API_KEY | Yes |
Content-Type | application/json | Yes |
Request Body
The create work order endpoint accepts only the essential fields that are actually used when creating new work orders. The title is automatically generated from the client name and service category.
Required Fields
| Field | Type | Description |
|---|---|---|
client_name | string | Name of the client (max 255 characters) |
client_contact | string | Client's phone number in international format |
Optional Fields
| Field | Type | Default | Description |
|---|---|---|---|
service_category | string | "installation" | Type of service work |
priority | string | "medium" | Priority level of the work order |
additional_information | string | "" | Additional notes or instructions (max 1000 characters) |
preferred_time | string | null | ISO 8601 datetime when client prefers service |
due_date | string | null | ISO 8601 date when work should be completed |
latitude | number | null | GPS latitude coordinate (-90 to 90) |
longitude | number | null | GPS longitude coordinate (-180 to 180) |
Field Values
service_category Options
"installation"- Fiber installation work"mdu"- Multi-dwelling unit work"extension"- Service extension work"transmission"- Transmission line work"construction"- Construction projects"support"- Support and maintenance
priority Options
"low"- Low priority"medium"- Medium priority (default)"high"- High priority"urgent"- Urgent priority
Automatic Field Generation
When creating a work order, certain fields are automatically set:
- title: Generated as
"{client_name} - {Service Category}"(e.g., "John Doe - Installation") - status: Always set to
"dispatch"for new work orders - organisation: Set from the API key context
- created_by: Set to the system user associated with the API key
Request Example
Minimal Request
{
"client_name": "John Doe",
"client_contact": "+256701234567"
}
Complete Request
{
"client_name": "Jane Smith",
"client_contact": "+256707654321",
"service_category": "installation",
"priority": "high",
"additional_information": "Customer prefers morning appointments between 8-11 AM. Gate code is 1234.",
"preferred_time": "2025-10-25T09:00:00Z",
"due_date": "2025-10-30",
"latitude": 0.3163,
"longitude": 32.5822
}
Response
Success Response (201 Created)
{
"success": true,
"message": "Work order created successfully",
"work_order": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"title": "Jane Smith - Installation",
"client_name": "Jane Smith",
"client_contact": "+256707654321",
"additional_information": "Customer prefers morning appointments between 8-11 AM. Gate code is 1234.",
"preferred_time": "2025-10-25T09:00:00Z",
"due_date": "2025-10-30",
"status": "dispatch",
"status_display": "Dispatch",
"priority": "high",
"priority_display": "High",
"service_category": "installation",
"service_category_display": "Installation",
"latitude": 0.3163,
"longitude": 32.5822,
"assigned_team": null,
"assigned_team_details": null,
"service_zone": null,
"service_zone_details": null,
"organisation": {
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "Centro Access Uganda"
},
"created_at": "2025-10-24T14:30:00Z",
"updated_at": "2025-10-24T14:30:00Z",
"created_by_details": {
"id": "987fcdeb-51a2-43d1-9c12-345678901234",
"username": "api_system_user",
"first_name": "API",
"last_name": "System"
},
"call_attempts": 0,
"last_status_change": "2025-10-24T14:30:00Z",
"is_deleted": false,
"work_order_call_logs": []
}
}
Error Responses
400 Bad Request - Validation Error
{
"error": "Invalid data provided",
"details": {
"client_name": ["This field is required."],
"client_contact": ["This field is required."]
}
}
400 Bad Request - Invalid Phone Number
{
"error": "Invalid data provided",
"details": {
"client_contact": ["Enter a valid phone number (e.g. +256701234567)."]
}
}
400 Bad Request - Invalid Coordinates
{
"error": "Invalid data provided",
"details": {
"latitude": ["Ensure this value is greater than or equal to -90."],
"longitude": ["Ensure this value is less than or equal to 180."]
}
}
401 Unauthorized
{
"error": "Authentication credentials were not provided."
}
403 Forbidden - Missing Permission
{
"error": "You do not have permission to perform this action.",
"required_permission": "workorder.add_workorder"
}
Code Examples
Python
import requests
# Create work order
url = "https://app.centroaccess.com/api/v1/external/workorders/"
headers = {
"Authorization": "Api-Key your-api-key-here",
"Content-Type": "application/json"
}
data = {
"client_name": "Alice Johnson",
"client_contact": "+256701234567",
"service_category": "installation",
"priority": "high",
"additional_information": "Customer has requested morning installation",
"preferred_time": "2025-10-25T09:00:00Z",
"latitude": 0.3163,
"longitude": 32.5822
}
response = requests.post(url, json=data, headers=headers)
if response.status_code == 201:
work_order = response.json()["work_order"]
print(f"Created work order: {work_order['id']}")
print(f"Title: {work_order['title']}")
print(f"Status: {work_order['status_display']}")
else:
print(f"Error: {response.json()}")
JavaScript
// Create work order
const createWorkOrder = async () => {
const response = await fetch('https://app.centroaccess.com/api/v1/external/workorders/', {
method: 'POST',
headers: {
'Authorization': 'Api-Key your-api-key-here',
'Content-Type': 'application/json',
},
body: JSON.stringify({
client_name: 'Bob Wilson',
client_contact: '+256707654321',
service_category: 'mdu',
priority: 'medium',
additional_information: 'Building access requires security clearance',
due_date: '2025-11-01'
})
});
if (response.ok) {
const result = await response.json();
console.log('Created work order:', result.work_order.id);
console.log('Title:', result.work_order.title);
return result.work_order;
} else {
const error = await response.json();
console.error('Error creating work order:', error);
throw new Error(error.error);
}
};
cURL
# Minimal work order creation
curl -X POST "https://app.centroaccess.com/api/v1/external/workorders/" \
-H "Authorization: Api-Key your-api-key-here" \
-H "Content-Type: application/json" \
-d '{
"client_name": "Sarah Connor",
"client_contact": "+256701234567"
}'
# Complete work order creation
curl -X POST "https://app.centroaccess.com/api/v1/external/workorders/" \
-H "Authorization: Api-Key your-api-key-here" \
-H "Content-Type: application/json" \
-d '{
"client_name": "Michael Davis",
"client_contact": "+256707654321",
"service_category": "extension",
"priority": "urgent",
"additional_information": "Emergency service required",
"preferred_time": "2025-10-24T16:00:00Z",
"due_date": "2025-10-25",
"latitude": 0.3476,
"longitude": 32.5825
}'
Validation Rules
Client Name
- Required: Yes
- Type: String
- Max Length: 255 characters
- Rules: Cannot be empty or contain only whitespace
Client Contact
- Required: Yes
- Type: Phone number
- Format: International format with country code (e.g., +256701234567)
- Rules: Must be a valid phone number
Service Category
- Required: No (defaults to "installation")
- Type: String
- Options: installation, mdu, extension, transmission, construction, support
Priority
- Required: No (defaults to "medium")
- Type: String
- Options: low, medium, high, urgent
Additional Information
- Required: No
- Type: String
- Max Length: 1000 characters
Preferred Time
- Required: No
- Type: ISO 8601 datetime string
- Format: YYYY-MM-DDTHH:MM:SSZ
Due Date
- Required: No
- Type: ISO 8601 date string
- Format: YYYY-MM-DD
Coordinates
- Required: No
- Latitude: Number between -90 and 90
- Longitude: Number between -180 and 180
Best Practices
1. Always Provide Client Information
{
"client_name": "Clear, full name",
"client_contact": "+256701234567"
}
2. Use Appropriate Service Categories
Choose the service category that best matches the work type:
- Use
"installation"for new fiber connections - Use
"mdu"for multi-dwelling unit projects - Use
"support"for maintenance and troubleshooting
3. Set Realistic Priorities
- Use
"urgent"sparingly for true emergencies - Most work orders should be
"medium"priority - Use
"high"for time-sensitive but non-emergency work
4. Include Location Data When Available
{
"latitude": 0.3163,
"longitude": 32.5822,
"additional_information": "Near Kampala Central Business District"
}
5. Provide Clear Additional Information
{
"additional_information": "Customer available weekday mornings. Security code: 1234. Contact property manager if needed: +256701111111"
}
6. Use Proper Time Formats
{
"preferred_time": "2025-10-25T09:00:00Z",
"due_date": "2025-10-30"
}
Related Endpoints
- List Work Orders - Retrieve created work orders
- Get Work Order Details - Get detailed information about a specific work order
- Authentication - Learn about API key authentication
Success Response (201 Created)
{
"success": true,
"message": "Work order created successfully",
"work_order": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"title": "Install fiber connection",
"client_name": "John Doe",
"client_contact": "+1234567890",
"additional_information": "Customer prefers morning appointments",
"status": "dispatch",
"status_display": "Dispatch",
"priority": "high",
"priority_display": "High",
"service_category": "installation",
"service_category_display": "Installation",
"due_date": "2025-12-31",
"preferred_time": "2025-10-25T10:00:00Z",
"longitude": -73.935242,
"latitude": 40.730610,
"created_at": "2025-10-23T14:30:00Z",
"updated_at": "2025-10-23T14:30:00Z",
"created_by": {
"id": "880e8400-e29b-41d4-a716-446655440003",
"email": "api-key-system@centroaccess.com",
"name": "API Key: Integration System"
},
"service_zone": {
"id": "660e8400-e29b-41d4-a716-446655440001",
"name": "Downtown Area",
"description": "Central business district"
},
"assigned_team": {
"id": "770e8400-e29b-41d4-a716-446655440002",
"name": "Installation Team A",
"description": "Primary installation team"
}
}
}
Work Order Object Fields
| Field | Type | Description |
|---|---|---|
id | UUID | Unique work order identifier |
title | string | Work order title |
client_name | string | Customer/client name |
client_contact | string | Client phone number |
additional_information | string | Additional notes |
status | string | Current status (always "dispatch" for new orders) |
status_display | string | Human-readable status |
priority | string | Priority level code |
priority_display | string | Human-readable priority |
service_category | string | Service category code |
service_category_display | string | Human-readable category |
due_date | string/null | Due date (YYYY-MM-DD) |
preferred_time | string/null | Preferred time (ISO format) |
longitude | float/null | Longitude coordinate |
latitude | float/null | Latitude coordinate |
created_at | string | Creation timestamp |
updated_at | string | Last update timestamp |
created_by | object | System user information |
service_zone | object/null | Service zone details |
assigned_team | object/null | Assigned team details |
Examples
Basic Work Order
Create a simple work order with only required fields:
curl -X POST "https://app.centroaccess.com/api/v1/external/workorders/" \
-H "Authorization: Api-Key your-api-key-here" \
-H "Content-Type: application/json" \
-d '{
"title": "Install fiber connection",
"client_contact": "+1234567890"
}'
Complete Work Order
Create a work order with all optional fields:
curl -X POST "https://app.centroaccess.com/api/v1/external/workorders/" \
-H "Authorization: Api-Key your-api-key-here" \
-H "Content-Type: application/json" \
-d '{
"title": "Complete fiber installation",
"client_name": "John Doe",
"client_contact": "+1234567890",
"additional_information": "Customer prefers morning appointments. Gate code: 1234",
"priority": "high",
"service_category": "installation",
"service_zone": "660e8400-e29b-41d4-a716-446655440001",
"assigned_team": "770e8400-e29b-41d4-a716-446655440002",
"due_date": "2025-12-31",
"preferred_time": "2025-10-25T10:00:00Z",
"longitude": -73.935242,
"latitude": 40.730610
}'
High Priority Work Order
Create an urgent work order:
curl -X POST "https://app.centroaccess.com/api/v1/external/workorders/" \
-H "Authorization: Api-Key your-api-key-here" \
-H "Content-Type: application/json" \
-d '{
"title": "Emergency fiber repair",
"client_name": "Business Customer",
"client_contact": "+1234567890",
"additional_information": "Business down, requires immediate attention",
"priority": "urgent",
"service_category": "support"
}'
Survey Work Order
Create a survey work order with location:
curl -X POST "https://app.centroaccess.com/api/v1/external/workorders/" \
-H "Authorization: Api-Key your-api-key-here" \
-H "Content-Type: application/json" \
-d '{
"title": "Site survey for new installation",
"client_name": "New Customer",
"client_contact": "+1234567890",
"additional_information": "Survey required before installation can proceed",
"priority": "medium",
"service_category": "survey",
"longitude": -73.935242,
"latitude": 40.730610
}'
Service Categories
Available service category values:
| Category | Description |
|---|---|
survey | Survey work |
installation | Installation work |
mdu | Multi-dwelling unit work |
service_provider | Service provider work |
extension | Extension work |
transmission | Transmission work |
construction | Construction work |
review | Review work |
support | Support work |
relocation | Relocation work |
equipment_recovery | Equipment recovery |
Priority Levels
Available priority values:
| Priority | Description | Use Case |
|---|---|---|
low | Low priority | Non-urgent maintenance |
medium | Medium priority (default) | Standard work orders |
high | High priority | Important customer requests |
urgent | Urgent priority | Emergency repairs, business down |
Error Responses
Validation Error
Status Code: 400 Bad Request
{
"error": "Invalid data provided",
"details": {
"client_contact": ["This field is required."],
"priority": ["'invalid' is not a valid choice."],
"due_date": ["Date has wrong format. Use one of these formats instead: YYYY-MM-DD."]
}
}
Invalid Service Zone
Status Code: 400 Bad Request
{
"error": "Invalid data provided",
"details": {
"service_zone": ["Invalid pk \"invalid-uuid\" - object does not exist."]
}
}
Invalid Team
Status Code: 400 Bad Request
{
"error": "Invalid data provided",
"details": {
"assigned_team": ["Invalid pk \"invalid-uuid\" - object does not exist."]
}
}
Authentication Required
Status Code: 401 Unauthorized
{
"detail": "Invalid API key"
}
Insufficient Permissions
Status Code: 403 Forbidden
{
"error": "Insufficient permissions",
"required_permission": "workorder.add_workorder"
}
Server Error
Status Code: 500 Internal Server Error
{
"error": "Failed to create work order",
"details": "Unexpected error occurred"
}
Code Examples
Python
import requests
from datetime import datetime, timedelta
API_KEY = "your-api-key-here"
BASE_URL = "https://app.centroaccess.com/api/v1/external"
headers = {
"Authorization": f"Api-Key {API_KEY}",
"Content-Type": "application/json"
}
def create_work_order(title, client_contact, **kwargs):
"""Create a new work order."""
data = {
"title": title,
"client_contact": client_contact,
**kwargs
}
response = requests.post(
f"{BASE_URL}/workorders/",
headers=headers,
json=data
)
if response.status_code == 201:
result = response.json()
work_order = result["work_order"]
print(f"✅ Created work order: {work_order['id']}")
print(f" Title: {work_order['title']}")
print(f" Status: {work_order['status_display']}")
print(f" Priority: {work_order['priority_display']}")
return work_order
else:
print(f"❌ Error: {response.status_code}")
print(f" Details: {response.json()}")
return None
def create_urgent_work_order(title, client_name, client_contact, details):
"""Create an urgent work order."""
return create_work_order(
title=title,
client_name=client_name,
client_contact=client_contact,
additional_information=details,
priority="urgent",
service_category="support"
)
def create_installation_order(title, client_name, client_contact,
service_zone_id=None, team_id=None,
due_date=None, coordinates=None):
"""Create an installation work order."""
kwargs = {
"client_name": client_name,
"priority": "medium",
"service_category": "installation"
}
if service_zone_id:
kwargs["service_zone"] = service_zone_id
if team_id:
kwargs["assigned_team"] = team_id
if due_date:
kwargs["due_date"] = due_date
if coordinates:
kwargs["latitude"] = coordinates["lat"]
kwargs["longitude"] = coordinates["lng"]
return create_work_order(title, client_contact, **kwargs)
# Usage examples
basic_order = create_work_order(
"Install fiber connection",
"+1234567890",
client_name="John Doe",
priority="high"
)
urgent_order = create_urgent_work_order(
"Emergency fiber repair",
"Business Customer",
"+1234567890",
"Business is down, requires immediate attention"
)
installation_order = create_installation_order(
"New residential installation",
"Jane Smith",
"+1234567890",
service_zone_id="660e8400-e29b-41d4-a716-446655440001",
due_date="2025-11-15",
coordinates={"lat": 40.730610, "lng": -73.935242}
)
JavaScript/Node.js
const axios = require('axios');
const API_KEY = 'your-api-key-here';
const BASE_URL = 'https://app.centroaccess.com/api/v1/external';
const headers = {
'Authorization': `Api-Key ${API_KEY}`,
'Content-Type': 'application/json'
};
async function createWorkOrder(workOrderData) {
try {
const response = await axios.post(
`${BASE_URL}/workorders/`,
workOrderData,
{ headers }
);
const { work_order } = response.data;
console.log(`✅ Created work order: ${work_order.id}`);
console.log(` Title: ${work_order.title}`);
console.log(` Status: ${work_order.status_display}`);
console.log(` Priority: ${work_order.priority_display}`);
return work_order;
} catch (error) {
console.error('❌ Error creating work order:');
if (error.response) {
console.error(` Status: ${error.response.status}`);
console.error(` Details:`, error.response.data);
} else {
console.error(` Error: ${error.message}`);
}
return null;
}
}
async function createUrgentWorkOrder(title, clientName, clientContact, details) {
return await createWorkOrder({
title,
client_name: clientName,
client_contact: clientContact,
additional_information: details,
priority: 'urgent',
service_category: 'support'
});
}
async function createInstallationOrder(options) {
const {
title,
clientName,
clientContact,
serviceZoneId,
teamId,
dueDate,
coordinates,
additionalInfo
} = options;
const workOrderData = {
title,
client_name: clientName,
client_contact: clientContact,
priority: 'medium',
service_category: 'installation'
};
if (serviceZoneId) workOrderData.service_zone = serviceZoneId;
if (teamId) workOrderData.assigned_team = teamId;
if (dueDate) workOrderData.due_date = dueDate;
if (coordinates) {
workOrderData.latitude = coordinates.lat;
workOrderData.longitude = coordinates.lng;
}
if (additionalInfo) workOrderData.additional_information = additionalInfo;
return await createWorkOrder(workOrderData);
}
// Usage examples
async function examples() {
// Basic work order
await createWorkOrder({
title: 'Install fiber connection',
client_contact: '+1234567890',
client_name: 'John Doe',
priority: 'high'
});
// Urgent work order
await createUrgentWorkOrder(
'Emergency fiber repair',
'Business Customer',
'+1234567890',
'Business is down, requires immediate attention'
);
// Installation work order
await createInstallationOrder({
title: 'New residential installation',
clientName: 'Jane Smith',
clientContact: '+1234567890',
serviceZoneId: '660e8400-e29b-41d4-a716-446655440001',
dueDate: '2025-11-15',
coordinates: { lat: 40.730610, lng: -73.935242 },
additionalInfo: 'Customer prefers afternoon appointments'
});
}
examples();
Validation Rules
Phone Number Format
Client contact should be in E.164 format:
# Good formats
"+1234567890"
"+12345678901"
"+44123456789"
# Acceptable but not recommended
"1234567890"
"(123) 456-7890"
"123-456-7890"
Title Length
Title must not exceed 255 characters:
# Good
"Install fiber connection for residential customer"
# Too long (over 255 characters)
"Very long title that exceeds the maximum allowed length for work order titles and will be rejected by the API validation because it contains too many characters and goes beyond the 255 character limit set in the database schema..."
Date Formats
Due date must be in YYYY-MM-DD format:
# Good
"2025-12-31"
"2025-01-15"
# Bad
"12/31/2025"
"31-12-2025"
"December 31, 2025"
Coordinate Validation
Coordinates must be valid latitude/longitude values:
# Good
"latitude": 40.730610, # Valid latitude (-90 to 90)
"longitude": -73.935242 # Valid longitude (-180 to 180)
# Bad
"latitude": 200, # Invalid (outside range)
"longitude": "invalid" # Invalid (not a number)
Best Practices
1. Validate Data Before Sending
def validate_work_order_data(data):
"""Validate work order data before sending to API."""
errors = []
if not data.get('title'):
errors.append("Title is required")
elif len(data['title']) > 255:
errors.append("Title must be 255 characters or less")
if not data.get('client_contact'):
errors.append("Client contact is required")
if 'priority' in data and data['priority'] not in ['low', 'medium', 'high', 'urgent']:
errors.append("Invalid priority value")
return errors
# Use validation before API call
data = {"title": "Install fiber", "client_contact": "+1234567890"}
errors = validate_work_order_data(data)
if errors:
print("Validation errors:", errors)
else:
create_work_order(**data)
2. Handle Errors Gracefully
def safe_create_work_order(data, max_retries=3):
"""Create work order with retry logic."""
for attempt in range(max_retries):
try:
response = requests.post(url, headers=headers, json=data)
if response.status_code == 201:
return response.json()
elif response.status_code == 400:
# Validation error - don't retry
print("Validation error:", response.json())
return None
else:
# Server error - retry
print(f"Attempt {attempt + 1} failed: {response.status_code}")
if attempt == max_retries - 1:
raise Exception("Max retries exceeded")
time.sleep(2 ** attempt) # Exponential backoff
except requests.RequestException as e:
print(f"Network error on attempt {attempt + 1}: {e}")
if attempt == max_retries - 1:
raise
time.sleep(2 ** attempt)
return None
3. Use Batch Creation for Multiple Orders
def create_multiple_work_orders(work_orders):
"""Create multiple work orders with proper error handling."""
results = []
for i, wo_data in enumerate(work_orders):
print(f"Creating work order {i + 1}/{len(work_orders)}")
try:
result = create_work_order(**wo_data)
results.append({"success": True, "data": result})
except Exception as e:
results.append({"success": False, "error": str(e), "data": wo_data})
# Rate limiting: small delay between requests
time.sleep(0.1)
# Summary
successful = sum(1 for r in results if r["success"])
print(f"Created {successful}/{len(work_orders)} work orders successfully")
return results
Next Steps
- Get Work Order Details → Retrieve detailed work order information
- List Work Orders → Query and filter work orders
- Code Examples → More comprehensive integration examples