SA Fuel Price API
Monthly South African fuel retail prices as published by the Department of Mineral Resources and Energy (DMRE). Prices are in Rands per litre and cover 95 ULP, 93 ULP and Diesel (0.05% sulphur) for inland and coastal zones.
Data runs from January 2024 to present and is updated monthly on the first Wednesday of each month.
Base URL: https://sa-fuel-api.railway.app
Quickstart
All read endpoints are open — no API key needed.
// Fetch latest prices
fetch('https://sa-fuel-api.railway.app/v1/prices/latest')
.then(r => r.json())
.then(data => console.log(data));
// Get 12 months history
fetch('https://sa-fuel-api.railway.app/v1/prices?limit=12')
.then(r => r.json())
.then(data => console.log(data.data));
Authentication
Read endpoints (GET) are public. Write endpoints (POST, PUT) require an API key.
// Option A — Authorization header (recommended)
fetch('/v1/prices', {
method: 'POST',
headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
body: JSON.stringify({ ... })
});
// Option B — Query param
fetch('/v1/prices?api_key=YOUR_API_KEY', { method: 'POST', ... });
Rate Limits
| Endpoint type | Limit | Window |
|---|---|---|
| Read (GET) | 100 requests | 15 minutes |
| Write (POST, PUT) | 20 requests | 1 hour |
Rate limit headers are returned on every response: RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset.
Response Format
All responses are JSON. Successful responses include success: true and a data field. Errors include success: false and an error object.
// Success
{
"success": true,
"data": {
"month": "2026-05",
"monthLabel": "May 2026",
"prices": {
"petrol": { "p95Inland": 26.63, "p95Coastal": 25.76, "p93Inland": 26.52 },
"diesel": { "d005Inland": 31.18, "d005Coastal": 30.30 }
},
"source": "DMRE",
"updatedAt": "2026-05-06T00:00:00.000Z"
}
}
// Error
{
"success": false,
"error": { "code": "NOT_FOUND", "message": "No prices found for 2024-13." }
}
Endpoints
Returns all months, newest first. Paginate with limit and offset.
| Param | Type | Default | Description |
|---|---|---|---|
limit | integer | 50 | Max rows (cap 200) optional |
offset | integer | 0 | Skip rows optional |
GET /v1/prices?limit=12
Returns the most recent month's prices only.
GET /v1/prices/latest
Returns prices for a specific month. Month must be in YYYY-MM format.
GET /v1/prices/2026-05
GET /v1/prices/2025-01
Returns all months within an inclusive date range.
| Param | Type | Description |
|---|---|---|
from | YYYY-MM | Start month required |
to | YYYY-MM | End month required |
GET /v1/prices/range?from=2025-01&to=2025-12
Returns aggregate statistics — min, max and average prices across all months.
GET /v1/stats
Add a new month's prices. Returns 409 Conflict if the month already exists.
| Field | Type | |
|---|---|---|
month | YYYY-MM | required |
monthLabel | string | required e.g. "Jun 2026" |
p95i | number | required 95 ULP Inland |
p95c | number | required 95 ULP Coastal |
p93i | number | required 93 ULP Inland |
d005i | number | required Diesel 0.05% Inland |
d005c | number | required Diesel 0.05% Coastal |
source | string | optional defaults to "DMRE" |
Update one or more price fields for an existing month. Only supplied fields are updated.
// Correct a single price
PUT /v1/prices/2026-05
{ "p95i": 26.71 }
Data source
Prices are sourced from the DMRE monthly gazette and cross-referenced with the Fuels Industry Association of South Africa (FIASA). New prices are published on the first Wednesday of each month and take effect from midnight.
Prices are in Rands per litre and include all levies, taxes and fuel levies as gazetted. Inland prices apply to Gauteng; coastal prices apply to Durban, Cape Town and Port Elizabeth.