AppForShareGet a token

Docs

CI API reference

The HTTP API the AppForShare CLI uses. Call it from any CI, script or tool to upload builds, find the newest one, move it between channels, read tester feedback and manage testers. Pro and Team; parts marked Team need a Team workspace.

Base URL: https://appforshare.io/api

Auth: Authorization: Bearer afs_... with an API token from Settings

Format: JSON in and out, except chunks (raw bytes) and file downloads. Errors answer with a message field.

Upload a build

Uploads are resumable: create the upload, send the file in chunks of up to 32 MB, then complete it. After a dropped connection, read the status to get the offset and go on from there. The X-Upload-Token from the first answer goes with every later call. This is the flow the CLI, GitHub Action, fastlane and Gradle plugins use.

POST/uploadsChanges data

Start an upload. fileName ends in .ipa, .apk or .aab; size is in bytes. Optional: releaseNotes (Pro and Team), channel (created on first use, Pro and Team), groups and testers to share the build with when it is ready (Team, up to 100 each). Answers id, token, chunkBytes and offset.

curl -s -X POST https://appforshare.io/api/uploads \
  -H "Authorization: Bearer $APPFORSHARE_TOKEN" -H "Content-Type: application/json" \
  -d '{"fileName":"app-release.apk","size":48211337,"releaseNotes":"Fixes the login crash","channel":"beta","groups":["Client QA"]}'
# {"id":"Q3vF8kL2mN0pR7sT","token":"...","chunkBytes":33554432,"offset":0}

PUT/uploads/:id?offset=NChanges data

Send the next chunk as raw bytes, starting at offset. The answer is the new offset. A wrong offset answers 409 with the offset to use.

split -b 32m app-release.apk part_
offset=0
for p in part_*; do
  curl -s -X PUT "https://appforshare.io/api/uploads/$ID?offset=$offset" \
    -H "X-Upload-Token: $UPLOAD_TOKEN" -H "Content-Type: application/octet-stream" \
    --data-binary @"$p"
  offset=$((offset + $(wc -c < "$p")))
done

POST/uploads/:id/completeChanges data

Finish the upload. The build is queued for processing.

curl -s -X POST https://appforshare.io/api/uploads/$ID/complete -H "X-Upload-Token: $UPLOAD_TOKEN"

GET/uploads/:id

Status: UPLOADING (with the offset received so far), QUEUED, PROCESSING, READY or FAILED (with error). When READY it has the install link url, the slug, expiresAt and, with a channel, the channel link.

curl -s https://appforshare.io/api/uploads/$ID -H "X-Upload-Token: $UPLOAD_TOKEN"
# {"id":"Q3vF8kL2mN0pR7sT","status":"READY","url":"https://appforshare.io/i/Stw0Ae","slug":"Stw0Ae","channel":{"name":"beta","url":"https://appforshare.io/c/..."},...}

Account and builds

A build is addressed by its id or its link slug (:ref).

GET/ci/whoami

Email, workspace, role and plan of the token.

curl -s https://appforshare.io/api/ci/whoami -H "Authorization: Bearer $APPFORSHARE_TOKEN"

GET/ci/projects

Projects with their ids and whether they are public or private to invited testers.

GET/ci/builds

Recent builds, newest first. Filters: platform (ios or android), app (bundle id or package name), project, channel, limit (1 to 100, default 20).

curl -s "https://appforshare.io/api/ci/builds?platform=android&app=com.example.shop&limit=5" -H "Authorization: Bearer $APPFORSHARE_TOKEN"

GET/ci/builds/latest

The newest build that matches the same filters, or 404 when there is none. With channel: the build in that channel.

curl -s "https://appforshare.io/api/ci/builds/latest?channel=beta&platform=ios" -H "Authorization: Bearer $APPFORSHARE_TOKEN"

GET/ci/builds/:ref

One build with its release notes, the store readiness report (status and each finding with a fix) and, on Pro and Team, the crash dashboard link for that version.

