Skip to main content

Distributing builds to testers

You can upload build artifacts to Release Management and distribute them to tester groups directly via the API. Tester groups can be internal (Bitrise users you add by their user slug) or external (testers you add by email, with no Bitrise account required). This covers both the artifact upload flow (Apps sub-API) and tester group management (Build Distributions sub-API).

  • Apps sub-API base URL: https://api.bitrise.io/release-management/v2/apps/v1. See the Apps API reference.
  • Build Distributions sub-API base URL: https://api.bitrise.io/release-management/v2/build-distributions/v1. See the Build Distributions API reference.

Uploading a build artifactClick to copy link

EndpointSub-APIFunction
GET /installable-artifacts/{id}/upload-urlAppsGenerate a presigned upload URL.
GET /installable-artifacts/{id}/statusAppsCheck upload and processing status.
GET /installable-artifactsAppsList uploaded artifacts for an app.
GET /installable-artifacts/{id}AppsGet details of an artifact.
DELETE /installable-artifacts/{id}AppsDelete an artifact.

Step 1: Generate an upload URLClick to copy link

Generate a presigned S3 upload URL for your build artifact. The response includes both the upload URL and confirms the artifact ID.

ARTIFACT_ID=$(uuidgen | tr '[:upper:]' '[:lower:]')

curl -X GET "https://api.bitrise.io/release-management/v2/apps/v1/installable-artifacts/${ARTIFACT_ID}/upload-url?app_id=APP_ID&file_name=MyApp.ipa&file_size_bytes=52428800" \
-H "Authorization: YOUR_ACCESS_TOKEN" \
-H "Accept: application/json"

Required query parameters:

  • app_id: The RM app ID.
  • file_name: The filename of the artifact (e.g., MyApp.ipa or MyApp.apk).
  • file_size_bytes: The file size in bytes.

Optional query parameters:

  • with_public_page: Set to true to enable a public install page immediately.
  • branch: The source branch this build came from.
  • workflow: The CI workflow that produced this build.

Step 2: Upload the binaryClick to copy link

You can upload .ipa (iOS), .apk, or .aab (Android) files. Use the method, url, and headers from the previous response exactly as returned — the headers vary per upload and typically include Content-Type and X-Goog-Content-Length-Range:

# Use the method, url, and headers exactly as returned by the Step 1 response.

curl -X PUT "PRESIGNED_UPLOAD_URL" \
-H "Content-Type: <value from response headers>" \
-H "X-Goog-Content-Length-Range: <value from response headers>" \
--data-binary "@/path/to/MyApp.aab"

Step 3: Check processing statusClick to copy link

After upload, wait for Bitrise to finish processing the artifact:

curl -X GET "https://api.bitrise.io/release-management/v2/apps/v1/installable-artifacts/${ARTIFACT_ID}/status" \
-H "Authorization: YOUR_ACCESS_TOKEN" \
-H "Accept: application/json"

The response returns the current status. Poll this endpoint until the status indicates the artifact is ready for distribution.

Listing installable artifactsClick to copy link

To act on an artifact you didn't just upload yourself, look it up with GET /installable-artifacts:

curl -X GET "https://api.bitrise.io/release-management/v2/apps/v1/installable-artifacts?app_id=APP_ID&items_per_page=10&page=1" \
-H "Authorization: YOUR_ACCESS_TOKEN" \
-H "Accept: application/json"
Use uid, not id

Each item in the response includes both an id and a uid field. Use uid as the ARTIFACT_ID in other calls — id is a separate identifier and won't work in the endpoints on this page.

Enabling a public install pageClick to copy link

You can make a build available via a public URL that testers can open directly without a Bitrise account.

curl -X PATCH "https://api.bitrise.io/release-management/v2/apps/v1/installable-artifacts/ARTIFACT_ID/public-install-page" \
-H "Authorization: YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"with_public_page": true
}'

Adding what-to-test notesClick to copy link

Attach test instructions to a build that testers can see when they receive the notification.

curl -X PATCH "https://api.bitrise.io/release-management/v2/apps/v1/installable-artifacts/ARTIFACT_ID/what-to-test" \
-H "Authorization: YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"what_to_test": "Focus on the new onboarding flow. Check that the splash screen animation completes before login."
}'

The what_to_test field accepts up to 4,000 characters.

Custom access links let you share a build with restricted access: optionally protected by a code and with an expiry date. For more information, see Custom access links.

note

A custom access link is different from the public install page link: the public install page is permanent and has no access controls.

curl -X POST "https://api.bitrise.io/release-management/v2/apps/v1/installable-artifacts/ARTIFACT_ID/custom-access-links" \
-H "Authorization: YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "External QA team",
"expires_at": "2026-07-31T23:59:59Z",
"access_code": "qa-team-2026"
}'

The access_code must be 8–64 characters. Omit expires_at to create a link that does not expire.

Managing tester groupsClick to copy link

Tester groups let you notify groups of internal testers when a new build is ready. For more information, see Tester groups.

EndpointFunction
POST /tester-groupsCreate a tester group.
GET /tester-groupsList tester groups for an app.
PUT /tester-groups/{id}Update a tester group.
POST /tester-groups/{id}/add-testersAdd testers to a group.
POST /tester-groups/{id}/notifyNotify a group about a new build.
DELETE /tester-groups/{id}Delete a tester group.

Creating a tester groupClick to copy link

Set the type query parameter to choose between an internal group (Bitrise users, added by user slug) or an external group (testers added by email, no Bitrise account required). type defaults to internal when omitted.

curl -X POST "https://api.bitrise.io/release-management/v2/build-distributions/v1/tester-groups" \
-H "Authorization: YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"app_id": "APP_ID",
"name": "iOS Beta Testers",
"auto_notify": true
}'

Setting auto_notify: true means testers are automatically emailed when a new build is uploaded.

Adding testers to a groupClick to copy link

Set the type query parameter to match the group's type — type defaults to internal when omitted. The array that doesn't match the group's type is ignored.

curl -X POST "https://api.bitrise.io/release-management/v2/build-distributions/v1/tester-groups/GROUP_ID/add-testers" \
-H "Authorization: YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"user_slugs": ["USER_SLUG_1", "USER_SLUG_2"]
}'
Finding user slugs

To find the user slugs of workspace members, use GET /tester-groups/{id}/potential-testers?search=name-or-email to search for eligible testers. The response includes each user's slug.

Notifying a tester groupClick to copy link

Send a notification to a tester group about a specific build:

curl -X POST "https://api.bitrise.io/release-management/v2/build-distributions/v1/tester-groups/GROUP_ID/notify" \
-H "Authorization: YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"test_build_id": "ARTIFACT_ID"
}'

The build must be distribution-ready before you can notify testers. A successful call returns 204 No Content.

Listing uploaded buildsClick to copy link

To list all builds available for distribution for a specific version:

curl -X GET "https://api.bitrise.io/release-management/v2/build-distributions/v1/test-builds?app_id=APP_ID&version=1.5.0" \
-H "Authorization: YOUR_ACCESS_TOKEN" \
-H "Accept: application/json"