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>.
Notes about account scoping
Most endpoints require an accountId UUID to scope reads and writes to a specific organization. The API expects accountId as a query parameter for reads and as part of the request body for writes when indicated.
Response Format
All endpoints return a unified envelope:
{
"success": true,
"message": "optional human readable message",
"data": {},
"count": 1,
"error": "error text"
}
Errors include success:false, a message and an error string.
Field reference (selected)
Tariff record (selected fields):
id(integer)name(string)description(string|null)account_id(uuid)meter_type(enum)tariff_type(enum)currency(enum)tax_rate(decimal)is_active(boolean)effective_from/effective_to(timestamp)timezone(string)
Tariff item record (selected fields):
id(integer)tariff_id(integer)item_type_code(enum)price(decimal)applies_to(string|null)season(enum|null)
Endpoints
Base path: /api/v1/tariffs
List Tariffs
GET /api/v1/tariffs
Query parameters
accountId(uuid, required)page(int, default 1)limit(int, default 10, max 100)query(string, optional)sortBy(string, defaultcreated_at)sortOrder(asc|desc, defaultdesc)meter_type(enum: ELECTRICITY | GAS | WATER | CARBON | SOLAR | GENSET, 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)
accountId(uuid, required)name(string, required)description(string, optional)meter_type(enum, optional)tariff_type(enum, optional)dso_id(int, optional)
Note: Additional fields (e.g. tax_rate, currency, effective_from) may be added later; current schema is minimal.
Example:
{
"accountId": "<account-uuid>",
"name": "Residential Flat Rate",
"description": "Standard residential plan",
"meter_type": "ELECTRICITY",
"tariff_type": "FLAT"
}
Response 201 — created tariff object in data.
Get / Update / Delete Tariff
GET /api/v1/tariffs/:id — requires accountId query param, returns tariff plus its tariff_items children.
PUT /api/v1/tariffs/:id Body fields:
accountId(uuid, required)- Any updatable:
name,description,timezone,notes,meter_type,tariff_type,dso_id
DELETE /api/v1/tariffs/:id — requires accountId query param; returns 204 on success.
Catalogue guard: Attempts to update or delete a tariff whose account_id matches the catalogue account ID will return a 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 or use. 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)
Response 200 envelope data contains an array of tariff records (same shape as regular tariffs) with count = total matching catalogue tariffs.
Example response (truncated):
{
"success": true,
"message": "Retrieved 2 of 2 catalogue tariffs",
"data": [
{
"id": 101,
"name": "Standard Residential",
"meter_type": "electricity",
"tariff_type": "time_of_use",
"currency": "USD",
"timezone": "America/New_York"
}
],
"count": 2
}
Get Catalogue Tariff
GET /api/v1/tariffs/catalogue/:id
Path parameter:
id(integer)
Returns 200 with a single tariff object in data. 404 if the tariff does not exist.
Clone Catalogue Tariff
POST /api/v1/tariffs/catalogue/:id/clone
Purpose: Creates a new mutable tariff in the destination account, copying catalogue tariff fields and items.
Path parameter:
id(integer) — source catalogue tariff ID
Request body:
{
"accountId": "<destination-account-uuid>",
"name": "Optional override name"
}
Field notes:
accountIdis required.nameoptional; falls back to source name.
Response 201 — cloned tariff (basic fields) plus cloned tariff_items. Errors: 400 invalid body / catalogue guard, 404 not found.
Catalogue Tariff Items
Catalogue tariff items are included when listing or retrieving catalogue tariffs. They cannot be updated or deleted. To modify pricing logic, clone the tariff then edit its items via the regular tariff item endpoints.
Errors
- 400 Invalid query or clone request body.
- 401 Missing/invalid authentication.
- 404 Catalogue tariff not found.
- 429 Excessive requests (rate limits may apply).
Immutability Guarantee
Catalogue tariffs and their items are read-only; cloning produces a distinct mutable copy with a new id under the destination accountId.
Tariff Items
List Items
GET /api/v1/tariffs/:id/items Query parameters: page, limit, query, sortBy, sortOrder. Returns paginated items (tariff_items).
Bulk Create Items
POST /api/v1/tariffs/:id/items Body may be either a single object or an array of objects:
{
"price": 100.5,
"item_type_code": "ENERGY",
"season": "SUMMER",
"applies_to": "peak"
}
or
[
{ "price": 100.5, "item_type_code": "ENERGY" },
{ "price": 80.0, "item_type_code": "ENERGY", "season": "WINTER" }
]
Response 201 — created items array.
Update Single Item
PUT /api/v1/tariffs/:id/items/:itemId Body fields (all optional): price, item_type_code, season, applies_to. Response 200 — updated item.
Delete Single 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.
Error Format Example
Serialized error sample when validation fails:
{
"success": false,
"error": "{\"message\":\"Invalid request body\"}",
"message": null
}
*** End of document