DELETE/ci/builds/:refChanges data

Delete a build. It can be restored from the dashboard for 7 days. Developer role.

Channels, links and release checklist

POST/ci/builds/:ref/channelChanges data

Put a build into a channel (created when missing); an older build is a rollback of the link. On Team a gated channel answers 409 with what is missing; force: true works for an Admin token. Pro and Team, Developer role.

curl -s -X POST https://appforshare.io/api/ci/builds/12345/channel \
  -H "Authorization: Bearer $APPFORSHARE_TOKEN" -H "Content-Type: application/json" \
  -d '{"channel":"live"}'

PATCH/ci/builds/:ref/linkChanges data

Link controls: paused (true or false), stopAt (an ISO date and time, or null), maxInstalls (a number, or null). Setting needs Pro or Team; removing works on any plan. Developer role.

curl -s -X PATCH https://appforshare.io/api/ci/builds/12345/link \
  -H "Authorization: Bearer $APPFORSHARE_TOKEN" -H "Content-Type: application/json" \
  -d '{"stopAt":"2026-12-31T23:59:59Z","maxInstalls":50}'

PUT/ci/channels/testflightChanges data

Add the TestFlight public link to a channel (url), or remove it (url: null). Name the app with app (bundle id) or project. Pro and Team, Developer role.

curl -s -X PUT https://appforshare.io/api/ci/channels/testflight \
  -H "Authorization: Bearer $APPFORSHARE_TOKEN" -H "Content-Type: application/json" \
  -d '{"channel":"beta","app":"com.example.shop","url":"https://testflight.apple.com/join/AbCd1234"}'

GET/ci/builds/:ref/release

The release checklist of a build with its ticks, open release blockers and whether the gated channel takes it. Team.

PUT/ci/builds/:ref/release/checks/:keyChanges data

Tick or untick one step. Developer role. Team.

curl -s -X PUT https://appforshare.io/api/ci/builds/12345/release/checks/a1b2c3d4 \
  -H "Authorization: Bearer $APPFORSHARE_TOKEN" -H "Content-Type: application/json" -d '{"done":true}'

GET/ci/builds/:ref/test-plan/export?format=firebase|maestro

The AI test plan of the build as a YAML file: Firebase App Testing agent test cases (run with firebase apptesting:execute --test-dir; Android only, in preview) or a Maestro starter flow. The build needs a plan first. Pro and Team.

curl -s "https://appforshare.io/api/ci/builds/12345/test-plan/export?format=firebase" \
  -H "Authorization: Bearer $APPFORSHARE_TOKEN" -o tests/app-testing.yaml

Feedback and activity

GET/ci/feedback

Tester feedback, newest first: message, kind, device, build, whether it came from the in-app feedback link with its screen, how many screenshots, and a dashboard link. Filters: build (id or slug), status (open, resolved or all; default open).

curl -s "https://appforshare.io/api/ci/feedback?build=Stw0Ae&status=open" -H "Authorization: Bearer $APPFORSHARE_TOKEN"

POST/ci/feedback/:id/trackerChanges data

Make a Linear or Jira issue from a report, with its screenshots, once a tracker is connected. Sent once per report. Pro and Team, Developer role.

curl -s -X POST https://appforshare.io/api/ci/feedback/678/tracker \
  -H "Authorization: Bearer $APPFORSHARE_TOKEN" -H "Content-Type: application/json" -d '{"tracker":"jira"}'

POST/ci/feedback/:id/taskChanges data

Add a task from a report to its project's task board, linked to the build. Team, Developer role.

GET/ci/activity

Workspace activity, newest first. Filters: project, kind (build, channel, feedback, task, release, link, tracker, tester), before (an activity id, for the next page), limit (1 to 100, default 50). Team.

curl -s "https://appforshare.io/api/ci/activity?kind=channel&limit=20" -H "Authorization: Bearer $APPFORSHARE_TOKEN"

