Rate specifications
Manage composable rate specifications and pricing strategies.
Rate specifications API
Endpoints for managing rate specifications, assigning rates to catalogue items, calculating charges, and reading rate-engine metadata.
Endpoints
| Method | URL | Description |
|---|---|---|
| GET | /api/v1/rate_specifications |
List rate specifications |
| GET | /api/v1/rate_specifications/{id} |
Show a rate specification |
| POST | /api/v1/rate_specifications |
Create a rate specification |
| PUT | /api/v1/rate_specifications/{id} |
Update a rate specification |
| DELETE | /api/v1/rate_specifications/{id} |
Delete a rate specification |
| POST | /api/v1/rate_specifications/{id}/duplicate |
Duplicate a definition into an editable copy |
Catalogue item rates (nested)
| Method | URL | Description |
|---|---|---|
| GET | /api/v1/catalogue_items/{catalogue_item}/rates |
List a catalogue item's rate assignments |
| GET | /api/v1/catalogue_items/{catalogue_item}/rates/{id} |
Show a catalogue item rate |
| POST | /api/v1/catalogue_items/{catalogue_item}/rates |
Assign a rate to a catalogue item |
| PUT | /api/v1/catalogue_items/{catalogue_item}/rates/{id} |
Update a catalogue item rate |
| DELETE | /api/v1/catalogue_items/{catalogue_item}/rates/{id} |
Remove a catalogue item rate |
Calculation & Metadata
| Method | URL | Description |
|---|---|---|
| POST | /api/v1/catalogue_items/{catalogue_item}/calculate_rate |
Calculate a rate breakdown for a rental window |
| GET | /api/v1/rate_engine/strategies |
List calculation strategies |
| GET | /api/v1/rate_engine/modifiers |
List modifiers |
| GET | /api/v1/rate_engine/presets |
List shipped presets |
| GET | /api/v1/rate_engine/schema |
Compose the config-form schema for a strategy |
Authentication
Read endpoints require a Sanctum bearer token with the rates:read ability; write endpoints require rates:write. The calculate_rate endpoint accepts either rates:read or catalogue-items:read, so catalogue-item-scoped integrations can price without rate management access.
List Rate specifications
GET /api/v1/rate_specifications
Filters
| Parameter | Description |
|---|---|
q[name_cont]=daily |
Name contains |
q[calculation_strategy_eq]=period |
Filter by strategy (period, fixed, hybrid) |
q[base_period_eq]=daily |
Filter by base period |
q[is_preset_true]=1 |
Presets only |
q[preset_slug_eq]=daily-rate |
Filter by preset slug |
Includes
Eager-load relationships with ?include=clonedFrom,catalogueItemRates.
Response
{
"rate_specifications": [
{
"id": 1,
"name": "Daily Rate",
"description": "A flat charge for each day of the rental.",
"calculation_strategy": "period",
"calculation_strategy_name": "Period-based",
"base_period": "daily",
"base_period_name": "Daily",
"enabled_modifiers": [],
"strategy_config": {},
"modifier_configs": {},
"is_preset": true,
"preset_slug": "daily-rate",
"cloned_from_id": null,
"created_at": "2026-01-15T14:30:00Z",
"updated_at": "2026-01-15T14:30:00Z"
}
],
"meta": {
"total": 11,
"per_page": 20,
"page": 1
}
}
Create Rate specification
POST /api/v1/rate_specifications
Request Body
{
"name": "Daily with Tiers",
"calculation_strategy": "period",
"base_period": "daily",
"description": "Daily rate with duration multipliers.",
"enabled_modifiers": ["multiplier"],
"strategy_config": { "day_type": "clock", "leeway_minutes": 60 },
"modifier_configs": {
"multiplier": { "tiers": [{ "multiplier": "1.0" }, { "multiplier": "0.9" }] }
}
}
strategy_config and each entry in modifier_configs are validated against the composed schema for the chosen strategy and enabled modifiers. Hidden and disabled-modifier values are stripped before saving. Returns 201 Created with the rate specification object.
Duplicate Rate specification
POST /api/v1/rate_specifications/{id}/duplicate
Creates an editable copy named "{name} (Copy)" with is_preset false, preset_slug null, and cloned_from_id set to the source. Returns 201 Created.
Catalogue item rates
GET /api/v1/catalogue_items/{catalogue_item}/rates
POST /api/v1/catalogue_items/{catalogue_item}/rates
Request Body
{
"rate_specification_id": 1,
"transaction_type": "rental",
"price": 5000,
"currency": "GBP",
"warehouse_id": null,
"valid_from": "2026-01-01",
"valid_to": null,
"priority": 0
}
Note:
priceis sent in minor units (pence/cents) as an integer. Responses return it as a decimal string ("50.00").
Response
{
"product_rate": {
"id": 7,
"catalogue_item_id": 1,
"rate_specification_id": 1,
"warehouse_id": null,
"transaction_type": "rental",
"transaction_type_name": "Rental",
"price": "50.00",
"currency": "GBP",
"valid_from": "2026-01-01",
"valid_to": null,
"priority": 0,
"created_at": "2026-01-15T14:30:00Z",
"updated_at": "2026-01-15T14:30:00Z"
},
"meta": {
"overlapping_rate_ids": []
}
}
meta.overlapping_rate_ids lists any existing rates that overlap the saved rate on warehouse, transaction type, priority, and date window. Overlaps are permitted (resolved by priority at calculation time); the list is a non-blocking warning.
Calculate Rate
POST /api/v1/catalogue_items/{catalogue_item}/calculate_rate
Resolves the highest-priority catalogue item rate for the given warehouse, transaction type, and start date, then runs the rate engine over the rental window.
Request Body
{
"quantity": 2,
"start": "2026-02-01T09:00:00Z",
"end": "2026-02-06T17:00:00Z",
"transaction_type": "rental",
"warehouse_id": null
}
Response
{
"rate_breakdown": {
"currency": "GBP",
"unit_price": "100.00",
"units": 5,
"unit_label": "days",
"per_unit_subtotal": "500.00",
"quantity": 2,
"total": "1000.00",
"line_items": [
{
"period_from": 1,
"period_to": 5,
"multiplier": "1.0",
"unit_price": "100.00",
"line_total": "500.00"
}
],
"applied_modifiers": []
},
"meta": {
"resolved": true,
"rate_specification_id": 1,
"product_rate_id": 7
}
}
Note: When no catalogue item rate is configured, the response is a zero-priced breakdown spanning the period and
meta.resolvedisfalse— catalogue items carry no standalone price, so this is an explicit "no rate configured" signal rather than a misleading amount.
Rate Engine Metadata
These read-only endpoints expose the same data the framework uses to render its rate-specification form, so external builders can reproduce it.
GET /api/v1/rate_engine/strategies
GET /api/v1/rate_engine/modifiers
GET /api/v1/rate_engine/presets
GET /api/v1/rate_engine/schema?strategy=period&modifiers[]=multiplier
strategies reports each strategy's allowed_base_periods and whether it supports each modifier. schema requires a strategy and optional modifiers[], validates them against the registered set (422 on unknown values), and returns ordered form sections of fields.
Legacy Rate Engine Mapping
Signals presets mirror common industry rate engine types, so an imported catalogue item rate maps onto a preset of the same shape. Match the source legacy rate engine name to the preset slug below.
| Source legacy rate engine | Signals Preset Slug |
|---|---|
| Daily Rate | daily-rate |
| Daily Multiplier and Factor Rate | daily-multiplier-factor |
| Hourly Rate | hourly-rate |
| Hourly Multiplier and Factor Rate | hourly-multiplier-factor |
| Half Hourly Rate | half-hourly-rate |
| Weekly Rate | weekly-rate |
| Monthly Rate | monthly-rate |
| Monthly Multiplier and Factor Rate | monthly-multiplier-factor |
| Fixed Rate | fixed-rate |
| Fixed Rate and Factor | fixed-rate-factor |
| Fixed Rate and Subs Days | fixed-rate-subs-days |
| Days Used Rate | daily-rate (fallback) |
Note: Some legacy platforms offer a "Days Used Rate Engine" that depends on per-asset usage tracking, which is not implemented in this version. Such rates map to the Daily Rate preset as a documented fallback and can be revisited once usage data is available.