General Response Format

All GET endpoints of Kombo follow the same principle. All of them return a list of results and a next cursor. All results follow the same basic structure with the following properties:

  • id: An ID generated by Kombo, also referred to throughout the documentation as “Kombo ID”.
  • remote_id: The ID of the object in the remote system. This can be null for some objects.
  • changed_at: Part of Kombo’s change tracking — this is the timestamp of the last change that was detected by Kombo.
  • remote_deleted_at: Part of Kombo’s change tracking — this is the timestamp where the object was not found anymore in the remote system.

Other properties are model-specific.

A note on Kombo IDs and their uniqueness

We generate the Kombo ID by referencing the remote ID and the integration ID.

This results in the following statements being true:

  • A Kombo ID is unique across all integrations for the same model.
    • This is because we reference the integration ID itself when generating the Kombo ID.
  • A Kombo ID is not unique across different models for the same integration.
    • This will occur for remote systems that follow a sequential ID pattern. For example, both the first employee and department have the ID 1. As the integration ID is the same, so will the Kombo ID.

Pagination

Each request returns either a value on the next field or null. The value will be a cursor which you can use to get the next page of results. Use the cursor query parameter to request the next page. (Please note that you still need to add the relevant filters while paginating.)

In addition, you can use the page_size parameter to specify the number of results per page.

curl --request GET \
  --url 'https://api.kombo.dev/v1/hris/employees?cursor=eyJwYWdlIjoxMiwibm90ZSI6InRoaXMgaXMganVzdCBhbiBleGFtcGxlIGFuZCBub3QgcmVwcmVzZW50YXRpdmUgZm9yIGEgcmVhbCBjdXJzb3IhIn0&page_size=100' \
  --header 'Authorization: Bearer <YOUR_API_KEY>'

Filtering

All models provide the same filters in addition to some model-specific filters. The following filters apply to all models:

  • updated_after: Only return objects where the changed_at value is after the given timestamp. This can be used to sync data incrementally. This filter also includes all expanded relations — so if only they have changed (but none of the primary attributes of the object), this will still count as the object having changed and it will still be returned.
  • include_deleted: By default, all values with a remote_deleted_at value are not returned. If you want to include them, set this to true. This is helpful if you want to remove them from your database.
  • ids: List of comma-separated ids. Only return objects with these IDs.
  • remote_ids: List of comma-separated remote ids. Only return objects with these remote IDs.

Rate limiting

The rate limiter restricts the number of API requests you can send to Kombo. Currently, we permit 300 requests over 60 seconds. After the time has passed, the limit is reset.

This information is exposed as headers on the response of every authenticated API request:

HeaderSample ValueDescription
ratelimit-limit300The maximum number of requests permitted
ratelimit-remaining298The remaining number of requests permitted
ratelimit-reset57The remaining seconds until the rate limiter is reset

When exceeded, you will receive a failed response with a 429 (“Too Many Requests”) status code:

{
  "status": "error",
  "error": {
    "message": "Rate limit exceeded. Maximum requests are 300 every 60 seconds"
  }
}

Handling rate limiting

The simplest way of handling rate limits is to watch for 429 status codes. If you receive one, you can implement retry logic that sends the same API request with an exponentially increasing wait time between each retry.

For a more sophisticated approach, you could parse the headers mentioned above and use the information about remaining requests and reset time to ensure you never encounter the rate limit. This could be useful if, for example, you never want a POST request to fail; you could globally keep track of the ratelimit-remaining value and keep a certain buffer of requests available to only be used by POST requests.