API v1  ·  REST + OAuth 2.0

EonsFleet Developer Portal

Everything you need to integrate with the EonsFleet Fleet Management API — authentication, roles, subscriptions, and live endpoint reference.

Get started API Reference

Make your first API call in 4 steps

The API is REST-based and returns JSON. All endpoints live under /api/v1/.

1
Register an organization & user
POST to /api/v1/organization/register to create your org and admin account.
# Register org + admin
POST /api/v1/organization/register
Content-Type: application/json
X-Request-Type: client

{
  "organization_name": "Acme Fleet",
  "email":             "admin@acmefleet.ng",
  "password":          "s3cr3t!",
  "first_name":        "Ada",
  "last_name":         "Obi"
}
2
Authenticate — get a Bearer token
Exchange credentials for an OAuth 2.0 access token (Password Grant).
POST /oauth/token
Content-Type: application/json

{
  "grant_type":    "password",
  "client_id":     2,
  "client_secret": "YOUR_CLIENT_SECRET",
  "username":      "admin@acmefleet.ng",
  "password":      "s3cr3t!",
  "scope":         ""
}

# Response:
{
  "token_type":    "Bearer",
  "expires_in":    86400,
  "access_token":  "eyJ0eXAiOiJK...",
  "refresh_token": "def50200..."
}
3
Set required headers on every request
Two headers are always required — missing either will result in a 400 or 401.
Authorization: Bearer <access_token>
X-Request-Type: client          # always "client" for user-context API calls
X-Request-Type is mandatory. Every request to /api/v1/* must include X-Request-Type: client. Omitting it returns 400 — no exceptions. This header selects the Passport guard and identifies the request source.
4
Make your first call
GET /api/v1/vehicles
Authorization: Bearer eyJ0eXAiOiJK...
X-Request-Type: client

# 200 OK — paginated list of vehicles for your organization

How authentication works

EonsFleet uses Laravel Passport (OAuth 2.0) with two guards and optional API key authentication for programmatic access.

🔑

OAuth 2.0 Password Grant

The standard method for user-context access. Exchange email + password for a token that expires in 24 hours.

POST /oauth/token
grant_type:    password
client_id:     2
client_secret: <secret>
username:      user@email.com
password:      secret
🔄

Token Refresh

Access tokens expire after 24 hours. Use the refresh token to get a new pair without re-entering credentials.

POST /oauth/token
grant_type:    refresh_token
client_id:     2
client_secret: <secret>
refresh_token: def50200...

API Keys

For server-to-server or CI/CD access. Create a key via the portal, then pass it on every request instead of a Bearer token.

# Create a key (requires Bearer token)
POST /api/v1/api-keys

# Use the key
X-API-KEY: eons_live_abc123...
X-Request-Type: client
🏢

Multi-tenancy

Every resource is scoped to your organization. The API resolves tenancy from your Bearer token — you never need to pass an org ID explicitly. All queries are automatically filtered.

Cross-tenant data access returns 403 or an empty result set — never data from another org.

Why X-Request-Type is required

The IdentifyRequestSource middleware reads this header to select the correct Passport guard (client vs admin) and to route the request to the correct authentication pipeline. Without it, the system cannot determine which user pool to authenticate against.

Header valueGuard usedUser modelUse case
client client App\Models\User All user-facing requests (web app, mobile app, API keys)
admin admin App\Models\Admin Internal platform administration only
Missing X-Request-Type → 400 Bad Request. The middleware rejects the request before authentication is attempted. Always include this header.

Access control model

Authorization is layered: role-based permissions gate individual endpoints, and subscription plan entitlements gate entire feature modules.

Available roles (client guard)

Role slugDescriptionTypical access
administratorFull org-level adminAll resources, all modules
fleet_managerFleet operations leadVehicles, trips, drivers, maintenance, analytics
dispatcherTrip dispatchCreate/assign trips, view vehicles
driverMobile app userOwn trips, own profile, report incidents
mechanicWorkshop technicianAssigned maintenance jobs, progress updates
financeFinancial oversightInvoices, fuel costs, subscriptions
complianceRegulatory complianceAudit logs, incident reports, analytics
vendorExternal workshop partnerAssigned maintenance jobs via Workshop Portal
adminLegacy aliasSame as administrator

Subscription plan gates

Routes protected by org.subscription:{feature} middleware check whether your organization's active subscription includes the required module. Accessing a gated route without the subscription returns 402.

MiddlewareRequired plan featureAffected routes
org.subscription:analyticsAnalytics module/api/v1/analytics/*
org.subscription:maintenanceMaintenance module/api/v1/maintenance/*
org.subscription:fuelFuel management/api/v1/fuel-expenses/*
org.subscription:trackingGPS Tracking/api/v1/trackers/*
org.subscription:geofenceGeofencing/api/v1/geofences/*
A dunning gate is also applied for overdue subscriptions. Organizations in restricted dunning stage receive 402 on all subscription-gated endpoints until payment is resolved.

Driver-specific endpoints

Routes under /api/v1/drivers/me* are restricted to users with the driver role and require Bearer token authentication (auth:client):

EndpointMethodDescription
/api/v1/drivers/meGETView own profile (driver record, org, vehicles)
/api/v1/drivers/mePATCHUpdate phone number or avatar URL
/api/v1/drivers/me/statsGETPerformance stats (trips, on-time rate, behavior score)
/api/v1/trips/mineGETList own assigned trips
/api/v1/trips/{id}/locationPOSTPush GPS location update (rate-limited: 60/min)

Consistent JSON:API error envelope

All error responses follow the same structure. Never parse HTTP status codes alone — always read errors[].code for machine-readable detail.

{
  "message": "Validation failed",
  "errors": [
    {
      "status": "422",
      "code":   "VALIDATION_ERROR",
      "title":  "Validation Failed",
      "detail": "The vehicle_id field is required.",
      "source": {
        "pointer": "/data/attributes/vehicle_id"
      }
    }
  ],
  "meta": {
    "request_id":        "17e0abc1-fd81-4d01-bf90-583772354bee",
    "version":            "v1",
    "timestamp":          "2026-03-04T12:00:00.000Z",
    "execution_time_ms":  7.43
  }
}
HTTP StatusCommon codesMeaning
200 / 201Success / Created
202Accepted (queued job dispatched — e.g. GPS location push)
204No content (resource deleted)
400MISSING_REQUEST_TYPEX-Request-Type header missing
401UNAUTHENTICATED, INVALID_API_KEYNo valid Bearer token or API key
402PAYMENT_REQUIREDSubscription gate — plan doesn't include this feature, or account in dunning
403FORBIDDENAuthenticated but insufficient role/permission, or cross-tenant access attempt
404NOT_FOUNDResource doesn't exist (or you don't have visibility into it)
422VALIDATION_ERRORRequest body failed validation — check errors[].source.pointer
429TOO_MANY_REQUESTSRate limit exceeded (GPS endpoint: 60/min)
500SERVER_ERRORUnexpected server error — contact support with the request_id
💡 The source.pointer field uses JSON Pointer syntax (RFC 6901) to pinpoint exactly which field failed validation — e.g. /data/attributes/vehicle_id.
📖

Interactive API Reference

Explore all 90+ endpoints with live request/response examples, request builder, and authentication flow — powered by Scalar.

Open API Reference →