Client integrations API
Book cars from your own systems — your BPM, Zoho Creator, FastCollab, an ERP — and get trip updates pushed to your URLs. Your vendor creates the integration; your admin manages keys, field mappings and subscriptions in Integrations. Machine-readable spec: OpenAPI 3.1.
Keys and limits
Send your integration key in x-api-key (or Authorization: Bearer). A key only reaches your organisation and only the bookings created through its integration. cik_live_… keys book for real; cik_test_… keys are the sandbox. Each key is rate limited (default 120 requests a minute; a 429 carries Retry-After).
curl -H "x-api-key: cik_live_…" https://<your-host>/api/integrations/v1/catalog
The catalog lists duty types and vehicle classes in your words (your vendor maps your terms, e.g. "AIRPORT DROP" → their airport transfer), your cost centres, entities and the statuses you will see.
Create a booking
POST /api/integrations/v1/bookings
{
"client_ref": "TKT-10042", // your ticket no. — sending it again never books twice
"passenger": { "employee_code": "T1003" }, // or { "name", "phone", "email" }
"duty_type": "AIRPORT DROP", // your term (see /catalog)
"vehicle_class": "Sedan",
"pickup_at": "2026-10-10T06:30:00+05:30", // ISO, unix seconds or "10-Oct-2026 06:30:00" (IST)
"pickup": { "address": "Koramangala, Bengaluru", "lat": 12.935, "lng": 77.624 },
"drop": { "address": "Kempegowda International Airport T1" },
"flight": { "number": "6E2341" },
"cost_centre": "CC-104", "purpose": "Client visit",
"approval": { "status": "approved", "approved_by": "R. Iyer", "reference": "APR-881" }
}
→ 201 { "id": "bk_…", "number": "BK-2610-0042", "client_ref": "TKT-10042", "status": "confirmed",
"duties": [{ "number": "BK-2610-0042-1", "status": "confirmed", "driver": null, "vehicle": null }] }
→ 200 { …same booking…, "duplicate": true } (the same client_ref again)Your travel policy, booking restrictions and the vendor's cut-off apply as for any booking. approval is honoured only when your vendor set the integration to trust your approvals; otherwise the booking waits in awaiting_approval.
Errors
422 { "error": { "code": "VALIDATION_FAILED", "message": "Some fields are missing or invalid",
"fields": [ { "field": "duty_type", "issue": "unknown duty type \"Helicopter\"; use one of: AIRPORT DROP, Full Day, …" },
{ "field": "passenger", "issue": "no active employee with code T9999" } ] },
"request_id": "req_…" }| HTTP | code | meaning |
|---|---|---|
| 401 | INVALID_KEY / UNAUTHENTICATED | missing, wrong or revoked key |
| 403 | INTEGRATION_PAUSED | your vendor paused the integration |
| 404 | NOT_FOUND | not a booking of this integration |
| 409 | NOT_EDITABLE / NOT_CANCELLABLE / IN_PROGRESS | the car is already out, or the same client_ref is being processed |
| 422 | VALIDATION_FAILED / POLICY_BLOCKED / CUTOFF / RESTRICTED | fix the request |
| 429 | RATE_LIMITED | slow down (Retry-After) |
Read, change, cancel
GET /api/integrations/v1/bookings/TKT-10042 (your client_ref or our id)
PATCH /api/integrations/v1/bookings/TKT-10042 { "pickup_at": "…", "drop": { "address": "…" }, "vehicle_class": "SUV" }
POST /api/integrations/v1/bookings/TKT-10042/cancel { "reason": "Meeting moved" }Changes are accepted until the car leaves for the pickup; cancelling twice answers duplicate: true.
Sandbox
With a cik_test_ key every call is validated against the real catalogue, employees and cost centres, but nothing is booked. Move a test booking through the trip and receive the events at your sandbox subscriptions:
POST /api/integrations/v1/sandbox/bookings/TKT-1/simulate { "event": "duty.driver_assigned" }
events: booking.confirmed, booking.rejected, duty.driver_assigned, duty.driver_changed, duty.dispatched, duty.arrived, duty.started, duty.completed, duty.no_show, duty.cancelled, duty.delayed, invoice.issuedStatus updates (subscriptions)
Your admin adds your https URLs and picks the events. Each update is POSTed as JSON, signed, and retried with back-off for about a day if your endpoint does not answer 2xx; your own API header (for example x-api-key) can be stored with the subscription and is sent on every call.
| event | when |
|---|---|
booking.created | Booking received |
booking.confirmed | Booking confirmed |
booking.approved | Approved |
booking.rejected | Rejected / denied |
booking.cancelled | Booking cancelled |
duty.driver_assigned | Driver & vehicle assigned |
duty.driver_changed | Driver / vehicle changed |
duty.dispatched | Driver on the way |
duty.arrived | Driver arrived |
duty.started | Trip started |
duty.completed | Trip completed |
duty.no_show | Passenger no-show |
duty.cancelled | Trip cancelled |
duty.delayed | Running late |
booking.flight_update | Flight change |
invoice.issued | Invoice issued |
| status | label | FastCollab trip_status |
|---|---|---|
awaiting_approval | Awaiting approval | requesting |
rejected | Not approved | denied_by_vendor |
confirmed | Confirmed — vehicle allotment pending | scheduled |
assigned | Vehicle & driver assigned | driver_assigned |
changed | Vehicle/driver changed | driver_reassigned |
on_the_way | On the way | driver_dispatched |
arrived | Arrived | driver_arrived |
on_trip | On trip | active |
completed | Completed | completed |
cancelled | Cancelled | cancelled |
no_show | No-show | no_show |
POST <your URL>
X-Charters-Event: duty.driver_assigned
X-Charters-Event-Id: evt_… (deduplicate on this)
X-Charters-Signature: t=1791349200,v1=<hex HMAC-SHA256(secret, "1791349200." + raw body)>
{ "id": "evt_…", "event": "duty.driver_assigned", "created_at": "…",
"data": { "client_ref": "TKT-10042", "status": "assigned", "status_label": "Vehicle & driver assigned",
"booking": { "id": "bk_…", "number": "BK-2610-0042", … },
"duty": { "number": "BK-2610-0042-1", "driver_name": "Ramesh P", "vehicle_number": "KA01AB1234", "vehicle_model": "Toyota Etios" } } }Payload templates: Charters (above), FastCollab (trip_id, reference_id, trip_status, trip_pickup_time, driver, vehicle), Zoho Creator ({ data: { Ticket_No, Booking_Status, Driver_Name, Vehicle_Number, Pickup_Date_Time, … } }) or a custom JSON template with placeholders such as {{client_ref}}, {{status_label}}, {{duty.vehicle_number}}. Passenger names, phones and emails are never sent; the driver's name and car appear once they are assigned to your trip.
Zoho Creator and your own BPM
Point your workflow's webhook at /api/integrations/inbound/<integration id> with the key header. Zoho integrations start with a preset for Creator field names (Ticket_No, Employee_ID, Trip_Type, Vehicle_Type, Pickup_Date_Time, Pickup_Location, Drop_Location, Cost_Center, Approval_Status, Action); any other payload is mapped field by field with JSON paths, value maps and date formats — try it in the test console before going live. Action = New / Modify / Cancel selects create, update or cancel. Optional signing (recommended):
X-Charters-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256(signing secret, "<t>.<raw body>")> // refused when older than 5 minutes
// Zoho Deluge
t = zoho.currenttime.toLong() / 1000;
sig = zoho.encryption.hmacsha256(secret, t + "." + body.toString(), "base64"); // hex or base64 both accepted
invokeurl [ url: url type: POST parameters: body.toString()
headers: {"x-api-key": key, "X-Charters-Signature": "t=" + t + ",v1=" + sig, "content-type": "application/json"} ];FastCollab (keep your existing calls)
The FastCollab endpoints, payloads, the x-api-key header and the { status, response: { data }, success } envelope are unchanged. Change the base URL from https://fleet-api.tylt.co.in/partners/fastcollab to https://<your-host>/partners/fastcollab and use the new key. Organisation, duty-type, vehicle-type and customer ids from your earlier system keep working after the migration.
| before | here | note |
|---|---|---|
| GET /parent-organisations, /helpdesks, /duty-types, /vehicle-types, /cities | same | only your organisation and its entities |
| POST /bookings | same payload | reference_id is now an idempotency key — a retry returns the same trip_id with duplicate: true |
| PUT /bookings/:trip_id | same whitelist | trip_notes are appended (the reference is kept) |
| POST /bookings/:trip_id/cancel | same | only trips created through your key |
| — | GET /bookings/:trip_id | new: poll a trip's status, driver and vehicle |
| no callbacks | subscriptions (FastCollab template) | status updates pushed to your URL |