openapi: 3.0.0
info:
description: 'Welcome to the Cabify Logistics API. This API allows you to create and manage parcel deliveries, track their status in real time, configure proof of delivery options, and receive live updates via webhooks. All requests must be authenticated using a Bearer token.
'
version: 1.0.0
title: Cabify Logistics delivery Journeys API
contact:
email: p.delivery@cabify.com
servers:
- url: https://logistics.api.cabify.com
description: Production
- url: https://logistics.api.cabify-sandbox.com
description: Sandbox
tags:
- description: This section covers the mobility solution for all companies looking to transport their employees in a simple, safe and comfortable way. We offer different types of vehicles with private drivers and provide everything you need to enjoy your journey, such as a good driver and a top-of-the-range car.
name: Journeys
paths:
/api/v4/journey/{id}/state:
post:
callbacks: {}
description: 'Cancels an active journey. Journeys can only be cancelled free of charge before a driver has been assigned. After assignment, cancellation fees may apply if the courtesy period has elapsed (this varies by operating zone).
Returns `409 Conflict` if the journey has already been completed, terminated, or is in a state that does not allow cancellation.
'
operationId: cancelJourney
parameters:
- description: Id of the journey
example: f0397896-19aa-11ed-b6fe-7aaea8067492
in: path
name: id
required: true
schema:
type: string
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/JourneyResponse'
description: Success
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/BadRequest'
description: Bad request
'401':
content:
application/json:
schema:
$ref: '#/components/schemas/UnauthorizedRequest'
description: Unauthorized
'409':
content:
application/json:
schema:
$ref: '#/components/schemas/Conflict'
description: Journey cannot be cancelled (already terminated or in a non-cancellable state)
'500':
content:
application/text:
schema:
$ref: '#/components/schemas/InternalServerError'
description: Internal server error
summary: Cancel Journey
tags:
- Journeys
get:
callbacks: {}
description: 'Returns the real-time operational state of an active journey: assigned driver, vehicle, and
the route waypoints collected so far.
Use this endpoint for live tracking while a journey is in progress. It provides the data
needed to show the driver''s position on a map and display vehicle/driver details to the rider.
**Typical use cases:**
- Show the assigned driver''s name, phone number, and avatar.
- Display the vehicle plate, model, and color so the rider can identify it.
- Plot the driver''s route on a map using the waypoints array.
**Availability:**
- Returns data once a driver is assigned (`hired` state onward).
- Returns empty waypoints for journeys in `terminated` state (route data is archived).
- Returns `404` if the journey does not exist or does not belong to the authenticated client.
> ⚠️ Stop polling once you receive an end state
>
> End states are terminal, the journey will never transition to another state. Once you receive an
> end state (via this endpoint or a webhook), stop polling. Continued polling returns `200` with
> `state: terminated` indefinitely but carries no new information.
>
> For reliable state delivery without polling, configure
> [Journey State Updates webhooks](https://developers.cabify.com/docs/journey-updates-webhook).
> 📘 Looking for booking details or pricing?
>
> To retrieve stops, cost breakdown, or lifecycle status, use the
> [Get Journey Details](#operation/getJourney) endpoint instead.
>
> To receive state changes in real time without polling, configure
> [Webhooks](https://developers.cabify.com/docs/journey-updates-webhook).
'
operationId: getJourneyState
parameters:
- description: UUID of the journey
example: f0397896-19aa-11ed-b6fe-7aaea8067492
in: path
name: id
required: true
schema:
type: string
- description: ID of the user who requested the journey
example: 6f80363aa84fa61a58dc5720
in: query
name: requester_id
required: true
schema:
type: string
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/JourneyState'
description: Success
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/BadRequest'
description: Bad request
'401':
content:
application/json:
schema:
$ref: '#/components/schemas/UnauthorizedRequest'
description: Unauthorized
'404':
content:
application/json:
schema:
$ref: '#/components/schemas/NotFound'
description: Not found
'500':
content:
application/text:
schema:
$ref: '#/components/schemas/InternalServerError'
description: Internal server error
summary: Get Journey State
tags:
- Journeys
/api/v4/journey:
post:
callbacks: {}
description: 'Creates a new journey request for a ride.
> ❗️ Prerequisites
>
> Before creating a journey, you **must** call the `/estimates` endpoint and use the returned
> `product.id` as `product_id` in this request. This guarantees that the product is available
> at the pickup location and provides accurate pricing shown to drivers.
>
> The estimate should be created within **5 minutes** of the journey request.
## Journey States
After creation, the journey progresses through these states:
1. `hire` - Searching for available drivers
2. `hired` - Driver assigned and en route
3. `arrived` - Driver at pickup location
4. `pick up` - Passenger in vehicle
5. `drop off` - Journey completed
6. `terminated` - Receipt generated (after ~2 hours)
For a detailed explanation of journey states and their transitions, see [Journey States](https://developers.cabify.com/docs/journey-states).
> 📘 Booking a Journey (Reservation)
>
> Creating a reservation is similar to creating an ASAP journey, except for the `start_at` field,
> which should contain a future date-time value in the format "YYYY-MM-DD HH:MM:SS", expressed
> in the local time of the pickup location.
>
> **Use the same `start_at` value you provided to the `/estimates` endpoint** to ensure consistent
> product availability and pricing between the estimate and the journey creation.
>
> **Important constraints:**
> - Reservations must be created at least **30 minutes** before the start time
> - Reservations can be scheduled up to **60 days** in advance
> ⚠️ Sandbox Testing
>
> In the sandbox environment, pickup locations must be within central Madrid (approximately 40.4361°, -3.7014°).
> See [Sandbox Environment](https://developers.cabify.com/docs/sandbox-environment) for details.
'
operationId: createJourney
parameters: []
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/JourneyRequest'
description: Journey request
required: false
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/JourneyResponse'
description: Success
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/BadRequest'
description: Bad request
'401':
content:
application/json:
schema:
$ref: '#/components/schemas/UnauthorizedRequest'
description: Unauthorized
'404':
content:
application/json:
schema:
$ref: '#/components/schemas/NotFound'
description: Not found
'500':
content:
application/text:
schema:
$ref: '#/components/schemas/InternalServerError'
description: Internal server error
summary: Create a journey
tags:
- Journeys
/api/v4/journey/{journey_id}:
get:
callbacks: {}
description: 'Returns the booking-level details of a journey: stops, pricing, timestamps, and lifecycle status.
Use this endpoint to check whether a journey is finished, retrieve its cost breakdown, or read
the stops that were requested. The response is stable once the journey is created and only
changes when the journey ends (populating `end_state`, `end_at`, and `totals`).
**Typical use cases:**
- Display a journey''s origin/destination and scheduled time.
- Check if a journey has finished and why (`end_state`).
- Retrieve the price summary after a journey is terminated.
> 📘 Looking for real-time tracking data?
>
> To get the driver''s current location, vehicle details, or route waypoints while a journey is
> in progress, use the [Get Journey State](#operation/getJourneyState) endpoint instead.
'
operationId: getJourney
parameters:
- description: UUID of the journey
example: f0397896-19aa-11ed-b6fe-7aaea8067492
in: path
name: journey_id
required: true
schema:
type: string
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/Journey'
description: Success
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/BadRequest'
description: Bad request
'401':
content:
application/json:
schema:
$ref: '#/components/schemas/UnauthorizedRequest'
description: Unauthorized
'500':
content:
application/text:
schema:
$ref: '#/components/schemas/InternalServerError'
description: Internal server error
summary: Get Journey details
tags:
- Journeys
/api/v4/journey/{id}/keep_searching:
post:
callbacks: {}
description: "If there are no drivers available after having created a journey (meaning you receive a\n 'not found' state via webhooks or via the GET journey/state endpoints), with this\n endpoint, you can continue searching for drivers for the same exact journey without the\n need of a new estimation.\n\nThe journey will enter again in the 'hire' state for another 5 minutes (this time cannot be changed).\n\n"
operationId: keepSearching
parameters:
- description: Id of the journey
in: path
name: id
required: true
schema:
format: uuid
type: string
responses:
'204':
description: Empty Response
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/BadRequest'
description: Bad request
'401':
content:
application/json:
schema:
$ref: '#/components/schemas/UnauthorizedRequest'
description: Unauthorized
'404':
content:
application/json:
schema:
$ref: '#/components/schemas/NotFound'
description: Not found
'500':
content:
application/text:
schema:
$ref: '#/components/schemas/InternalServerError'
description: Internal server error
summary: Keep searching drivers for a journey
tags:
- Journeys
components:
schemas:
MeetingPoint:
description: A specific meeting point within a hub location (e.g. a terminal at an airport). Obtained from the hub data returned in the estimates response.
example:
id: mp_001
loc:
- 40.4722
- -3.5608
name: Terminal 1 - Puerta de llegadas
properties:
id:
description: Unique identifier of the meeting point.
type: string
loc:
description: Coordinates of the meeting point as [latitude, longitude].
items:
format: float
type: number
maxItems: 2
minItems: 2
type: array
name:
description: Display name of the meeting point.
type: string
required:
- id
- loc
- name
title: MeetingPoint
type: object
BadRequest:
description: Indicates that the server cannot or will not process the request due to something that is perceived to be a client error (for example, malformed request syntax, invalid request message framing, or deceptive request routing).
example:
error: Bad Request error message
properties:
message:
type: string
title: BadRequest
type: object
InternalServerError:
description: indicates that an internal server error occurred
example:
error: Something went wrong
properties:
error:
type: string
title: InternalServerError
type: object
UnauthorizedRequest:
description: The token used is invalid either because it is expired or because it is incorrect.
example:
error: Unauthorized
properties:
error:
type: string
title: UnauthorizedRequest
type: object
Journey:
description: Booking-level details of a journey including stops, pricing, timestamps, and lifecycle status.
example:
created_at: '2022-08-04T19:28:18.375Z'
current_state: terminated
end_at: '2022-02-17T09:30:34.831Z'
end_state: drop off
finished: true
id: 96fc6f24-142b-11ed-bba7-56a6f40ef0bf
label_slug: apiV4
product_id: 75dd566797369d1f0927102e5356ce59
public_url: /j/5ceg7v77qm8x28c9
region_id: madrid
start_at: '2022-02-17T09:30:34.831Z'
start_type: asap
stops:
- addr: Calle de la cruz
city: Madrid
contact:
mobile_cc: '34'
mobile_num: '123456789'
name: Jhon Doe
stop_action: pickup
country: ES
id: '123'
loc:
- 40.4169335
- -3.7061872
name: Work
num: '1428'
totals:
discount:
amount: 0
currency: EUR
price:
amount: 100
currency: EUR
price_total:
amount: 100
currency: EUR
user_id: 0dfc7c0bbbd300e6f9212827106e8911
properties:
created_at:
description: ISO 8601 datetime when the journey was created.
format: date-time
type: string
current_state:
description: Current lifecycle state of the journey (e.g. hire, hired, arrived, pick up, terminated).
type: string
end_at:
description: ISO 8601 datetime when the journey ended. Null while still active.
nullable: true
type: string
end_state:
default: not found
description: The reason the journey ended. Null while the journey is still active.
enum:
- drop off
- driver cancel
- not found
- no show
- rider cancel
nullable: true
type: string
finished:
description: Whether the journey has reached an end state (drop off, cancel, no show, or not found).
type: boolean
id:
description: UUID of the journey.
type: string
label_slug:
description: Slug of the label (cost center, project code) associated with this journey for expense reporting.
type: string
product_id:
description: ID of the vehicle category/product used for this journey, as returned by the estimates endpoint.
type: string
public_url:
description: Shareable URL that allows anyone to track the journey in real time without authentication.
nullable: true
type: string
region_id:
description: Identifier of the city/region where the journey takes place.
type: string
start_at:
description: ISO 8601 datetime when the journey started (driver began moving toward pickup). Null for journeys still in `hire` state.
nullable: true
type: string
start_type:
description: Whether the journey was requested immediately or scheduled for a future time.
enum:
- asap
- reserved
nullable: false
type: string
stops:
items:
$ref: '#/components/schemas/StopResponse'
type: array
totals:
$ref: '#/components/schemas/Totals'
user_id:
description: ID of the user who requested the journey.
type: string
required:
- id
title: Journey
type: object
Price:
description: Price in the currency smallest unit.
example:
amount: 100
currency: EUR
nullable: false
properties:
amount:
description: Amount in cents. *For CLP this field is in currency units
nullable: false
type: integer
currency:
description: Currency code in ISO_4217 format
nullable: false
type: string
title: Price
type: object
Driver:
description: Driver's information.
example:
avatar_url: https://secure.gravatar.com/avatar/675ee8c314586d36a7b33c6c773565e9?r=pg&s=80&=blank
id: e8417e8cd14c11ec869eb2e3f32e3b38
name: John
phone_number: '34611111111'
properties:
avatar_url:
description: Driver's picture.
type: string
id:
description: Id of the driver
nullable: false
type: string
name:
description: Driver's name.
type: string
phone_number:
description: Driver's phone number.
type: string
title: Driver
type: object
Mobile:
description: Input Mobile Number. Required when the rider is external. Journey's SMS state updates will arrive to this mobile.
example:
mobile_cc: '34'
mobile_num: '123456789'
properties:
mobile_cc:
description: Mobile Country Code. Required if mobileNum is provided.
nullable: false
pattern: ^\+?\d+$
type: string
mobile_num:
description: Rider's phone number.
nullable: false
pattern: ^[0-9]+$
type: string
required:
- mobile_cc
- mobile_num
title: Mobile
type: object
JourneyRequest:
additionalProperties: false
description: 'Input object needed to create a new journey.
> ⚠️ Always estimate before creating a journey
>
> You **must** call `/estimates` before creating a journey. The estimation response provides:
> - `product.id` — the product to book
> - Pricing and availability information valid at the time of the estimate
>
> Pass `product.id` as `product_id` in this request. For **reserved** journeys, also pass the same
> `start_at` you used in the estimation request to guarantee consistent pricing and availability.
>
> We recommend estimating no more than **5 minutes** before creating the journey.
'
example:
label_slug: null
message: Test message for driver
product_id: 75dd566797369d1f0927102e5356ce59
reason: Test reason for driver
requester_id: 081a70a52cfc11ecbb03a25a490feee4
rider:
email: riderEmail@example.com
locale: ES
mobile:
mobile_cc: '34'
mobile_num: '123456789'
name: Jhon Doe
start_at: '2022-07-01 10:00:00'
stops:
- addr: Madrid Barajas T1
city: Madrid
contact:
mobile_cc: '34'
mobile_num: '123456789'
name: Jhon Doe
stop_action: pickup
country: ES
loc:
- 40.4722
- -3.5608
location_id: location-4
meeting_point:
id: mp-loc4-1
loc:
- 40.4722
- -3.5608
name: Terminal 1
name: Work
num: '1428'
- addr: Calle de la cruz
city: Madrid
country: ES
loc:
- 40.4169335
- -3.7061872
properties:
label_slug:
description: If your company has the labels feature enabled (used to categorize expenses, receipts) than a valid label can be provided and it will be associated to a journey for later financial reporting purposes. Custom string which does not allow an empty string value '' Note that it can have a null value.
nullable: true
type: string
message:
description: A message that be associated to a journey that driver can see after they accept the ride. It's usually used to give any extra information that might help the driver in the pickup or to give any information that might help improving the journey experience.
nullable: true
type: string
preferred_driver_id:
description: Id of the preferred driver for this journey (UUID without hyphens). Only available for clients that have their own driver fleet.
nullable: true
type: string
product_id:
description: The product/vehicle category to book. **Must** come from a recent `/estimates` response (`product.id`). Products are dynamic and vary by location and time — never hardcode IDs. Always estimate first to discover available products.
nullable: false
type: string
reason:
description: Free text explaining the motive of the journey. It is available later in all expenditure reports together with the label (if used). Note that this has to be a valid string if the company decides to have this field as mandatory.
nullable: true
type: string
requester_id:
description: It represents the person who creates the ride and is also the passenger of the ride. Nevertheless if the rider object is provided then the passenger (rider) is a different person (check rider attribute for more info). The value of requesterIdshould correspond to a user.id of an registered user in the account.
nullable: false
pattern: ^[a-f0-9]{32}$
type: string
rider:
$ref: '#/components/schemas/Rider'
start_at:
description: "Defines when the journey should start. Format: `YYYY-MM-DD HH:MM:SS` (local time of the pickup location).\n\n- **ASAP rides**: Leave as `null` (or omit the field).\n- **Reservations**: Set to a future time. **Use the same `start_at` value you provided in the `/estimates` request** to ensure consistent product availability and pricing.\n - Minimum: 30 minutes from now\n - Maximum: 60 days in advance\n"
nullable: true
pattern: '[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]) (2[0-3]|[01][0-9]):[0-5][0-9]:[0-5][0-9]'
type: string
stops:
items:
$ref: '#/components/schemas/StopRequest'
maxItems: 15
minItems: 2
type: array
required:
- product_id
- requester_id
- rider
- stops
title: JourneyRequest
type: object
Conflict:
description: The request conflicts with the current state of the resource. For journey cancellation, this means the journey has already been cancelled, terminated, or is in a non-cancellable state.
example:
error: journey has already been terminated
properties:
error:
type: string
title: Conflict
type: object
JourneyResponse:
example:
id: 0397896-19aa-11ed-b6fe-7aaea8067492
properties:
id:
description: journey_id of the current operation.
type: string
title: JourneyResponse
type: object
PreassignedDriver:
description: 'Driver preassigned to the journey (for example on a reservation) before the journey is actually assigned. It does not include the phone number, and it may change or disappear before the journey starts. `driver` always takes precedence: once a driver is assigned, that `driver` is authoritative and this field is only informative about who had been preassigned.'
example:
avatar_url: https://secure.gravatar.com/avatar/1a79a4d60de6718e8e5b326e338ae533?r=pg&s=80&=blank
id: a1b2c3d4e5f611ec869eb2e3f32e3b38
name: Diana
nullable: true
properties:
avatar_url:
description: Preassigned driver's picture.
type: string
id:
description: Id of the preassigned driver
nullable: false
type: string
name:
description: Preassigned driver's first name.
type: string
title: PreassignedDriver
type: object
Rider:
description: Input data defining the rider of a journey.
example:
email: riderEmail@example.com
locale: ES
mobile:
mobile_cc: '34'
mobile_num: '123456789'
name: John Doe
properties:
email:
description: Rider's email.
format: email
nullable: true
type: string
id:
description: Id of the Rider that will travel, if the Rider is a User of your company this will be the User's id (can be same as requester_id to request a journey for yourself). Leave empty when the Rider is external to your company.
pattern: ^[a-f0-9]{32}$
type: string
locale:
description: Rider's Locale. Syntax consists of language two-letter tag which then will be suffixed with Client's country.
nullable: true
type: string
mobile:
$ref: '#/components/schemas/Mobile'
name:
description: Rider's name. Required when the rider is external.
type: string
title: Rider
type: object
StopResponse:
description: 'Stop of a journey. A journey needs to have at least 2 stops: the first one is considered the pickup point the last one the destination.'
example:
addr: Calle de la cruz
city: Madrid
contact:
mobile_cc: '34'
mobile_num: '123456789'
name: Jhon Doe
stop_action: pickup
country: ES
id: '123'
loc:
- 40.4169335
- -3.7061872
name: Work
num: '1428'
postal_code: '28002'
properties:
addr:
description: If an address was provided when creating the journey this field will have its value.
type: string
city:
description: City name where the address is located, e.g. Madrid.
type: string
contact:
$ref: '#/components/schemas/Contact'
contacts:
default: []
description: List of contacts for the stop, in case of multiple contacts.
items:
$ref: '#/components/schemas/Contact'
type: array
country:
description: Country name where the address is located, e.g. España.
type: string
hit_at:
description: DateTime when the driver arrived at the indicated point.
format: date-time
type: string
id:
description: Id of the stop.
type: string
instr:
description: Set of instructions for the Driver.
type: string
loc:
default: []
description: The actual coordinates of the address. Required floats per location latitude and longitude.
items:
format: float
type: number
type: array
meeting_point:
$ref: '#/components/schemas/MeetingPoint'
name:
description: A short name for previously stored addresses. These can be viewed in places.
type: string
num:
description: Street number.
type: string
postal_code:
description: Postal code of the address.
type: string
required:
- loc
title: StopResponse
type: object
Row:
description: Point and state through which the driver passed during the journey.
example:
loc:
- 40.4169335
- -3.7061872
state_name: hired
properties:
loc:
default: []
description: The actual coordinates of the address. Required floats per location latitude and longitude.
items:
format: float
type: number
type: array
state_name:
description: Status of the journey at the time the driver passed through that point.
nullable: false
type: string
title: Row
type: object
NotFound:
description: The server did not find a current representation for the target resource
example:
error: user with provided ID does not exist
properties:
message:
type: string
title: NotFound
type: object
Totals:
description: Price breakdown for the journey. Only populated after the journey reaches `terminated` state.
example:
discount:
amount: 0
currency: EUR
price:
amount: 100
currency: EUR
price_total:
amount: 100
currency: EUR
nullable: true
properties:
discount:
$ref: '#/components/schemas/Price'
price:
$ref: '#/components/schemas/Price'
price_total:
$ref: '#/components/schemas/Price'
title: Totals
type: object
StopRequest:
description: 'Stop of a journey. A journey needs to have at least 2 stops: the first one is considered the pickup point the last one the destination.'
example:
addr: Calle de la cruz
city: Madrid
contact:
mobile_cc: '34'
mobile_num: '123456789'
name: Jhon Doe
stop_action: pickup
country: ES
loc:
- 40.4169335
- -3.7061872
location_id: location-4
meeting_point:
id: mp-loc4-1
loc:
- 40.4169335
- -3.7061872
name: Terminal 1
name: Work
num: '1428'
postal_code: '28002'
properties:
addr:
description: If an address was provided when creating the journey this field will have its value.
type: string
city:
description: City name where the address is located, e.g. Madrid.
type: string
contact:
$ref: '#/components/schemas/Contact'
contacts:
description: List of contacts for the stop. Only one of `contact` or `contacts` should be provided.
items:
$
# --- truncated at 32 KB (37 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/cabify/refs/heads/main/openapi/cabify-journeys-api-openapi.yml