Ride creation flow
This guide is written from the perspective of an external integrator. On this page, you means a non-ioki user integrating with ioki Platform.
This page describes a typical ride creation flow through the Platform API when the provider uses external_payment.
Use this flow when your integration creates the ride, waits until it becomes bookable, creates the booking, and then reports the external payment result back to ioki Platform.
This guide supplements the API Docs. This page focuses on the end-to-end flow, while the API Docs remain the reference for request and response details.
This guide uses the current Platform API version v20210101.
Required headers
Send these headers with the requests in this guide.
| Header | Value |
|---|---|
Authorization | Bearer <PLATFORM_TOKEN> |
X-Api-Version | 20210101 |
X-Client-Identifier | <CLIENT_IDENTIFIER> |
X-Client-Secret | <CLIENT_SECRET> |
X-Client-Version | <CLIENT_VERSION> |
Accept | application/json |
Content-Type | application/json |
Use the base URL that corresponds to your environment. This will be either
- https://demo.io.ki/ for the demo environment, which can be used for test purposes, or
- https://app.io.ki/ for the production environment.
Recommended flow
- Read provider and product configuration.
- Read product-specific passenger and ride options.
- Optionally run a ride inquiry.
- Create the ride.
- Poll the ride until it is bookable.
- Create the booking with the latest
ride_version. - Report the external payment result.
sequenceDiagram
autonumber
participant Integrator
participant PlatformAPI as Platform API
participant Payment as External payment system
Integrator->>PlatformAPI: Read provider and product configuration
PlatformAPI-->>Integrator: Payment and product settings
Integrator->>PlatformAPI: Read passenger types, passenger options, and ride options
PlatformAPI-->>Integrator: Valid payload inputs
opt Optional estimation step
Integrator->>PlatformAPI: Run ride inquiry
PlatformAPI-->>Integrator: Availability and estimates
end
Integrator->>PlatformAPI: Create ride
PlatformAPI-->>Integrator: Ride created
loop Until ride is bookable
Integrator->>PlatformAPI: Read ride
PlatformAPI-->>Integrator: Current state and version
end
Integrator->>PlatformAPI: Create booking with latest ride_version
PlatformAPI-->>Integrator: Booking created
Integrator->>Payment: Run external payment flow
Payment-->>Integrator: Payment result
Integrator->>PlatformAPI: Report payment result
PlatformAPI-->>Integrator: Updated ride payment state
1. Read provider and product configuration
Before you create a ride, check the provider and product configuration that affects booking and payment.
Confirm these points in particular:
| Resource | Field | Why it matters |
|---|---|---|
| Provider | ride_payment_method_types | The flow on this page assumes the provider supports external_payment. |
| Product | payment_method_allowed_on_booking | The booking step sends a payment method during booking. |
curl -i -X GET \ -H "X-Api-Version: 20210101" \ -H "X-Client-Identifier: $CLIENT_IDENTIFIER" \ -H "X-Client-Secret: $CLIENT_SECRET" \ -H "X-Client-Version: $CLIENT_VERSION" \ -H "Authorization: Bearer $PLATFORM_TOKEN" \ "$BASE_URL/api/platform/providers/$PROVIDER_ID"
curl -i -X GET \ -H "X-Api-Version: 20210101" \ -H "X-Client-Identifier: $CLIENT_IDENTIFIER" \ -H "X-Client-Secret: $CLIENT_SECRET" \ -H "X-Client-Version: $CLIENT_VERSION" \ -H "Authorization: Bearer $PLATFORM_TOKEN" \ "$BASE_URL/api/platform/products/$PRODUCT_ID"
2. Read product-specific input options
Read the product-specific endpoints before building the ride payload.
Use them to determine:
- valid passenger types
- valid passenger options
- valid ride options
Relevant endpoints:
GET /api/platform/products/{product_id}/passenger_typesGET /api/platform/products/{product_id}/passenger_optionsGET /api/platform/products/{product_id}/ride_options
curl -i -X GET \ -H "X-Api-Version: 20210101" \ -H "X-Client-Identifier: $CLIENT_IDENTIFIER" \ -H "X-Client-Secret: $CLIENT_SECRET" \ -H "X-Client-Version: $CLIENT_VERSION" \ -H "Authorization: Bearer $PLATFORM_TOKEN" \ "$BASE_URL/api/platform/products/$PRODUCT_ID/passenger_types"
3. Optionally run a ride inquiry
Use ride inquiry as an advisory step before you create the ride. It is useful when you want to check availability or show estimated pickup, drop-off, or fare information.
The request can include origin, destination, and passengers. If you send a time value, only one of origin.time or destination.time is allowed.
Relevant endpoint:
POST /api/platform/products/{product_id}/ride_inquiry
Errors and troubleshooting
Ride inquiry is designed to return guidance, not only a binary success or failure. When ioki Platform cannot provide a usable result, inspect:
availabilityassistancesestimations
Common inquiry problems in the current implementation include:
| Issue | What it means | What to check |
|---|---|---|
service_not_available | Our cars are taking a break. We will be back on the road for you on <date> at <time>. We will be happy to see you then. If no follow-up availability is known, the text changes to “… and unfortunately we don’t know when we will be available again”. The product is currently unavailable, or no follow-up availability is known. | Check the requested time and the product’s active service windows. If next_availability is returned, retry with a later time. |
origin_outside_of_service_area | The specified origin is outside of our service area. The requested origin is not covered at the relevant time. | Check the origin coordinates or station selection, and verify the product’s served and unserved areas. |
destination_outside_of_service_area | The specified destination is outside of our service area. The requested destination is not covered at the relevant time. | Check the destination coordinates or station selection, and verify the product’s served and unserved areas. |
ride_not_prebookable | It is not possible to book this ride in advance. The request uses a future time, but no matching task list allows prebooking. | Check whether the product and current task lists support prebooked rides, or retry without a future time. |
lead_time_filtered_all_solutions | All possible vehicles were excluded by lead-time requirements. Please adjust your request. For details, refer to this product’s terms of service. Potential matches were filtered out by lead-time rules. | Check the requested departure or arrival time against the product’s lead-time settings. |
invalid_passenger | We are unable to provide a ride for the requested passengers. The requested passenger mix is not valid for the product or available vehicles. | Check which passenger types are set as bookable in the product. |
invalid_ride_option | We are unable to provide a ride for the requested ride options. One or more ride options cannot be fulfilled. | Check the allowed ride options for the product and verify the submitted values. |
resources_exceed_capabilities | We are currently unable to provide a vehicle with the requested resources. No available vehicle can satisfy the requested resource consumption. | Reduce the requested passenger or option requirements, or check whether the fleet supports them. |
travel_combination_not_served | We don’t serve the selected combination of origin and destination. The selected origin and destination combination is blocked. | Check whether the product uses blacklisted travel combinations or zone-based restrictions for this route. |
ride_filtered | The text depends on the configured ride filter error message. A ride filter rejected the request. | Check product-specific ride filters and their validation rules. |
A ride inquiry can return assistances even when the request itself is structurally valid. Treat these messages as the main troubleshooting signal before moving on to ride creation.
curl -i -X POST \ -H "X-Api-Version: 20210101" \ -H "X-Client-Identifier: $CLIENT_IDENTIFIER" \ -H "X-Client-Secret: $CLIENT_SECRET" \ -H "X-Client-Version: $CLIENT_VERSION" \ -H "Authorization: Bearer $PLATFORM_TOKEN" \ -H "Content-Type: application/json" \ "$BASE_URL/api/platform/products/$PRODUCT_ID/ride_inquiry" \ --data '{ "data": { "origin": { "lat": 50.104692, "lng": 8.644062, "location_name": "Galluswarte", "street_name": "Mainzer Landstrasse", "street_number": "299", "postal_code": "60326", "city": "Frankfurt am Main", "county": "Hessen", "country": "Deutschland" }, "destination": { "lat": 50.113695, "lng": 8.678996, "location_name": "Hauptwache", "street_name": "Zeil", "street_number": "8", "postal_code": "60313", "city": "Frankfurt am Main", "county": "Hessen", "country": "Deutschland" }, "passengers": [ { "type": "adult" } ] } }'
4. Create the ride
Create the ride only after you have built a payload that matches the product configuration.
Relevant endpoint:
POST /api/platform/products/{product_id}/rides
In practice, a ride request usually includes:
user_idorigindestinationpassengers
Depending on the product, it can also include:
optionspassenger_note_to_driverorigin.timefor prebookingdestination.timefor destination-time-based matching
Keep these rules in mind:
- The
product_idin the path defines the product context. - Only one of
origin.timeordestination.timeis allowed. - Ride creation and booking are separate steps.
curl -i -X POST \ -H "X-Api-Version: 20210101" \ -H "X-Client-Identifier: $CLIENT_IDENTIFIER" \ -H "X-Client-Secret: $CLIENT_SECRET" \ -H "X-Client-Version: $CLIENT_VERSION" \ -H "Authorization: Bearer $PLATFORM_TOKEN" \ -H "Content-Type: application/json" \ "$BASE_URL/api/platform/products/$PRODUCT_ID/rides" \ --data '{ "data": { "user_id": "usr_12345678-1234-1234-1234-123456789012", "passengers": [ { "type": "adult", "options": [ { "slug": "public_transport_ticket", "value": false } ] } ], "options": [ { "slug": "storage_spaces", "value": 2 } ], "origin": { "lat": 50.104692, "lng": 8.644062, "location_name": "Galluswarte", "street_name": "Mainzer Landstrasse", "street_number": "299", "postal_code": "60326", "city": "Frankfurt am Main", "county": "Hessen", "country": "Deutschland" }, "destination": { "lat": 50.113695, "lng": 8.678996, "location_name": "Hauptwache", "street_name": "Zeil", "street_number": "8", "postal_code": "60313", "city": "Frankfurt am Main", "county": "Hessen", "country": "Deutschland" } } }'
5. Poll the ride until it is bookable
After you create the ride, poll the ride resource and track at least these fields:
idversionstate
Use the current version as ride_version when you create the booking.
Relevant endpoint:
GET /api/platform/products/{product_id}/rides/{ride_id}
curl -i -X GET \ -H "X-Api-Version: 20210101" \ -H "X-Client-Identifier: $CLIENT_IDENTIFIER" \ -H "X-Client-Secret: $CLIENT_SECRET" \ -H "X-Client-Version: $CLIENT_VERSION" \ -H "Authorization: Bearer $PLATFORM_TOKEN" \ "$BASE_URL/api/platform/products/$PRODUCT_ID/rides/$RIDE_ID"
6. Create the booking with external payment
Create the booking only after the ride is bookable. The booking schema describes this step as creating a booking for a ready ride, and ioki Platform rejects booking attempts for rides that are not bookable.
Relevant endpoint:
POST /api/platform/products/{product_id}/rides/{ride_id}/booking
For this flow, send:
- the latest
ride_version payment_method.payment_method_type = external_payment
If the ride changes before booking, ioki Platform can reject the request with a version conflict. Use the latest ride response instead of a cached version.
curl -i -X POST \ -H "X-Api-Version: 20210101" \ -H "X-Client-Identifier: $CLIENT_IDENTIFIER" \ -H "X-Client-Secret: $CLIENT_SECRET" \ -H "X-Client-Version: $CLIENT_VERSION" \ -H "Authorization: Bearer $PLATFORM_TOKEN" \ -H "Content-Type: application/json" \ "$BASE_URL/api/platform/products/$PRODUCT_ID/rides/$RIDE_ID/booking" \ --data '{ "data": { "ride_version": 3, "payment_method": { "payment_method_type": "external_payment" } } }'
7. Report the external payment result
When the ride uses external payment, your integration is responsible for reporting the final payment result back to ioki Platform.
Relevant endpoint:
PATCH /api/platform/products/{product_id}/rides/{ride_id}/payment_state
Allowed payment_state values are:
payment_pendingpayment_succeededpayment_failedno_payment
curl -i -X PATCH \ -H "X-Api-Version: 20210101" \ -H "X-Client-Identifier: $CLIENT_IDENTIFIER" \ -H "X-Client-Secret: $CLIENT_SECRET" \ -H "X-Client-Version: $CLIENT_VERSION" \ -H "Authorization: Bearer $PLATFORM_TOKEN" \ -H "Content-Type: application/json" \ "$BASE_URL/api/platform/products/$PRODUCT_ID/rides/$RIDE_ID/payment_state" \ --data '{ "data": { "payment_state": "payment_succeeded" } }'