Durations API
The Durations API returns a predicted duration for every test, so a test runner can split shards by duration instead of by test count. A balanced split makes the slowest shard shorter and CI finishes faster.
You send Flakiness.io the list of tests you are about to run, and it returns the same list annotated with each test’s predicted duration. The runner reads those durations and balances its shards.
The exchange consists of three sequential steps:
- Create Session - Start a durations session for a commit and receive a
testDurationsTokenplus a presigneduploadUrl. - Upload the Test List - Upload a Flakiness report describing the tests you intend to run, using the presigned URL.
- Submit & Poll - Trigger the computation, receive a presigned
downloadUrl, and poll it until the report with durations attached is ready.
Concepts
Section titled “Concepts”Predicted durations
Section titled “Predicted durations”For each test, Flakiness.io returns a predicted duration per environment, based on how that test has run before.
A test with no prior data still appears in the response, but with an empty attempts array; likewise, a test that has data for some environments but not others simply has no attempt for the environments it lacks. So a missing prediction shows up as a missing attempt, not a missing test. Treat any test or environment with no attempt as “no estimate” and substitute your own (for example, the test count). Otherwise new tests land at zero duration and unbalance the shards.
commitId
Section titled “commitId”Identifies the commit you are testing. Together with the shardGroupKey, it keeps the predicted durations stable and consistent across every shard of a run.
shardGroupKey
Section titled “shardGroupKey”Every shard in a run asks for the same durations. The shardGroupKey groups those concurrent requests so the prediction is computed once and shared, rather than recomputed by each shard. It is combined with the commitId, so the test runner’s name and version is usually enough.
Report format
Section titled “Report format”Both the upload and the download use the Flakiness.io JSON Report format. The report you upload lists the tests and the environment(s) they will run in. The report you download is the same document with each test’s attempts filled in: one attempt per environment for which a prediction exists, carrying the predicted duration. Every uploaded test is present in the response; tests without a prediction keep an empty attempts array.
Like the Upload API, both the upload and the download are Brotli-compressed with Content-Type: application/json and Content-Encoding: br.
Quick Start Example
Section titled “Quick Start Example”-
Create a Durations Session
Start the session for the commit you are about to test:
Terminal window curl -X POST "https://flakiness.io/api/testDurations/create" \-H "Authorization: Bearer $FLAKINESS_ACCESS_TOKEN" \-H "Content-Type: application/json" \-d '{"commitId":"a1b2c3d","shardGroupKey":"ci-run-8123"}'Response:
{"testDurationsToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...","uploadUrl": "https://s3.flakiness.test/flakiness-data/test-durations/..."}The
testDurationsTokenauthenticates the submit step and expires in 10 minutes. -
Compress and Upload the Test List
Build a Flakiness report listing the tests you are about to run and the environment(s) they run in, then compress it with Brotli:
Terminal window brotli --quality=9 --output=tests.json.br tests.jsonUpload it to the presigned URL:
Terminal window curl -X PUT "$UPLOAD_URL" \-H "Content-Type: application/json" \-H "Content-Encoding: br" \--data-binary @tests.json.br -
Submit and Receive a Download URL
Trigger the computation with the session token:
Terminal window curl -X POST "https://flakiness.io/api/testDurations/submit" \-H "Authorization: Bearer $TEST_DURATIONS_TOKEN"Response:
{"downloadUrl": "https://s3.flakiness.test/flakiness-data/test-durations/..."}The
downloadUrlis valid for 1 hour. -
Poll the Download URL
The report is computed asynchronously, so the
downloadUrlis not ready the instant submit returns. Poll it until it responds with the report, usually within a few seconds. The URL returns404while the result is still being computed:Terminal window until curl -fsS --compressed "$DOWNLOAD_URL" -o durations.json; do sleep 1; doneEach test in
durations.jsonnow carries anattemptper environment for which a prediction exists, with the predicteddurationin milliseconds. Tests with no prediction keep an emptyattemptsarray, so fall back to your own estimate for those. Feed the durations into your runner to balance shards.
API Methods
Section titled “API Methods”Create Session
Section titled “Create Session”| Method | Endpoint | Authorization | Content-Type |
|--------|----------|---------------|--------------|
| POST | /api/testDurations/create | Bearer {ACCESS_TOKEN} | application/json |
curl -X POST "https://flakiness.io/api/testDurations/create" \ -H "Authorization: Bearer $FLAKINESS_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{"commitId":"a1b2c3d","shardGroupKey":"ci-run-8123"}'{ "testDurationsToken": "eyJhbGciOiJIUz...", "uploadUrl": "https://s3.flakiness.test/flakiness-data/test-durations/..."}Starts a durations session and returns a session token along with a presigned URL for uploading the test list.
Request Body:
commitId- The commit you are testing. Combined withshardGroupKey, it keeps predictions stable across a run’s shards. It is not used to look up history.shardGroupKey- Groups concurrent requests from the shards of one run so the prediction is computed once. Combined withcommitId, so the test runner’s name and version is usually enough. Must match^[a-zA-Z0-9_-]+$and be 1–250 characters.orgSlug,projectSlug- Optional. When the access token is already bound to a single project (CI access token or GitHub OIDC), these are inferred and can be omitted.
Response Fields:
testDurationsToken- JWT for authenticating the submit call. Expires in 10 minutes.uploadUrl- Presigned URL for uploading the Brotli-compressed test list.
Submit & Poll
Section titled “Submit & Poll”| Method | Endpoint | Authorization | Content-Type |
|--------|----------|---------------|--------------|
| POST | /api/testDurations/submit | Bearer {TEST_DURATIONS_TOKEN} | N/A |
curl -X POST "https://flakiness.io/api/testDurations/submit" \ -H "Authorization: Bearer $TEST_DURATIONS_TOKEN"{ "downloadUrl": "https://s3.flakiness.test/flakiness-data/test-durations/..."}Triggers the computation for the uploaded test list and returns a presigned URL for the annotated report. Call this after the test list has been uploaded to the uploadUrl from the create step.
The report is produced asynchronously, so the downloadUrl is not populated when this call returns. Poll the URL until it responds with 200, usually within a few seconds; it returns 404 while the result is still being computed. The annotated report is a Brotli-compressed Flakiness report where each test carries an attempt per environment for which a prediction exists; tests without a prediction keep an empty attempts array.
Response Fields:
downloadUrl- Presigned URL for the annotated report. Poll it until ready. Valid for 1 hour.