PORTING API Documentation

Complete guide to the PORTING REST API

Overview

The PORTING API provides comprehensive access to fleet tracking data, vehicle information, driver statistics, and real-time alerts. The API uses REST principles with JSON request/response format and requires API key authentication.

Base URL: https://api.portingfour.co.ke/api/

Key Features

  • Real-time Tracking: Get current vehicle locations and status
  • Historical Data: Access detailed tracking history with date filtering
  • Fleet Analytics: Generate reports on fuel efficiency, idle time, and more
  • Alert Management: Monitor speeding, offline vehicles, and geofence violations
  • Pagination Support: Efficiently handle large datasets

Error Handling

The API returns standard HTTP status codes. Error responses include a JSON body with details:

{
  "success": false,
  "error": {
    "code": "INVALID_PARAMS",
    "message": "Limit must be > 0 and offset must be >= 0"
  }
}

Common Status Codes

Code Meaning Resolution
200 OK Request successful No action needed
400 Bad Request Invalid parameters or format Check request parameters and format
401 Unauthorized Missing or invalid API key Include valid X-API-Key header
403 Forbidden API key lacks permission Use key with appropriate role
404 Not Found Resource doesn't exist Verify resource ID
429 Too Many Requests Rate limit exceeded Wait before making more requests
500 Internal Server Error Server error Retry later or contact support

Error Codes

Code Description
INVALID_PARAMS Request parameters are invalid
NOT_FOUND Resource not found
UNAUTHORIZED Authentication failed
FORBIDDEN Access denied
INTERNAL_ERROR Server error occurred

Vehicles Endpoints

Manage and retrieve vehicle information, locations, and tracking data.

GET /api/vehicles

List All Vehicles

Get a paginated list of all vehicles with current status and location info

Parameters
Name Type Required Description
limit number No Results per page (default: 20, max: 100)
offset number No Results to skip (default: 0)
status string No Filter by status: active, idle, offline
branch_id number No Filter by branch ID
search string No Search by plate number or vehicle name
Example Request
GET /api/vehicles?limit=10&status=active
Authorization: Bearer sk_live_xxx
Example Response
{
  "success": true,
  "data": {
    "vehicles": [
      {
        "id": 1,
        "plate_number": "ABC-1234",
        "name": "Delivery Van 1",
        "status": "active",
        "current_location": {
          "latitude": 40.7128,
          "longitude": -74.0060,
          "location_name": "New York, NY"
        },
        "branch_id": 1,
        "branch_name": "NYC Branch",
        "speed": 45,
        "last_update": "2026-02-05T10:30:00Z",
        "created_at": "2025-01-01T00:00:00Z"
      }
    ],
    "total": 150,
    "limit": 10,
    "offset": 0
  }
}
GET /api/vehicles/:id

Get Vehicle Details

Get detailed information about a specific vehicle including location and stats

Parameters
Name Type Location Description
id number URL Path Vehicle ID (required)
Example Request
GET /api/vehicles/1
Authorization: Bearer sk_live_xxx
Example Response
{
  "success": true,
  "data": {
    "id": 1,
    "plate_number": "ABC-1234",
    "name": "Delivery Van 1",
    "status": "active",
    "current_location": {
      "latitude": 40.7128,
      "longitude": -74.0060,
      "location_name": "New York, NY"
    },
    "speed": 45,
    "branch_id": 1,
    "branch_name": "NYC Branch",
    "total_distance": 5432,
    "last_update": "2026-02-05T10:30:00Z",
    "created_at": "2025-01-01T00:00:00Z"
  }
}
GET /api/vehicles/:id/location

Get Current Location

Get only the current location of a vehicle (lightweight, fast endpoint - useful for live maps)

Example Request
GET /api/vehicles/1/location
Authorization: Bearer sk_live_xxx
Example Response
{
  "success": true,
  "data": {
    "vehicle_id": 1,
    "latitude": 40.7128,
    "longitude": -74.0060,
    "location_name": "New York, NY",
    "speed": 45,
    "timestamp": "2026-02-05T10:30:00Z",
    "accuracy": 5
  }
}
GET /api/vehicles/:id/history

Get Tracking History

Get historical tracking records for a vehicle with date filtering and pagination

