Developer platform
FuelSync API
Quote, place, track and cancel fuel orders from your own POS system, ERP connector, or dispatch software — the same pricing and order pipeline the FuelSync app itself runs on.
Pricing
Developer-friendly pricing built for rapid integration.
Build on FuelSync. Fuel. EV. Roadside. Fleet energy. Procurement. One API.
Loading plans…
Every plan includes full sandbox access with no request limit — build and test for free, upgrade only once you're ready for production traffic.
Authentication
Every request needs an Authorization header with an API key. Keys are self-service — sign in to any FuelSync account and generate one from the developer settings page.
Authorization: Bearer fs_live_8a3b21e9c4f6d05a17b2e4c8f9012ab3 # fs_test_... keys run against the sandbox environment — they never # create real orders, so they're safe for integration testing.
Sandbox vs production
A key's environment is fixed at creation. fs_test_... keys return realistic pricing but never write a real order — order-creation responses are clearly marked "simulated": true and their IDs can't be looked up afterwards. fs_live_... keys place real orders that get dispatched to a real runner or driver.
Endpoints
/api/v1/fuel/quotescope: fuel:quoteGet current fuel price and delivery-fee estimate. Side-effect free — never creates anything.
Request body
{
"product": "diesel_50ppm",
"quantity_litres": 500,
"province": "GP",
"distance_km": 12
}Response
{
"data": {
"quote_id": "quote_...",
"product": "diesel_50ppm",
"fuel_cost_cents": 1105000,
"delivery_fee": { "total_cents": 45000, "...": "..." },
"expires_at": "2026-01-01T12:15:00Z"
},
"meta": { "request_id": "req_...", "environment": "production" }
}/api/v1/fuel/ordersscope: fuel:orders:createCreate a fuel order on behalf of your own customer. Requires a delivery address and GPS coordinates.
Request body
{
"product": "diesel_50ppm",
"quantity_litres": 500,
"province": "GP",
"delivery_address": "1 Example St, Sandton",
"delivery_location": { "latitude": -26.1076, "longitude": 28.0567 },
"payment_type": "cash",
"external_customer_ref": "your-internal-customer-id"
}Response
{
"data": {
"order_id": "...",
"status": "pending",
"total_cents": 1150000,
"simulated": false
},
"meta": { "request_id": "req_...", "environment": "production" }
}/api/v1/fuel/orders/:idscope: fuel:orders:readRead an order's current status, driver, and totals. Only orders your own key created are visible.
Response
{
"data": {
"order_id": "...",
"status": "dispatched",
"driver_name": "T. Nkosi",
"total_cents": 1150000,
"external_customer_ref": "your-internal-customer-id"
},
"meta": { "request_id": "req_...", "environment": "production" }
}/api/v1/fuel/orders/:id/cancelscope: fuel:orders:cancelCancel an order you created, before it's completed. Orders that are already completed, cancelled, or refunded return 409.
Request body
{ "reason": "Customer changed their mind" }Response
{
"data": { "order_id": "...", "status": "cancelled" },
"meta": { "request_id": "req_...", "environment": "production" }
}Fleet & demand intelligence
The fleet:read scope is not granted by default — it requires an admin to link your API partner account to a specific FuelSync fleet (partner_accounts row) first. /api/v1/vehicles/* and /api/v1/fleet/* only ever return data for vehicles/runners that are active members of that one linked fleet — every other id, including a real vehicle belonging to a different fleet, returns 404 rather than 403, so a probing request can't confirm it exists.
/api/v1/vehicles/:id/capabilitiesscope: fleet:readA vehicle's Vehicle Capability Profile — configuration (dedicated / multi_compartment / service_only), fuel types carried, total capacity, and per-compartment breakdown.
Response
{
"data": {
"vehicle_id": "...",
"configuration": "multi_compartment",
"fuel_types": ["diesel_50ppm", "petrol_95"],
"capacity_l": 4000,
"compartment_count": 3,
"compartments": [
{ "position": 1, "product": "diesel_50ppm", "capacity_l": 2500, "current_volume_l": 2200 },
{ "position": 2, "product": "petrol_95", "capacity_l": 1000, "current_volume_l": 900 }
]
},
"meta": { "request_id": "req_...", "environment": "production" }
}/api/v1/vehicles/:id/inventoryscope: fleet:readA vehicle's real current load — distinct from capability. Capable of carrying diesel is not the same fact as currently carrying enough of it.
Response
{
"data": {
"vehicle_id": "...",
"total_capacity_l": 4000,
"total_current_load_l": 3100,
"available_headroom_l": 900,
"compartments": [
{ "position": 1, "product": "diesel_50ppm", "capacity_l": 2500, "current_volume_l": 2200, "available_headroom_l": 300 }
]
},
"meta": { "request_id": "req_...", "environment": "production" }
}/api/v1/vehicles/:id/opportunitiesscope: fleet:readReal nearby demand this vehicle can act on, ranked by the same opportunity_score the mobile Opportunity Map uses. Requires ?lat=&lng= (the vehicle's current position — this API has no live GPS feed to fall back to); optional &radius_km= (default 20).
Response
{
"data": {
"vehicle_id": "...",
"opportunities": [
{ "order_id": "...", "fuel_type": "diesel_50ppm", "litres": 200, "distance_km": 2.1, "fulfillability": "fulfillable", "opportunity_score": 0.91 }
]
},
"meta": { "request_id": "req_...", "environment": "production" }
}/api/v1/demand/nearbyscope: fleet:readReal network-wide demand near a point — not fleet-scoped. Requires ?lat=&lng=; optional &radius_km= (default 20) and &product= to filter the breakdown to one fuel type.
Response
{
"data": {
"window_days": 7,
"radius_km": 20,
"by_product": [
{ "fuel_type": "diesel_50ppm", "order_count": 12, "total_litres": 9800, "open_count": 4 }
]
},
"meta": { "request_id": "req_...", "environment": "production" }
}/api/v1/fleet/:id/inventoryscope: fleet:read:id is your linked fleet's own id — aggregate real capacity and current load across every active vehicle in it.
Response
{
"data": {
"fleet_id": "...",
"vehicle_count": 6,
"total_capacity_l": 14000,
"total_current_load_l": 9200,
"vehicles": [ { "vehicle_id": "...", "fuel_types": ["diesel_50ppm"], "capacity_l": 2000, "current_load_l": 1240, "configuration": "dedicated" } ]
},
"meta": { "request_id": "req_...", "environment": "production" }
}/api/v1/fleet/:id/demandscope: fleet:readReal nearby demand centered on your fleet's own registered address. Optional ?radius_km= (default 20). Returns 409 if the fleet has no registered lat/lng yet.
Response
{
"data": {
"fleet_id": "...",
"window_days": 7,
"radius_km": 20,
"by_product": [ { "fuel_type": "diesel_50ppm", "order_count": 5, "total_litres": 4200, "open_count": 2 } ]
},
"meta": { "request_id": "req_...", "environment": "production" }
}Webhooks
Configure a webhook URL from the developer settings page to get notified on order.created and order.cancelled. Every delivery is signed:
X-Webhook-Timestamp: 1735689600
X-Webhook-Id: <delivery id>
X-Webhook-Signature: sha256=<hex(hmac_sha256(secret, `${timestamp}.${id}.${rawBody}`))>Errors
Every error follows the same shape:
{
"error": {
"code": "MISSING_SCOPE",
"message": "This API key does not have the 'fuel:orders:create' scope.",
"request_id": "req_...",
"details": { "required_scope": "fuel:orders:create", "granted_scopes": ["fuel:quote"] }
}
}429 RATE_LIMIT_EXCEEDED is returned once you exceed your plan's requests-per-minute limit (visible on your developer settings page).
Scopes
Self-service keys are granted the core order-lifecycle scopes automatically. Other scopes below are part of the platform but not yet self-service — contact FuelSync if your integration needs one of them.
Loading…