Testers and groups (Team)

Emails go in lists of up to 100 per call. An account can have up to 1,000 testers. Changes need the Developer role.

GET/ci/testers

Testers with their projects and groups. Filters: project, group (name).

curl -s "https://appforshare.io/api/ci/testers?group=Client%20QA" -H "Authorization: Bearer $APPFORSHARE_TOKEN"

POST/ci/testersChanges data

Add testers: emails, optional project and groups (names). New testers get an invite unless notify is false.

curl -s -X POST https://appforshare.io/api/ci/testers \
  -H "Authorization: Bearer $APPFORSHARE_TOKEN" -H "Content-Type: application/json" \
  -d '{"emails":["[email protected]","[email protected]"],"project":42,"groups":["Client QA"]}'

POST/ci/testers/importChanges data

Import a CSV as text: an email column, name or first and last name columns, a groups column (semicolon or pipe between several). Groups are made when missing. Up to 1,000 rows; invites only with notify: true, and then up to 200 new testers per import.

jq -Rs '{text: ., groups: ["Beta"]}' testers.csv | curl -s -X POST https://appforshare.io/api/ci/testers/import \
  -H "Authorization: Bearer $APPFORSHARE_TOKEN" -H "Content-Type: application/json" --data @-

POST/ci/testers/removeChanges data

With project: take away the access you gave by hand in that project (access through a group stays). Without: remove the testers from the workspace.

GET/ci/tester-groups

Groups with member counts and their projects.

POST/ci/tester-groupsChanges data

Make a group: name, optional project.

DELETE/ci/tester-groups/:nameChanges data

Delete a group. Its members stay testers.

POST/ci/tester-groups/:name/membersChanges data

Add members by email (made testers when new); notify defaults to true.

POST/ci/tester-groups/:name/members/removeChanges data

Take members out of a group.

POST/ci/builds/:ref/distributeChanges data

Share an uploaded build with groups and testers: the groups get its project, new addresses become testers, and they are emailed its install link (at most one email per tester per project in an hour). Up to 100 groups and testers together.

curl -s -X POST https://appforshare.io/api/ci/builds/12345/distribute \
  -H "Authorization: Bearer $APPFORSHARE_TOKEN" -H "Content-Type: application/json" \
  -d '{"groups":["Client QA"],"testers":["[email protected]"]}'

Devices

POST/ci/devices/importChanges data

Import iPhone and iPad UDIDs as text: Firebase's Export Apple UDIDs file, Apple's Register Multiple Devices file or one UDID per line with an optional name. Up to 1,000 per call. Answers added, known, named and the skipped lines with a reason. Developer role.

jq -Rs '{text: .}' firebase-udids.txt | curl -s -X POST https://appforshare.io/api/ci/devices/import \
  -H "Authorization: Bearer $APPFORSHARE_TOKEN" -H "Content-Type: application/json" --data @-

GET/ci/devices/apple-devices.txt

Your devices in Apple's Register Multiple Devices format, for the Apple portal or fastlane register_devices.

curl -s https://appforshare.io/api/ci/devices/apple-devices.txt -H "Authorization: Bearer $APPFORSHARE_TOKEN" -o devices.txt

Questions

Which plan do I need?
API tokens come with Pro and Team. Testers, groups, distribute, the release checklist, tasks and activity need Team. Make a token under Dashboard, Settings, API tokens.
What can a token do?
The same as its creator in that workspace, with their role: a Viewer token only reads. Revoke a token in Settings and it stops at once.
Is there a rate limit?
Yes. Adding testers, adding group members and distribute share 20 calls an hour per workspace, tester imports 10 an hour and device imports 30 an hour. An answer of 429 means wait and try again.
Do I have to use the API?
No. The CLI does all of this with one command per job, and the GitHub Action, fastlane plugin and MCP server use the same calls.

Prefer commands? See the CLI, GitHub Action, fastlane and Gradle guide, or connect an AI tool through the MCP server.