Parameters
Name Type Description
id number Vehicle ID (required, in URL)
date_from string (ISO 8601) Start date (default: 7 days ago)
date_to string (ISO 8601) End date (default: now)
status string Filter by status: active, idle, offline
limit number Results per page (default: 100, max: 500)
offset number Results to skip (default: 0)
Example Request
GET /api/vehicles/1/history?date_from=2026-02-01T00:00:00Z&date_to=2026-02-05T23:59:59Z&limit=50
Authorization: Bearer sk_live_xxx
Example Response
{
  "success": true,
  "data": {
    "vehicle_id": 1,
    "plate_number": "ABC-1234",
    "date_from": "2026-02-01T00:00:00Z",
    "date_to": "2026-02-05T23:59:59Z",
    "records": [
      {
        "id": 1001,
        "timestamp": "2026-02-05T10:30:00Z",
        "latitude": 40.7128,
        "longitude": -74.0060,
        "location_name": "New York, NY",
        "speed": 45,
        "status": "active",
        "accuracy": 5,
        "poi": "Times Square"
      }
    ],
    "total": 250,
    "limit": 50,
    "offset": 0
  }
}
GET /api/vehicles/:id/geofence-alerts

Get Geofence Alerts

Get geofence entry/exit events for a vehicle

Parameters
Name Type Description
id number Vehicle ID (required, in URL)
limit number Results per page (default: 50, max: 200)
offset number Results to skip (default: 0)
Example Request
GET /api/vehicles/1/geofence-alerts?limit=20
Authorization: Bearer sk_live_xxx

Drivers Endpoints

Access driver information and vehicle assignments.

GET /api/drivers

List All Drivers

Get paginated list of all drivers with assignment statistics

Parameters
Name Type Description
limit number Results per page (default: 20, max: 100)
offset number Results to skip (default: 0)
Example Request
GET /api/drivers?limit=10&offset=0
Authorization: Bearer sk_live_xxx
GET /api/drivers/:id/assignments

Get Driver Assignments

Get vehicle assignments and tracking history for a specific driver

Example Request
GET /api/drivers/1/assignments?limit=10
Authorization: Bearer sk_live_xxx

Branches Endpoints

Get branch information and fleet statistics.

GET /api/branches

List All Branches

Get paginated list of all branches with vehicle count summaries

Parameters
Name Type Description
limit number Results per page (default: 20, max: 100)
offset number Results to skip (default: 0)
Example Request
GET /api/branches?limit=10
Authorization: Bearer sk_live_xxx
GET /api/branches/:id/summary

Get Branch Summary

Get detailed branch statistics including all vehicles and operational metrics

Example Request
GET /api/branches/1/summary
Authorization: Bearer sk_live_xxx

Alerts Endpoints

Real-time alerts and event notifications from fleet operations.

GET /api/alerts

Get Recent Alerts

Get recent alerts detected from tracking data. Alert types include: SPEEDING, OFFLINE, GEOFENCE_BREACH, IDLE

Parameters
Name Type Description
alert_type string Filter by type: SPEEDING, OFFLINE, GEOFENCE_BREACH, IDLE
vehicle_id number Filter by specific vehicle
limit number Results per page (default: 50, max: 200)
offset number Results to skip (default: 0)
Alert Types
  • SPEEDING: Vehicle speed exceeds threshold (default: 100 km/h)
  • OFFLINE: Vehicle has no tracking for > 1 hour
  • GEOFENCE_BREACH: Unauthorized geofence entry/exit
  • IDLE: Vehicle stationary for > 30 minutes
Example Request
GET /api/alerts?alert_type=SPEEDING&limit=25
Authorization: Bearer sk_live_xxx
Example Response
{
  "success": true,
  "data": {
    "alerts": [
      {
        "id": 1001,
        "type": "SPEEDING",
        "severity": "warning",
        "vehicle_id": 1,
        "plate_number": "ABC-1234",
        "timestamp": "2026-02-05T10:30:00Z",
        "message": "Vehicle ABC-1234 exceeding speed limit",
        "value": 85,
        "threshold": 100
      }
    ],
    "total": 342,
    "limit": 25,
    "offset": 0
  }
}

Tracking Endpoints

Historical tracking data and route information.

