Trip Segments
Taxi & Private Hire › Products › Trip › Trip Segments
Generally available
A TripSegment is one leg of a Trip — the work between two stops with its own pickup, dropoff, capacity requirements, lifecycle status, pricing snapshot and tracking code. Single-load trips have exactly one segment; multi-load trips have several. Segments are the unit of dispatch, the unit of meter recording, and the unit of charge.
Example request
GET /client/{clientId}/trip/{tripId}/tripsegment
See the API reference for the full request and response schema.
Endpoints
| Method | Path | |
|---|---|---|
GET | /client/{clientId}/trip/{tripId}/tripsegment · primary | |
PUT | /client/{clientId}/tripsegment/{tripSegmentId}/clientcapability/{clientCapabilityId} | |
POST | /client/{clientId}/trip/{tripId}/tripsegment/{tripSegmentId}/copy | |
DELETE | /client/{clientId}/trip/{tripId}/tripsegment/{tripSegmentId} | |
GET | /client/{clientId}/trip/{tripId}/tripsegment/{tripSegmentId} | |
POST | /client/{clientId}/tripsegment/{tripSegmentId}/dropoff-verify | |
POST | /client/{clientId}/trip/{tripId}/tripsegment/{tripSegmentId}/promote | |
POST | /client/{clientId}/trip/{tripId}/tripsegment/{tripSegmentId} | |
DELETE | /client/{clientId}/tripsegment/{tripSegmentId}/clientcapability/{clientCapabilityId} |
Full request/response schemas and an interactive explorer will live in the API reference (coming soon).
Use cases
Operator flows that exercise this feature.
config risk: low
Attach a required capability (wheelchair, pet, etc.) to a booking segment.
PUT/client/{clientId}/tripsegment/{tripSegmentId}/clientcapability/{clientCapabilityId}
action risk: low
Copy a segment within a trip (e.g. a repeat stop).
POST/client/{clientId}/trip/{tripId}/tripsegment/{tripSegmentId}/copy
action risk: low
Delete a segment (booking leg) from a trip.
DELETE/client/{clientId}/trip/{tripId}/tripsegment/{tripSegmentId}
action risk: low
Confirm a safeguarded drop-off (PIN / guardian handoff) for a school passenger.
POST/client/{clientId}/tripsegment/{tripSegmentId}/dropoff-verify
action risk: low
Elevate a segment position / order within a trip.
POST/client/{clientId}/trip/{tripId}/tripsegment/{tripSegmentId}/promote
Related
Fields
| Field | Type | Description |
|---|---|---|
trip | Trip | Parent Trip — the booking container that owns this segment. Required for active segments; nullable only during the brief construction phase. |
customer | Customer | The customer who booked + is billed for this segment. When `scp` is also set, the customer is the booker/guardian and `scp` is the actual traveller. Editing the customer is price-sensitive — re-quotes the segment. |
scp | SpecialCategoryPassenger | Optional Special Category Passenger — child / vulnerable adult / named third party who travels under the booker's account. When set, the customer remains the billable + notification target but the SCP is the actual passenger; SCP-driver preferences + safety-envelope checks engage. |
dropoffPin | string | |
dropoffPinAttempts | integer | |
dropoffVerifiedAt | integer | |
dropoffVerifiedBy | bigint | |
trackingCode | string | Short shareable tracking code (3-char tenant prefix + 10-char unique part) for the public /p/track/{code} endpoint. Generated at segment creation; case-insensitive, exclude-confusing-chars alphabet. |
arriveDate | integer | Unix timestamp the driver arrived at the pickup. Distinct from passengerOnBoardDate (waiting time = POB - arrive). |
requestedPickupDate | integer | Customer-requested pickup time (unix). Required. Drives release-time calculation for pre-booked trips and pricing time-of-day modifiers. Price-sensitive — editing re-quotes. |
expectedPickupDate | integer | Platform-projected pickup time accounting for current dispatch state. Differs from requestedPickupDate when delays push the realistic arrival forward. |
predictedLateAtAssignment | integer | Predicted lateness in seconds at the moment of dispatch assignment. Set once by detectLateAtAssignment; always positive (guard skips below-threshold cases). Drives the late-trip alert + customer notification flow. |
customerSharedEta | integer | The system's at-booking ETA commitment to the customer (unix). Pre-booked = `requestedPickupDate`; ASAP = bookingTime + ReleaseTimeDecision.offsetSeconds. Set once and frozen — never updated by later projections. The baseline for system-fault lateness attribution; see analytics.outcome-score. |
assignedEta | integer | Driver-specific the routing service-projected pickup ETA at the moment of assignment (unix). Frozen except on reassignment, where it's overwritten with the new driver's projection. The boundary between systemFault (customerSharedEta → assignedEta) and driverFault (assignedEta → arriveDate); see analytics.outcome-score. |
firstAssignedEta | integer | The very first assignedEta value for this segment (unix). Write-once — preserved through any reassignment so the reshuffle delta (`currentAssignedEta − firstAssignedEta`) attributes correctly to system fault; see analytics.outcome-score. |
firstPickupProximityDate | integer | Unix timestamp the serving driver first came within the learning threshold (guard.pickup_proximity.threshold_metres) of this segment's pickup. Passive GPS-derived stamp, distinct from the gameable `arriveDate`; stamped once per assignment, reset on reassignment. Feeds approach-time percentiles + release-timing learning. |
firstPickupProximityDistanceMetres | integer | Haversine distance in metres from the driver's GPS to the pickup at the moment firstPickupProximityDate was stamped. Always within the proximity threshold. Diagnostic for the stamp. |
firstPickupProximityGpsAgeSeconds | integer | Age in seconds of the GPS reading used for the proximity stamp (now − session timestamp). Stale readings are rejected by guard.arrival.max_gps_age_seconds; this records the accepted age for confidence weighting. |
firstPickupProximitySource | string | How firstPickupProximityDate was produced — LIVE_STAMP (from a live location tick) or GPS_BACKFILL (reconstructed from GPS history). See App\Domain\Trip\Enum\PickupProximitySource. |
firstPickupProximityTransporterId | bigint | The transporter id the proximity stamp belongs to. On reassignment the stamp resets (the serving driver is what matters); the stamping service overwrites the stamp when the assigned transporter differs from this id. |
arrivalDriftMetres | smallint | Haversine distance in metres between the driver's ARRIVED-press location and the booked pickup coordinates. Set once at the first PICKUP stop's ENROUTE→ARRIVED transition. Not used for per-trip scoring (driver-vs-address-data attribution is ambiguous per-trip); aggregated across drivers per `(pickupLat, pickupLng)` to surface address-quality candidates. See analytics.outcome-score. |
arrivalRejectionCount | smallint | Count of arrival-guard-rejected attempts on this segment before a successful ARRIVED transition. Incremented atomically on each rejection. Not used for per-trip scoring; aggregated per-driver to surface repeat-offender patterns. See analytics.outcome-score. |
earlySeconds | integer | For pre-booked segments only: seconds the driver arrived BEFORE the customer-requested pickup time (floored at zero). Driver-bad signal — fixes the "Outside SMS too early" pressure. Null/0 for ASAP segments. Feeds `driverTransporterScore` in Phase 2a. See analytics.outcome-score. |
actualTripDistanceMetres | integer | Actual driven distance in metres for the with-passenger leg (POB → dropoff). v1 uses the routing service single-call at finalisation, which captures the traffic-adjusted optimal route at finish-time (not the driver's literal driven route — that needs breadcrumb-sum). Recorded for aggregate deviation analytics; not used for per-trip scoring. See analytics.outcome-score. |
actualTripDurationSeconds | integer | Actual with-passenger duration in seconds — wall-clock from passengerOnBoardDate to segment finishedDate. Includes any dropoff handover time. Not used for per-trip scoring. See analytics.outcome-score. |
actualTripPrice | integer | Final priced amount in cents for the segment. Metered fares only; fixed-fare segments leave null (price equals quote by design). Not used for per-trip scoring. See analytics.outcome-score. |
timeDriftSeconds | integer | Time drift in seconds: `actualTripDurationSeconds − quoted.routeDuration`. Can be negative (came in faster than quoted) or positive (took longer). Recorded for aggregate deviation analytics; not used for per-trip scoring. See analytics.outcome-score. |
distanceDriftMetres | integer | Distance drift in metres: `actualTripDistanceMetres − quoted.routeDistance`. Can be negative or positive. v1 inherits the routing service-vs-the routing service noise (traffic-adjusted optimal at finish vs at quote); breadcrumb-based actual-vs-optimal is a planned refinement. See analytics.outcome-score. |
priceDriftCents | integer | Price drift in cents: `actualTripPrice − quote.price`. Metered fares only; null for fixed-fare. Can be negative or positive. Not used for per-trip scoring. See analytics.outcome-score. |
scheduleAnchor | ScheduleAnchor · PICKUP | DROPOFF | WINDOW | Which timing column is the authoritative anchor for this segment: PICKUP (requestedPickupDate), DROPOFF (requestedDropoffDate), or WINDOW (pickupWindowStart/End). Hospital appointments anchor on DROPOFF; schools anchor on WINDOW; everything else anchors on PICKUP. |
requestedDropoffDate | integer | |
pickupWindowStart | integer | |
pickupWindowEnd | integer | |
dropoffWindowStart | integer | |
dropoffWindowEnd | integer | |
passengerOnBoardDate | integer | Unix timestamp the passenger was onboard (POB) — set when the driver finishes the pickup stop. Drives waiting-time pricing (the meter switches from "approach" to "fare" at POB) and serves as the fixed-fare lock-in moment. |
dispatchedDate | integer | Unix timestamp the segment entered the ALLOCATION lifecycle (became dispatch-eligible). For ASAP trips that's shortly after creation; for pre-booked trips it's the release moment. |
finishedDate | integer | Unix timestamp the segment reached a terminal state (FINISHED or CANCELLED). Anchors the archive cursor — segments older than the cursor get archived in batch. |
status | TripSegmentLifecycleEnum · NONE | SCHEDULED | INPROGRESS | FINISHED | CANCELLED | Lifecycle state: NONE → SCHEDULED → ALLOCATION → ASSIGNED → ENROUTE → ONBOARD → FINISHED, or → CANCELLED / NOSHOW from various points. Drives every downstream visibility / dispatch / pricing decision. |
passengerType | PassengerType · HUMAN | ANIMAL | PACKAGE | Passenger classification (STANDARD / VIP / SCHOOL_RUN / MEDICAL / etc.). Drives tariff-decision-tree matching and capability-requirement defaults. Price-sensitive — editing re-quotes. |
tripSegmentStops | Collection | Ordered stops the driver visits — pickup, dropoff, and any intermediate waypoints. Mutations are price-sensitive (route changes → re-quote). |
quote | Quote | BILLING-role Quote for this segment — the priced snapshot at booking time. Shadow quotes (fixed-fare alternates) live on the Trip-level quote instead. |
price | Price | |
resolvedSharePercentage | integer | |
operatorSharePercentage | integer | |
discountOverridePercentage | integer | |
account | Account | |
accountDepartment | AccountDepartment | |
accountEmployee | AccountEmployee | |
paymentMethod | TripPaymentMethod · CASH | CARD | INVOICE | VOUCHER | |
customerPaymentMethod | CustomerPaymentMethod | |
pricingMode | PricingMode · FIXED | METERED | |
requiredClientCapabilities | Collection | |
originatingFleet | Fleet | |
vehicleType | VehicleType | |
passengerCapacityRequirement | smallint | |
tripSegmentChargeableItems | Collection | |
pickupZone | Zone | |
accountFieldData | JsonStorage | |
brand | Brand | |
mergeGroup | string | |
planCostMetres | integer | |
planDetourPercentage | smallint | |
sharingRatio | smallint | |
dispatchScore | smallint | System-attributable lateness score (0–100, floor 10). `computeScore(systemFaultSeconds)` where `systemFaultSeconds = max(0, assignedEta − customerSharedEta) + max(0, assignedEta − firstAssignedEta)`. Renamed from `outcomeScore` in Phase 2a — now represents the system-fault slice only, not the blended customer view. `null` until segment reaches FINISHED. See analytics.outcome-score. |
driverTransporterScore | smallint | Driver-attributable conduct score (0–100, floor 10). Pre-booked: `(computeScore(driverFaultSeconds) × 0.7) + (computeScore(earlySeconds) × 0.3)`. ASAP: `computeScore(driverFaultSeconds)` only — earliness is neutral for ASAP. Aggregated per driver_id → Driver page KPI; per transporter_id → Transporter page KPI. See analytics.outcome-score. |
blendedScore | smallint | Blended customer-experience score (0–100, floor 10). `round((dispatchScore + driverTransporterScore) / 2)` — simple 50/50 mean. Successor to the legacy outcome score for fleet/zone headline KPIs. `null` if either component is null. See analytics.outcome-score. |
pricingStartDate | integer | |
pricingEndDate | integer | |
excludeFromMultiload | bool | |
allowedMergeStrategy | MergeStrategy · NONE | ACCOUNT | ACCOUNT_DEPARTMENT | ALL | |
region | Region | |
fixedStopSequence | bool | |
note | string | |
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. |