Skip to content

Pricing Modifiers

Taxi & Private HireProductsPricing › Pricing Modifiers

Generally available

Conditional adjustments applied on top of the base tariff — surcharges, premiums, or rebates triggered by an arbitrary decision tree. Each modifier holds a list of ModifierInstruction rows specifying which price column to adjust and by how much, plus a chaining strategy controlling how it composes with other matching modifiers (multiply, add, override). Operators model rules like "20% premium on Friday/Saturday nights", "€5 airport surcharge", "fixed €25 for school-run accounts" without code.

Example request

POST /client/{clientId}/tariff

{
  "name": "<string>",
  "modifierChainingStrategy": "CHAIN",
  "decisionTree": {},
  "modifier": {},
  "parentModifierGroup": {
    "id": "<id>"
  },
  "targetModifierGroup": {
    "id": "<id>"
  },
  "instructions": [
    {
      "id": "<id>"
    }
  ]
}

Example shape, derived from the Modifier fields — indicative, not the authoritative schema (that arrives with the API reference).

Endpoints

MethodPath
POST /client/{clientId}/modifierinstruction/{instructionId}/tariffband/{tariffbandId}
POST /client/{clientId}/tariff/{tariffId}/modifier/{modifierId}/modifierinstruction
DELETE /client/{clientId}/tariff/{tariffId}/modifier/{modifierId}/modifierinstruction/{instructionId}
GET /client/{clientId}/tariff/{tariffId}/modifier/{modifierId}/tariffband
GET /client/{clientId}/tariff/{tariffId}/modifier/{modifierId}/modifierinstruction
DELETE /client/{clientId}/modifierinstruction/{instructionId}/tariffband/{tariffbandId}
POST /client/{clientId}/tariff/{tariffId}/modifier/{modifierId}/modifierinstruction/{instructionId}
POST /client/{clientId}/tariff/{tariffId}/modifiergroup/{modifierGroupId}/modifier
POST /client/{clientId}/tariff/{tariffId}/modifiergroup
POST /client/{clientId}/tariff · primary
DELETE /client/{clientId}/tariff/{tariffId}/modifiergroup/{modifierGroupId}
DELETE /client/{clientId}/tariff/{tariffId}/modifiergroup/{modifierGroupId}/modifier/{modifierId}
GET /client/{clientId}/tariff/{tariffId}
DELETE /client/{clientId}/tariff/{tariffId}/modifier/{modifierId}/modifiergroup/{modifierGroupId}
POST /client/{clientId}/tariff/{tariffId}/modifier/{modifierId}/modifiergroup/{modifierGroupId}
GET /client/{clientId}/tariff/test/{tripSegmentId}
POST /client/{clientId}/tariff/{tariffId}
POST /client/{clientId}/tariff/{tariffId}/modifier/{modifierId}
POST /client/{clientId}/tariff/{tariffId}/modifiergroup/{modifierGroupId}

Full request/response schemas and an interactive explorer will live in the API reference (coming soon).

Use cases

Operator flows that exercise this feature.

Add a pricing modifier

tune risk: high approval required

Add a pricing modifier (surcharge / discount). Affects all future pricing — requires approval.

  1. POST /client/{clientId}/tariff/{tariffId}/modifiergroup/{modifierGroupId}/modifier
Add a modifier group

config risk: medium

Add a modifier group to a tariff (container for surcharge / discount rules).

  1. POST /client/{clientId}/tariff/{tariffId}/modifiergroup
Create a tariff

config risk: medium

Create a tariff and add its first distance/time band.

  1. POST /client/{clientId}/tariff
  2. POST /client/{clientId}/tariff/{tariffId}/tariffband

Fields

FieldTypeDescription
name string Operator-friendly name shown in modifier-graph dropdowns and on the trip-charge breakdown row when this modifier fires. "Friday Night Premium", "Airport Surcharge", etc.
modifierChainingStrategy ModifierChainingStrategy · CHAIN | RESTART How evaluation continues after this modifier fires: CHAIN walks to targetModifierGroup, STOP halts the modifier evaluation entirely. Lets operators model "if airport surcharge fires, skip the night-rate surcharge" patterns without nested decision trees.
decisionTree JsonStorage JsonCondition tree (AND/OR/NOT over typed leaves) that decides whether the modifier applies to a given trip. Edited in the operator console as a visual node graph; persisted as a typed JSON blob via JsonStorageTypedAccessor.
modifier JsonStorage Deprecated legacy pricing-data blob. Replaced by the ModifierInstruction[] list (see `instructions`); retained for backward compatibility with old tariff configs.
parentModifierGroup ModifierGroup Parent ModifierGroup — the bucket this modifier sits inside on the operator-console graph. Groups partition modifiers for both UI layout and chain navigation.
targetModifierGroup ModifierGroup Next ModifierGroup in the chain — where evaluation continues if this modifier fires and the chaining strategy is CHAIN. Null = end of chain.
instructions Collection Price adjustments this modifier applies — each ModifierInstruction targets a specific price column (perKm, perMin, pickup, etc.) and specifies a delta. Multiple instructions on one modifier execute together when the decision tree matches.
clientId bigint Tenant scope. Every tenant-aware entity carries this; `ClientFilter` enforces row-level isolation on read; the multi-tenancy routing layer (`/client/{clientId}`) sets it at create time. Surfaced only under `admin` / `tripLog` groups — never to end users.
internalKey string Optional client-supplied external reference / idempotency key. When present, lets external systems correlate platform-side records back to their own source-of-truth ids. Not persisted to a column — populated by the request handler when the caller sets it.
__objectType string Discriminator string (entity class short-name) emitted alongside the id in serialized output. Resolved at read time by `getObjectType()`; lets the FE dispatch entity-specific rendering without inspecting the URL.
id bigint Snowflake-style primary key (unsigned BIGINT). Generated by `IdFactory` at create time; surfaced to the FE / API as a `G`-prefixed string and stripped back to plain bigint server-side before Doctrine lookup.
createdDate integer Unix timestamp the row was first persisted. Set in the entity's PrePersist hook; never rewritten on subsequent updates.
updatedDate integer Unix timestamp the row was last touched. Bumped on every commit that hits the Doctrine UoW for this entity; drives FE invalidation + the listing change cursor.
passiveUpdatedDate int Read-through alias for `updatedDate` exposed under different serializer groups. Lets the FE distinguish "real edit" from "background touch" projections without changing the underlying column.
listingUpdatedDate int Listing-projection timestamp surfaced only under the `listMode` group. Driven by `TripCache` and other listing-shape refreshers separately from `updatedDate` so a listing rebuild doesn't trigger detail-page invalidation.