📌 Note: Most tracking endpoints are covered under the Vehicles section. See GET /api/vehicles/:id/history and GET /api/vehicles/:id/geofence-alerts for detailed examples.

Reports Endpoints

Generate and retrieve fleet analytics reports.

GET /api/reports/idle-vehicles

Idle Vehicles Report

Get list of idle vehicles and idle time statistics

Parameters
Name Type Description
idle_minutes number Consider idle if stationary for N minutes (default: 30)
limit number Results per page (default: 50, max: 200)
offset number Results to skip (default: 0)
Example Request
GET /api/reports/idle-vehicles?idle_minutes=30&limit=25
Authorization: Bearer sk_live_xxx
GET /api/reports/fuel-efficiency

Fuel Efficiency Report

Get fuel efficiency metrics for vehicles across specified date range

Parameters
Name Type Description
vehicle_id number Filter by specific vehicle (optional)
date_from string (ISO 8601) Start date
date_to string (ISO 8601) End date
Example Request
GET /api/reports/fuel-efficiency?date_from=2026-02-01T00:00:00Z&date_to=2026-02-05T23:59:59Z
Authorization: Bearer sk_live_xxx
GET /api/reports/geofence-compliance

Geofence Compliance Report

Get geofence violation and compliance metrics

Parameters
Name Type Description
date_from string (ISO 8601) Start date
date_to string (ISO 8601) End date
Example Request
GET /api/reports/geofence-compliance
Authorization: Bearer sk_live_xxx

Rate Limiting

The API implements rate limiting based on your API key role. Rate limits are enforced per hour.

Role Requests/Hour Response Header
guest 100 X-RateLimit-Limit: 100
viewer 1,000 X-RateLimit-Limit: 1000
operator 5,000 X-RateLimit-Limit: 5000
admin Unlimited N/A

Rate Limit Headers

Each response includes rate limit information:

X-RateLimit-Limit: 1000        # Your hourly limit
X-RateLimit-Remaining: 995    # Requests remaining
X-RateLimit-Reset: 1675420800 # Unix timestamp when limit resets
⚠️ Rate Limit Exceeded: When you exceed the rate limit, you'll receive a 429 Too Many Requests response. Wait until the reset time before making more requests.

Best Practices

1. Use Appropriate Pagination

Always paginate large datasets. Use reasonable limit values (20-100) and iterate through results using offset.

// Good: Paginate through results
GET /api/vehicles?limit=50&offset=0
GET /api/vehicles?limit=50&offset=50
GET /api/vehicles?limit=50&offset=100

// Bad: Requesting too many results at once
GET /api/vehicles?limit=10000

2. Filter When Possible

Use query parameters to filter data server-side, reducing response size and improving performance.

// Good: Filter by status
GET /api/vehicles?status=active&limit=20

// Less efficient: Get all then filter client-side
GET /api/vehicles?limit=1000

3. Cache Responses

Cache responses locally to reduce API calls. Location data can be cached for 30-60 seconds, historical data for longer periods.

4. Handle Errors Gracefully

Always handle error responses and implement retry logic with exponential backoff for transient failures.

async function apiCall(url, retries = 3) {
  for (let i = 0; i < retries; i++) {
    try {
      const response = await fetch(url, { headers });
      if (response.status === 429) {
        // Rate limited: wait before retry
        await sleep(1000 * Math.pow(2, i));
        continue;
      }
      return response.json();
    } catch (error) {
      if (i === retries - 1) throw error;
      await sleep(1000 * Math.pow(2, i));
    }
  }
}

Support & Troubleshooting

Common Issues

401 Unauthorized

Issue: API key is missing or invalid

Solution:

  • Verify you're including the Bearer header
  • Check that the key is correct (copy-paste from dashboard)
  • Ensure the key hasn't been revoked
  • Generate a new key if needed

403 Forbidden

Issue: API key doesn't have permission for this endpoint

Solution:

  • Check your API key's role in the dashboard
  • Verify the endpoint requires your role level or higher
  • Request a key with appropriate role

429 Too Many Requests

Issue: Rate limit exceeded

Solution:

  • Check X-RateLimit-Reset header for reset time
  • Implement backoff logic in your client
  • Consider upgrading to higher tier role for higher limits
  • Optimize your requests to use less quota