Pricing API reference
Overview
One HTTPS + JSON API that tells your website or app whether a trip is serviceable and exactly what it costs. Any language that can send an HTTPS request can integrate.
Send coordinates, a vehicle code and a service type. The engine checks the pickup against geofenced service areas, applies outstation route rules, picks the live pricing version and returns an itemised fare with a quote ID. The engine is the source of truth for price — requests that include a fare are rejected.
Base URL https://api.primetaxihub.com/api/v1
Format JSON (UTF-8), request body ≤ 32 KB
Timezone Send pickup_at as ISO-8601 with offset. Night/peak/weekend rules use the pickup's local time.Authentication
Every request except /health needs your API key in the Authorization header (or X-API-Key):
Authorization: Bearer pth_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxKeys are issued per client in the admin console and shown once. Keep them on your server. If a key is ever exposed in browser code or a repository, revoke it and issue a new one. Clients can additionally be restricted to IP addresses and browser origins.
Request signing (optional)
If your client has Require HMAC signature enabled, add two headers. The signature is hex(HMAC-SHA256(api_secret, timestamp + "." + raw_body)); timestamps older than 5 minutes are rejected, which blocks replays.
import crypto from "node:crypto";
const body = JSON.stringify(payload);
const ts = Math.floor(Date.now() / 1000).toString();
const sig = crypto.createHmac("sha256", process.env.PTH_API_SECRET).update(`${ts}.${body}`).digest("hex");
await fetch("https://api.primetaxihub.com/api/v1/fare/quote", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.PTH_API_KEY}`,
"Content-Type": "application/json",
"X-PTH-Timestamp": ts,
"X-PTH-Signature": sig,
},
body, // send exactly the string you signed
});Get a fare quote
POST /fare/quote
| Field | Type | Notes |
|---|---|---|
| pickup | { lat, lng, address? } | Required. The polygon decides serviceability, never the address. |
| drop | { lat, lng } | null | Required except for hourly rentals. |
| vehicle | string | Vehicle code, e.g. sedan (see /vehicles). |
| service_type | string | local, airport, outstation, hourly … |
| trip_type | string | Default one_way. round_trip doubles billable distance. |
| pickup_at | ISO-8601 | Default now. Up to 365 days ahead. |
| return_at | ISO-8601 | Round trips: decides the number of trip days. |
| hours | number | Hourly rentals. |
| waiting_minutes | integer | Expected waiting time. |
| coupon_code | string | Invalid coupons never fail the quote; see warnings. |
{
"pickup": { "lat": 28.6139, "lng": 77.2090, "address": "Connaught Place" },
"drop": { "lat": 28.4595, "lng": 77.0266 },
"vehicle": "sedan",
"service_type": "local",
"trip_type": "one_way",
"pickup_at": "2026-10-10T09:30:00+05:30",
"coupon_code": "WELCOME10"
}Response:
{
"success": true,
"quote_id": "QT-20261003-000001",
"currency": "INR",
"expires_at": "2026-10-03T09:30:00.000Z",
"pickup_at": "2026-10-10T04:00:00.000Z",
"service": { "type": "local", "name": "Local", "trip_type": "one_way" },
"vehicle": { "code": "sedan", "name": "Sedan", "passenger_capacity": 4, "luggage_capacity": 2, "image_url": null },
"location": { "pickup_area": "Delhi NCR", "drop_area": "Delhi NCR", "pickup_allowed": true, "drop_allowed": true,
"pickup_airport": null, "drop_airport": null },
"route": null,
"distance": { "km": 28.4, "billable": 28.4, "unit": "KM", "duration_minutes": 72, "estimated": false },
"pricing": { "plan": "delhi_local_sedan", "version": 2 },
"fare": {
"base_fare": 2500, "included_km": 80, "extra_km": 0, "extra_km_charge": 0,
"time_charge": 0, "waiting_charge": 0, "airport_charge": 0, "night_charge": 0, "surcharge": 0,
"toll": 0, "parking": 0, "state_tax": 0, "driver_allowance": 0, "other_charges": 0,
"adjustments": 0, "discount": 200, "subtotal": 2300,
"tax": 115, "taxes": [{ "name": "GST", "rate": 5, "type": "PERCENTAGE", "amount": 115 }],
"round_off": 0, "total": 2415, "trip_days": 1
},
"warnings": [],
"request_id": "6c1b2f7e-…"
}Quotes expire (default 30 minutes). Store quote_id with the booking and call /quote/{id}/verify before confirming.
All endpoints
POST/fare/quoteCalculate a fare and create a quote. The response is the price — clients never send one.
POST/fare/recalculateRe-price an earlier quote with the current pricing version (e.g. after it expired). Returns a new quote id; the old one becomes superseded.
{ "quote_id": "QT-20261003-000001", "pickup_at": "2026-10-10T11:00:00+05:30" }{ "success": true, "quote_id": "QT-20261003-000042", …, "recalculated_from": "QT-20261003-000001", "previous_total": 2415, "price_changed": false }GET/quote/{quote_id}Retrieve one of your quotes, with status and validity.
POST/quote/{quote_id}/verifyCall just before confirming a booking: checks the quote is still valid and, optionally, that the amount you show matches.
{ "total": 2415 }{ "success": true, "quote_id": "QT-…", "valid": true, "amount_matches": true, "total": 2415, "currency": "INR", "expires_at": "…" }POST/location/validateIs pickup possible at this point? Returns the service area and airport, if any.
{ "point": { "lat": 28.5562, "lng": 77.1 }, "service_type": "airport" }{ "success": true, "inside_service_area": true, "pickup_allowed": true, "service_available": true, "area": { "code": "delhi_ncr", "name": "Delhi NCR", … }, "airport": { "code": "DEL", … } }POST/service-area/checkCheck pickup and drop together for a service — applies the drop policy (local) or route rules (outstation).
{ "pickup": { "lat": 28.61, "lng": 77.21 }, "drop": { "lat": 27.17, "lng": 78.0 }, "service_type": "local" }{ "success": true, "pickup_allowed": true, "drop_allowed": false, "bookable": false, "reason": { "code": "DROP_LOCATION_NOT_ALLOWED", "message": "…" } }POST/route/checkIs an outstation route served? Optionally include road distance.
{ "pickup": { "lat": 28.61, "lng": 77.21 }, "drop": { "lat": 26.91, "lng": 75.79 }, "service_type": "outstation", "trip_type": "one_way", "include_distance": true }{ "success": true, "allowed": true, "route": { "name": "Delhi → Jaipur", … }, "distance": { "km": 268.3, "duration_minutes": 330 } }GET/vehicles?service_area=delhi_ncrVehicle categories you can request (optionally only those available in an area).
GET/service-typesService types (local, airport, outstation, hourly …).
GET/trip-typesTrip types (one_way, round_trip …).
GET/citiesCities served for pickup or as outstation destinations.
GET/service-areas?include=polygonService areas, optionally with their polygons for drawing coverage maps.
GET/healthLiveness and database readiness. No authentication.
Errors
Every error uses the same envelope and an HTTP status that matches the problem:
{
"success": false,
"error": { "code": "OUTSIDE_SERVICE_AREA", "message": "Pickup location is outside our service area." },
"request_id": "…"
}| Code | HTTP | Meaning |
|---|---|---|
| INVALID_API_KEY | 401 | Missing, unknown or revoked key. |
| INVALID_SIGNATURE | 401 | Signing is required for this client and the signature or timestamp is wrong. |
| CLIENT_DISABLED | 403 | The API client was disabled by an administrator. |
| IP_NOT_ALLOWED | 403 | The caller's IP isn't on the client's whitelist. |
| ORIGIN_NOT_ALLOWED | 403 | A browser Origin header isn't in the client's allowed origins. |
| INVALID_REQUEST | 400 | Body failed validation. details.fields lists each problem. |
| INVALID_COORDINATES | 422 | Latitude/longitude out of range, or 0,0. |
| OUTSIDE_SERVICE_AREA | 422 | Pickup isn't inside any pickup-enabled service area. |
| DROP_LOCATION_NOT_ALLOWED | 422 | Drop violates the area's drop policy for local trips. |
| ROUTE_NOT_ALLOWED | 422 | Outstation route not served, blocked, or outside its distance limits. |
| VEHICLE_NOT_AVAILABLE | 422 | Unknown vehicle code, or not offered in the pickup area. |
| SERVICE_TYPE_NOT_AVAILABLE | 422 | Unknown service type, or not offered in the pickup area. |
| TRIP_TYPE_NOT_AVAILABLE | 422 | Unknown trip type code. |
| PRICING_PLAN_NOT_FOUND | 422 | No live pricing matches this trip. |
| NO_ROUTE_FOUND | 422 | No drivable route, or the routing service is down. |
| QUOTE_NOT_FOUND | 404 | No such quote for your client. |
| QUOTE_EXPIRED | 410 | The quote expired or was superseded — recalculate. |
| NOT_FOUND | 404 | Unknown endpoint. |
| METHOD_NOT_ALLOWED | 405 | Wrong HTTP method. |
| PAYLOAD_TOO_LARGE | 413 | Body exceeds 32 KB. |
| RATE_LIMIT_EXCEEDED | 429 | Too many requests. Wait Retry-After seconds. |
| SERVER_ERROR | 500 | Unexpected error. Quote request_id when contacting support. |
Rate limits
Each client has a per-minute limit (default 60). Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. Over the limit you get 429 RATE_LIMIT_EXCEEDED with Retry-After. Ask your account manager to raise the limit.
Code examples
curl -X POST https://api.primetaxihub.com/api/v1/fare/quote \
-H "Authorization: Bearer $PTH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"pickup":{"lat":28.6139,"lng":77.2090},"drop":{"lat":28.4595,"lng":77.0266},
"vehicle":"sedan","service_type":"local","trip_type":"one_way"}'Integration checklist
- Keep the API key and secret on your server; the browser talks to your backend.
- Show the fare from the response exactly — never compute or round it yourself.
- Save
quote_idwith the booking and verify it before confirming payment. - Handle
OUTSIDE_SERVICE_AREA,ROUTE_NOT_ALLOWEDandVEHICLE_NOT_AVAILABLEwith clear messages to your customer. - Log
request_idfrom every response; support uses it to find the exact calculation. - Retry
429and5xxwith backoff. Don't retry4xxvalidation errors unchanged.