Tariff API
Manage tariffs and tariff items — list, create, read, update, delete, and catalogue operations.
Tariff API Documentation
Overview
The Tariff API provides endpoints for managing tariffs and their pricing components (tariff items). Tariffs are associated with organizations and meter types, and can be cloned from a global read-only catalogue.
Authentication
All tariff endpoints require authentication. Include a valid Bearer token in the Authorization header: Authorization: Bearer <access_token>.
Account scoping
All endpoints require an account_id UUID to scope reads and writes to a specific organization.
- List / read / delete — pass
account_idas a query parameter - Create / update — include
account_idin the JSON request body
Response format
All endpoints return a unified envelope:
{
"success": true,
"message": "optional human readable message",
"data": {},
"count": 1,
"error": "error text"
}
Field reference
Tariff record (selected fields):
id(integer)name(string)description(string|null)account_id(uuid)dso_id(integer|null) — foreign key to the energy providermeter_type(enum: ELECTRICITY | GAS | WATER | CARBON | SOLAR | GENSET | EV)tariff_type(enum: FLAT | TIME_OF_USE | BLOCK)currency(string)tax_rate(decimal)is_active(boolean)effective_from/effective_to(ISO 8601 timestamp)timezone(string)
DSO object (nested on tariff reads, null when no provider is set):
id(integer)name(string)tz(string) — IANA timezone identifier (e.g.Africa/Johannesburg)
Tariff item record (selected fields):
id(integer)tariff_id(integer)item_type_code(string)price(decimal)applies_to(string|null)season(string|null)
Endpoints
Base path: /api/v1/tariffs
List Tariffs
GET /api/v1/tariffs
Query parameters:
account_id(uuid, required)page(int, default 1)limit(int, default 10, max 100)query(string, optional — text search)sortBy(string, defaultcreated_at)sortOrder(asc|desc, defaultdesc)meter_type(enum: ELECTRICITY | GAS | WATER | CARBON | SOLAR | GENSET | EV, optional)tariff_type(enum: FLAT | TIME_OF_USE | BLOCK, optional)dso_id(int, optional)
Response 200 — list envelope with data array and count.
Create Tariff
POST /api/v1/tariffs
Request body (JSON):
account_id(uuid, required)name(string, required)description(string, optional)meter_type(enum, optional)tariff_type(enum, optional)dso_id(int, optional)
Example:
{
"account_id": "<account-uuid>",
"name": "Residential Flat Rate",
"description": "Standard residential plan",
"meter_type": "ELECTRICITY",
"tariff_type": "FLAT"
}
Response 201 — created tariff object in data.
Get Tariff
GET /api/v1/tariffs/:id
Query parameters:
account_id(uuid, required)
Returns 200 with the tariff and its nested tariff_items array and dso object.
Update Tariff
PUT /api/v1/tariffs/:id
Request body:
account_id(uuid, required)name(string, optional)description(string, optional)timezone(string, optional)notes(string, optional)meter_type(enum: ELECTRICITY | GAS | WATER | CARBON | SOLAR | GENSET | EV, optional)tariff_type(enum: FLAT | TIME_OF_USE | BLOCK, optional)dso_id(int, optional)effective_from(ISO 8601 string, optional)effective_to(ISO 8601 string, optional)deleted_at(ISO 8601 string, optional)currency(enum: USD | EUR | GBP | ZAR, optional)tax_rate(positive integer, optional)updated_by(uuid, optional)is_active(boolean, optional)cloned_from(integer, optional)
Response 200 — updated tariff object in data.
Delete Tariff
DELETE /api/v1/tariffs/:id
Query parameters:
account_id(uuid, required)
Response 204 — no content.
Catalogue guard: Attempts to create, update, or delete a tariff belonging to the catalogue account return 400 (Catalogue is read-only).
Catalogue (read-only)
The catalogue provides globally maintained, immutable tariff definitions that can be cloned into an organization's scope for customization. Catalogue tariffs and their items cannot be modified directly.
Base path: /api/v1/tariffs/catalogue
List Catalogue Tariffs
GET /api/v1/tariffs/catalogue
Query parameters:
page(int, default 1)limit(int, default 10, max 100)query(string, optional — fuzzy match against name/description)sortBy(string, defaultcreated_at)sortOrder(asc|desc, defaultdesc)meter_type(enum, optional)tariff_type(enum, optional)
Response 200 — data array of catalogue tariff records with count.
Get Catalogue Tariff
GET /api/v1/tariffs/catalogue/:id
Path parameter:
id(integer)
Returns 200 with the catalogue tariff and its nested tariff_items and dso object. Returns 404 if not found.
Clone Catalogue Tariff
POST /api/v1/tariffs/catalogue/:id/clone
Creates a new fully mutable tariff in the destination account, copying all catalogue tariff fields and items.
Path parameter:
id(integer) — source catalogue tariff ID
Request body:
{
"account_id": "<destination-account-uuid>",
"name": "Optional override name"
}
account_id(uuid, required) — destination organizationname(string, optional) — falls back to source tariff name
Response 201 — cloned tariff with tariff_items array and dso object.
Errors: 400 invalid body, 404 catalogue tariff not found.
TOU Schedule
Get TOU Schedule
GET /api/v1/tariffs/:id/schedule
Returns the Time-of-Use schedule and its linked rules for a tariff. Only applicable when tariff_type is TIME_OF_USE.
Path parameter:
id(integer) — tariff ID
Query parameters:
account_id(uuid, required)
Fallback behaviour: When the tariff has no tou_schedule_id configured, schedule ID 3 is used as the default.
Response 200 — schedule object in data:
{
"success": true,
"data": {
"id": 3,
"name": "Standard TOU Schedule",
"dso_id": 1,
"holiday_default": "WEEKEND",
"is_active": true,
"tz": "Africa/Johannesburg",
"version": 1,
"tou_rules": [
{
"id": 1,
"schedule_id": 3,
"season_id": 1,
"day_type": "WEEKDAY",
"period": "PEAK",
"start_minute": 420,
"end_minute": 540
}
]
}
}
tou_rule fields:
id(integer)schedule_id(integer)season_id(integer) — references a DSO seasonday_type(enum) — e.g.WEEKDAY,WEEKENDperiod(enum) — e.g.PEAK,STANDARD,OFF_PEAKstart_minute(integer) — minutes from midnight (0–1439)end_minute(integer) — minutes from midnight (exclusive)
Errors:
400— tariff exists but is notTIME_OF_USE404— tariff or TOU schedule not found
Tariff Items
List Items
GET /api/v1/tariffs/:id/items
Query parameters: page, limit, query, sortBy, sortOrder.
Returns paginated tariff_items.
Bulk Create Items
POST /api/v1/tariffs/:id/items
Body may be a single object or an array:
[
{ "price": 100.5, "item_type_code": "ENERGY" },
{ "price": 80.0, "item_type_code": "ENERGY", "season": "WINTER" }
]
Fields:
price(decimal, required)item_type_code(string, required)season(string, optional)applies_to(string, optional)
Response 201 — array of created items.
Update Item
PUT /api/v1/tariffs/:id/items/:itemId
Body fields (all optional): price, item_type_code, season, applies_to.
Response 200 — updated item.
Delete Item
DELETE /api/v1/tariffs/:id/items/:itemId
Response 204 — no content.
Catalogue guard: Any attempt to modify items of a catalogue tariff returns 400 with Catalogue is read-only.