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.

HeaderValue
AuthorizationBearer <PLATFORM_TOKEN>
X-Api-Version20210101
X-Client-Identifier<CLIENT_IDENTIFIER>
X-Client-Secret<CLIENT_SECRET>
X-Client-Version<CLIENT_VERSION>
Acceptapplication/json
Content-Typeapplication/json

Use the base URL that corresponds to your environment. This will be either

  1. Read provider and product configuration.
  2. Read product-specific passenger and ride options.
  3. Optionally run a ride inquiry.
  4. Create the ride.
  5. Poll the ride until it is bookable.
  6. Create the booking with the latest ride_version.
  7. 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:

ResourceFieldWhy it matters
Providerride_payment_method_typesThe flow on this page assumes the provider supports external_payment.
Productpayment_method_allowed_on_bookingThe 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:

Relevant endpoints:

  • GET /api/platform/products/{product_id}/passenger_types
  • GET /api/platform/products/{product_id}/passenger_options
  • GET /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:

  • availability
  • assistances
  • estimations

Common inquiry problems in the current implementation include:

IssueWhat it meansWhat to check
service_not_availableOur 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_areaThe 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_areaThe 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_prebookableIt 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_solutionsAll 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_passengerWe 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_optionWe 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_capabilitiesWe 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_servedWe 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_filteredThe 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_id
  • origin
  • destination
  • passengers

Depending on the product, it can also include:

  • options
  • passenger_note_to_driver
  • origin.time for prebooking
  • destination.time for destination-time-based matching

Keep these rules in mind:

  • The product_id in the path defines the product context.
  • Only one of origin.time or destination.time is 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:

  • id
  • version
  • state

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_pending
  • payment_succeeded
  • payment_failed
  • no_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"
    }
  }'