Pricing & Estimates
import \{ Callout } from 'nextra/components'
Pre-Order Information & Estimates
Before creating an order, you must use the aggregated preorder endpoint to gather all essential pre-order information. This single endpoint provides everything you need to present booking options to your customers and make informed decisions.
Get Aggregated Pre-Order Information
The aggregated preorder endpoint is your one-stop solution for retrieving comprehensive pre-order data, including:
- Service Availability - Which services are currently available for your route
- Service Capabilities - Passenger and luggage capacity for each service tier
- Estimated Prices - Real-time pricing with currency formatting
- Expected Arrival Time - ETA ranges for driver pickup
This endpoint provides all the information needed to present complete booking options to your users.
Endpoint
GET https://api.gett.com/v1/private/preorder/aggregated
Headers
Content-Type: application/json
Authorization: Bearer {your_token}
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
partner_id | string | Yes | Your partner ID provided by Gett |
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
stops | array | Yes | Array of stop objects defining the route |
stops[].type | string | Yes | Type of stop: origin, destination, or on_going |
stops[].location | object | Yes | Location coordinates |
stops[].location.lat | float | Yes | Latitude coordinate |
stops[].location.lng | float | Yes | Longitude coordinate |
scheduled_at | string | No | Pickup time in ISO8601 format (e.g., 2025-09-28T13:35:00Z) |
category | string | Yes | Service category: transportation or delivery |
locale | string | Yes | Language code (e.g., en, es, fr) |
payment_type | string | Yes | Payment method: cash (only option for partners) |
Example Request
curl --location 'https://api.gett.com/v1/private/preorder/aggregated?partner_id=1f4c281e-b3eb-4676-beb7-b3a61caba0e6' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {token}' \
--data '{
"stops": [
{
"type": "origin",
"location": {
"lat": 51.473401,
"lng": -0.0221145
}
},
{
"type": "destination",
"location": {
"lat": 51.4712475,
"lng": 0.0357987
}
}
],
"category": "transportation",
"locale": "en",
"payment_type": "cash"
}'Example Response
{
"routes": [
{
"uuid": "c41116f6-697c-4799-80e6-af0953a61b00",
"provider": "google",
"polyline": "mldyHdgCa@PK?_@Mw@iAG?U[Da@HUN_@Xs@p@yBf@eBj@iCXiBRwCJmBDk@@i@?aBA_ACaAB{@H_ANSh@eBb@qAPw@Fm@F{@?yAIaCWeFe@uHEoBFeCLcBPmCAM@_@D_@D{@VgDd@wGN}@^{FPmCDkBCwBMmE_Cmb@k@mKIqAG_@YmAO[IUASBUFMHi@J_AC]u@mMe@iIKoBEKCGSoCGw@@m@@OIcAa@_IWcFIoAK}AKYK_AKkAg@eFi@cGO{@EGKCWUKWIi@?a@Fg@LY@k@@q@SgBWmDYqEI{EAsDHmBTEtB]jAORFJNP^DNbBoAdBiAtBwAnA{@jBiAz@_@`Ac@EYm@qE]gDEq@O_E",
"scheduled_at": "2025-10-06T10:34:43Z",
"distance": 4624,
"duration": 703,
"duration_unit": "s",
"distance_unit": "m",
"selected_route": true,
"label": ["manual"]
}
],
"product_with_prices": [
{
"product": {
"product_id": "74352801-2d3d-4235-966e-11e07b0e076a",
"name": "Guest Booking",
"icon": "https://static.gett.com/services/media/media_files/28207/uk_black-cab__1.png",
"description": "Iconic, spacious black cabs with 5 or 6 seats that can cut through traffic using the bus lanes to get you to your destination faster",
"eta_sec": 206,
"eta_description": "Under 4 min",
"booking_settings": {
"on_demand": {
"allowed": true
},
"pre_book": {
"allowed": true,
"pre_book_in_advance_min": 30,
"edit_enabled": true,
"edit_before_scheduled_at_min": 30,
"destination_mandatory": false
},
"stops": {
"mandatory_origin": true,
"mandatory_destination": false,
"ongoing_stops": {
"allowed": true,
"max_ongoing_stops": 3
}
},
"multi_riders": {
"allowed": true,
"max_tracked_riders": 5
},
"max_available_seats": 5,
"note_to_driver": {
"allowed": true,
"mandatory": false
}
}
},
"price": {
"pricing_options": [
{
"estimation_id": "6f1caae3-d3fa-4b18-992f-ae0a374acfab",
"price_concept": "meter_range",
"calculated_as": "meter",
"include_vat": true,
"currency": "£",
"currency_iso": "GBP",
"tech_fee": {
"applicable": false,
"value": 0
},
"additional_fee": [
{
"name": "driving",
"value": "18.6",
"min": 17,
"max": 20
}
],
"properties": [
{
"name": "meter_total",
"min": 17,
"max": 20,
"is_range": true,
"amount": "18.6",
"percentage": null
}
]
}
]
},
"eta_to_destination": "0001-01-01T00:00:00Z"
}
]
}Understanding the Pre-Order Response
The aggregated response provides four critical pieces of information through two main sections:
Routes Section
Contains route and journey information:
- Route Details: Distance (in meters), duration (in seconds), and route polyline
- Scheduling: Confirmation of scheduled pickup time
- Provider: Route calculation provider (e.g., Google)
Product with Prices Section
Contains available services and their details:
1. Service Availability
Each product includes booking settings that indicate availability:
- On Demand: Whether immediate booking is
allowed - Pre-book: Whether advance booking is
allowedwith minimum advance time - Stops Configuration: Maximum ongoing stops and destination requirements
2. Service Capabilities
Detailed service capabilities in booking_settings:
- max_available_seats: Maximum passenger capacity
- max_ongoing_stops: Maximum intermediate stops allowed
- max_tracked_riders: Maximum riders that can be tracked
- note_to_driver: Whether driver notes are supported
3. Estimated Prices
Pricing information in the price.pricing_options array:
- estimation_id: Unique quote identifier used as
quote_idwhen creating orders - price_concept: Pricing model -
meter,meter_range, orfixed_pricemeter: Final price calculated by taxi meter (estimate may be 0 or minimal)meter_range: Final price calculated by meter, with estimated range provided (min/max values)fixed_price: Price is committed when you create the order using thisestimation_idasquote_id
- calculated_as: Method used to calculate the price (e.g., "meter", "distance")
- currency & currency_iso: Currency symbol and ISO code
- include_vat: Whether VAT is included in pricing
- tech_fee: Technology fee details and applicability
- additional_fee: Additional fees with min/max ranges (for meter_range pricing)
- properties: Pricing breakdown with amounts and ranges
is_range: Indicates if the price includes min/max estimatesmin&max: Price range boundaries (for meter_range)amount: Estimated or fixed price amount
Price Commitment: When
price_conceptisfixed_price, providing theestimation_idasquote_idin your order creation request commits the displayed price. Formeterormeter_rangepricing, thequote_idis still required but the final price will be determined by the taxi meter.
4. Expected Arrival Time (ETA)
Driver pickup time estimates:
- eta_sec: ETA in seconds from booking
- eta_description: Human-readable ETA description
- eta_to_destination: Estimated arrival time at destination
Service Details
Additional service information:
- product_id: Unique identifier for booking
- name & description: Service display information
- icon: Service icon URL for UI display
Always call the aggregated endpoint before creating orders. Prices, availability, and ETAs can change rapidly. Never attempt to create an order without first getting current pre-order information.
Pricing Types
The aggregated response includes pricing information with different pricing models:
Meter Pricing
When price_concept is "meter" or "meter_range", the price shown is an estimate only:
Simple Meter Pricing:
{
"estimation_id": "4f3cc8ba-b24e-42d9-aef8-3ce528f603fd",
"price_concept": "meter",
"calculated_as": "meter",
"properties": [
{
"name": "meter_total",
"amount": "0",
"is_range": false
}
]
}Meter Range Pricing (with estimated range):
{
"estimation_id": "6f1caae3-d3fa-4b18-992f-ae0a374acfab",
"price_concept": "meter_range",
"calculated_as": "meter",
"additional_fee": [
{
"name": "driving",
"value": "18.6",
"min": 17,
"max": 20
}
],
"properties": [
{
"name": "meter_total",
"min": 17,
"max": 20,
"is_range": true,
"amount": "18.6"
}
]
}- The
estimation_idmust be provided asquote_idwhen creating the order - The final price will be calculated by the taxi meter during the ride
- For
meter_range, the displayed range (min/max) and estimated amount are for reference only - The actual fare may differ from the estimate
Fixed Price
When price_concept is "fixed_price", the price is committed when you create the order:
{
"estimation_id": "1a22584a-9685-4153-a629-271ebc34dcda",
"price_concept": "fixed_price",
"calculated_as": "distance",
"properties": [
{
"name": "fixed_total",
"amount": "25.50",
"is_range": false
}
]
}- Providing the
estimation_idasquote_idlocks in the displayed price - The customer pays exactly the amount shown, regardless of route changes
- Price is guaranteed at order creation time
Fixed Price Advantage: When
fixed_priceis available, using thequote_idguarantees the exact fare to your customer, providing price certainty and transparency.
Integration Workflow
Required Pre-Order Flow
- User selects route → Call aggregated endpoint
- Display options → Show available services with prices, capacity, and ETAs
- User selects service → Validate selection is still available
- Create order → Use the
product_idandestimation_id(asquote_id) from the aggregated response
When creating an order, you must provide the
quote_idparameter with the value ofestimation_idfrom the selected product'spricing_optionsarray. For services withprice_concept: "fixed_price", this commits the displayed price. Forprice_concept: "meter", the quote is required but the final price is determined by the taxi meter.
Best Practices
Real-time Updates
- Cache pre-order data for maximum 2-3 minutes to balance performance and accuracy
- Refresh automatically when route parameters change
- Show users when information was last updated
- Re-fetch before order creation if data is older than 2 minutes
Handling Availability Changes
async function getPreOrderInfo(routeData) {
try {
const response = await fetch(`/v1/private/preorder/aggregated?partner_id=${partnerId}`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(routeData)
});
if (!response.ok) {
if (response.status === 400) {
throw new Error('Invalid route parameters');
} else if (response.status === 404) {
throw new Error('No services available for this route');
}
throw new Error('Failed to get pre-order information');
}
const data = await response.json();
// Check if we have products and routes
if (!data.product_with_prices || data.product_with_prices.length === 0) {
throw new Error('No services currently available for this route');
}
if (!data.routes || data.routes.length === 0) {
throw new Error('No valid routes found for this request');
}
// Filter products that allow the requested booking type
const availableServices = data.product_with_prices.filter(item => {
const isOnDemand = !routeData.scheduled_at;
if (isOnDemand) {
return item.product.booking_settings.on_demand?.allowed;
} else {
return item.product.booking_settings.pre_book?.allowed;
}
});
if (availableServices.length === 0) {
throw new Error('No services available for the requested booking type');
}
return {
...data,
product_with_prices: availableServices
};
} catch (error) {
console.error('Pre-order info request failed:', error);
throw error;
}
}Multiple Stops
For routes with multiple stops, include all stops in the request:
{
"stops": [
{
"type": "origin",
"location": {
"lat": 51.4988787,
"lng": -0.020746
}
},
{
"type": "on_going",
"location": {
"lat": 51.4899,
"lng": -0.0125
}
},
{
"type": "destination",
"location": {
"lat": 51.4712475,
"lng": 0.0357987
}
}
]
}Essential Integration Requirements
Mandatory Pre-Order Check: You must call the aggregated endpoint for every booking attempt. This is not optional - it's required to ensure service availability and get current pricing.
Critical Implementation Points
-
Always Check All Four Aspects:
- ✅ Service availability before showing options
- ✅ Service capabilities to match user needs
- ✅ Current prices for accurate billing
- ✅ Real ETAs for user expectations
-
User Experience Guidelines:
- Display all available service tiers with clear capability differences
- Show real-time ETAs to set proper expectations
- Update information when route changes
- Handle "no services available" scenarios gracefully
-
Technical Requirements:
- Never cache pre-order data longer than 2-3 minutes
- Always validate selected service is still available before order creation
- Implement proper loading states during API calls
- Handle network failures and API errors appropriately
Complete Integration Example
class BookingFlow {
async displayBookingOptions(origin, destination, scheduledTime) {
// Step 1: Get all pre-order information
const preOrderData = await this.getPreOrderInfo({
stops: [
{ type: 'origin', location: origin },
{ type: 'destination', location: destination }
],
scheduled_at: scheduledTime,
category: 'transportation',
locale: 'en',
payment_type: 'cash'
});
// Step 2: Extract route information
const selectedRoute = preOrderData.routes.find(route => route.selected_route) || preOrderData.routes[0];
const routeInfo = {
distance: `${(selectedRoute.distance / 1000).toFixed(1)} km`,
duration: `${Math.round(selectedRoute.duration / 60)} min`,
scheduledAt: selectedRoute.scheduled_at
};
// Step 3: Process available services
const availableServices = preOrderData.product_with_prices.filter(item => {
const isOnDemand = !scheduledTime;
return isOnDemand
? item.product.booking_settings.on_demand?.allowed
: item.product.booking_settings.pre_book?.allowed;
});
if (availableServices.length === 0) {
throw new Error('No services available for this route at this time');
}
// Step 4: Format service options for display
return availableServices.map(item => {
const product = item.product;
const pricing = item.price.pricing_options[0];
return {
id: product.product_id,
name: product.name,
description: product.description,
icon: product.icon,
eta: product.eta_description,
etaSeconds: product.eta_sec,
maxSeats: product.booking_settings.max_available_seats,
maxOngoingStops: product.booking_settings.stops.ongoing_stops.max_ongoing_stops,
pricing: {
concept: pricing.price_concept,
currency: pricing.currency,
currencyIso: pricing.currency_iso,
includeVat: pricing.include_vat,
techFee: pricing.tech_fee
},
bookingSettings: product.booking_settings,
routeInfo: routeInfo
};
});
}
async createOrderWithValidation(selectedProductId, orderData) {
// Re-validate availability before creating order
const currentInfo = await this.getPreOrderInfo(orderData.routeInfo);
const selectedProduct = currentInfo.product_with_prices.find(
item => item.product.product_id === selectedProductId
);
if (!selectedProduct) {
throw new Error('Selected service is no longer available');
}
// Check booking type availability
const isOnDemand = !orderData.scheduled_at;
const bookingAllowed = isOnDemand
? selectedProduct.product.booking_settings.on_demand?.allowed
: selectedProduct.product.booking_settings.pre_book?.allowed;
if (!bookingAllowed) {
throw new Error('Selected booking type is not available for this service');
}
// Get the estimation_id (quote_id) from the pricing options
const quoteId = selectedProduct.price.pricing_options[0].estimation_id;
// Proceed with order creation using validated product_id and quote_id
return await this.createOrder({
...orderData,
product_id: selectedProductId,
quote_id: quoteId
});
}
formatPriceDisplay(pricingOptions) {
const pricing = pricingOptions[0];
// Handle meter pricing - show as estimate
if (pricing.price_concept === 'meter') {
return {
displayText: `${pricing.currency} Metered pricing`,
type: 'meter',
isEstimate: true,
note: 'Final price determined by taxi meter'
};
}
// Handle meter range pricing - show range estimate
if (pricing.price_concept === 'meter_range') {
const mainProperty = pricing.properties.find(p => p.name.includes('total'));
if (mainProperty && mainProperty.is_range) {
return {
displayText: `${pricing.currency}${mainProperty.min}-${mainProperty.max}`,
estimatedAmount: `${pricing.currency}${mainProperty.amount}`,
type: 'meter_range',
isEstimate: true,
note: 'Estimated range - final price determined by taxi meter'
};
}
}
// Handle fixed pricing - show exact amount
if (pricing.price_concept === 'fixed_price') {
const mainProperty = pricing.properties.find(p => p.name.includes('total'));
if (mainProperty && mainProperty.amount !== "0") {
return {
displayText: `${pricing.currency}${mainProperty.amount}`,
type: 'fixed_price',
isEstimate: false,
note: 'Price guaranteed at booking'
};
}
}
// Fallback for other pricing types
return {
displayText: `${pricing.currency} Variable pricing`,
type: 'variable',
isEstimate: true,
note: 'Contact support for pricing details'
};
}
}Updated 12 days ago
