How to use Karhoo APIs


Detailed information and examples of how to use Karhoo's APIs can be found in the Karhoo API Explorer.


Karhoo's API design follows RESTful standards which will be familiar to developers accustomed to working with modern web APIs.

The Karhoo APIs follow consistent patterns for usage:


HTTP Headers

Valid API requests provide the following two HTTP header fields with each request:

  • Content-Type
  • Authorization

Content-Type: application/json

The API consumes and produces JSON. This means that you should always set the Content-Type header to application/json to ensure that your requests are properly accepted and processed by the API.

Authorization; bearer {token}

Karhoo API calls are authenticated using an Access Token. This token is a string of random characters generated by the server in response to a Request. Refer to Auth for details on working with these tokens.


Karhoo APIs responses are in JSON format and include

HTTP Status Codes

All RESTful API calls return a valid HTTP status code.

Status CodeDescription
200OK. Everything worked as expected.
201Created. We will return a 201 after a successful POST where a resource was created.
302Retry request on given redirect URI.
400Malformed request.
401Unauthorised. The request requires user authentication (not logged in).
403Forbidden. Used for unauthorised requests where your permissions restrict the request.
User not allowed. User is banned and is not permitted to request a ride.
404Resource not found.
406Unacceptable content type. Client sent an accepts header for a content type which does not exist on the server. Body includes a list of acceptable content types, such as “Unacceptable content type. Request resource as: application/json.
409A conflict needs to be resolved before the request can be made.
422Invalid request. The request body is parse-able however with invalid content or there are issues with a rider’s user account.
429Too Many Requests. Exceeded the rate limit for requests.
500Internal Server Error. Something has gone wrong on the website’s server, but the server could not be more specific on what the exact problem is.
503The service is not available.


Rich errors are returned for API-specific errors. See Interpreting errors for more details

Rate limiting

The APIs enforce rate limits. These limits are specific to each endpoint. If usage exceeds the rate limit for a given endpoint, requests will receive a response with an HTTP Status Code of 429. You will continue to receive these responses until your rate of requests has dropped below the acceptable threshold for that endpoint.



All timezones in the API are expressed in UTC and it is the responsibility of the client to localize.


The API does not explicitly define a currency. However, each fleet may quote in a different currency for a geological area. So, when requesting a quote you should allow for a quote list with multiple currency units . These will be provided in standard ISO 4217 format (e.g. USD, GBP or JPY). For instance you may get quotes from fleets from different countries who quote for the same trip with their own currencies (especially if the journey crosses a national border).


Some API requests may return bulk results (like getting a listing of an organisation’s bookings). These bulk fetches will be sorted in reverse chronological order with the most recent data first. They share two common parameters which allow you to cursor through the data:

pagination_offset Starting row for the results
pagination_row_countNumber or records to return in one go. Large requests have a greater chance of timing out. The default and maximum value is set to 1000


Calling a paginated API endpoint with these parameters would return records 201-400.

  pagination_offset: 200,
  pagination_row_count: 200


If you are paginating through results, making consecutive calls, you should make allowances for duplicate rows. This is because the records are returned with the most recent data at the top. If new records are added to the database whilst you requesting the data set, because of the time lapse between two requests, you will see overlapping result sets. So, in the example above which returns records 201-400, if a new record was added (it becomes row 0), and resending the same API request means the returned data would be shunted down by 1 row. Row 201 would be row 202, row 201 would be row 202, and so on. The previous row 400 would no longer be returned in that request but you will see it on the subsequent request for a pagination_offset of 400.