Connecting your app
Semaloop picks up every new iOS build from TestFlight automatically, and Android builds arrive as an APK pushed from your CI. There are a few different ways you can connect your app: on iOS you can use TestFlight or push a build directly, and on Android you push an APK.
Before you connect
Section titled “Before you connect”Setting up a new app or platform isn’t self-serve yet. You’ll need to contact us first if you’re:
- Onboarding for the first time.
- Adding Android to an existing iOS app.
- Adding iOS to an existing Android app.
We’ll gather the details we need, set things up on our side and get back to
you. Until then, builds you push to us (an APK, or an iOS .app or .ipa)
are rejected with an error, and we can’t start picking up your TestFlight
builds — joining your TestFlight group is something we trigger on our side.
Once that’s done, new builds you ship through TestFlight or push from CI are picked up automatically.
When we set up a second platform in your Semaloop account, such as adding Android alongside your iOS app, it’s added as a separate app with its own tests, builds and API key. We copy your existing tests, secrets and tools across to it, so you don’t start from scratch. Check any test that relies on something only one platform has, such as a phone number or an iOS-only screen, and keep tests that need a phone number on your iOS app.
TestFlight (iOS)
Section titled “TestFlight (iOS)”Semaloop ingests every new iOS build from TestFlight automatically: its agents join your app’s TestFlight as testers, the same way a person on your team would, and pick up each build you make available to them. This is the easiest and most popular way of connecting your app. TestFlight builds run on our real devices.
There are three ways to set this up. All of them start with contacting us.
- External, public link. You create a public link for an external group and send it to us. The fewest steps, and the one to pick if you’re not sure.
- External, email invite. You invite the agent email addresses we send you to an external group. Use it if you’d rather not create a public link.
- Internal. You add the agent email addresses as App Store Connect users on your team. Use it if you only distribute internally, or your builds are uploaded as TestFlight Internal Only.
External groups (routes 1 and 2) need Apple’s TestFlight App Review for the first build of each version. Internal groups don’t, but the agents need App Store Connect accounts on your team.
1. External TestFlight: public link
Section titled “1. External TestFlight: public link”What you need to do
- In your app’s TestFlight tab, choose an external group and add the build you want tested, with Automatically notify testers ticked.
- In that group, create a public link that’s Open to Anyone, with no tester limit.
- Send us the link privately.
For each new build after that, add it to the same group.
Step-by-step guide
Before you start
- You’ve contacted us and we’ve confirmed we’re ready to join.
- You have the Account Holder, Admin or App Manager role in App Store Connect.
- The build you want tested was not uploaded as TestFlight Internal Only. Those builds can only go to internal groups — use route 3 instead.
- The build supports iOS 18 or later, which our devices run (see supported platforms).
Steps
- In App Store Connect, go to Apps, select your app and open the TestFlight tab. Check it’s the app you set up with us — if you have several similar apps, compare the bundle ID under App Information.
- In the sidebar, under External Testing, select the group you want us in. To make a new one, click + next to External Testing, name it (for example, “Semaloop”) and click Create. Apple requires you to have an internal group before you can create an external one.
- On the group page, click Add Builds (or + next to Builds), choose the version and build you want tested, and click Add.
- Fill in What to Test and tick Automatically notify testers. That notification is how our agents learn a build is ready; if you leave it unticked, you’ll have to notify testers by hand after every review (see step 6).
- Click Submit Review or Start Testing, whichever appears. The first build of each version goes through Apple’s TestFlight App Review; later builds of the same version may not. We can’t install the build until it’s approved.
- If you didn’t tick Automatically notify testers: once the build is approved, go to Builds in the sidebar, choose the version and click Notify Testers on the build’s row. Its status changes to Testing. Adding a build to a group doesn’t make it available until this happens.
- Open the group’s Testers tab and click Create Public Link.
- Choose Open to Anyone. If you choose Filter by Criteria instead, check the criteria include iOS 18 and later, or our devices can’t join.
- Leave Tester limit off, or set it high enough to leave room for our agents — ask us how many will join. If the beta is full, our agents can’t join through the link.
- Click Confirm, then copy the link.
- Send the link to us privately, through your shared Slack channel or by email. Anyone with the link can join your beta, so don’t post it anywhere public.
For each new build after that, repeat steps 3 to 6 in the same group. Your link stays the same.
Checklist
- The group is under External Testing, in the right app.
- The build you want tested is in that group, and its status is Testing (approved and testers notified).
- The public link is enabled, open to iOS 18 and later, and has room for our agents.
- You’ve sent the link to us privately, and we’ve confirmed our agents have joined.
Public-link testers show as anonymous in App Store Connect, so you won’t see our agents’ names or email addresses in the group. To check we’ve joined, ask us.
2. External TestFlight: email invite
Section titled “2. External TestFlight: email invite”What you need to do
- Get the agent email addresses for your app from us.
- In your app’s TestFlight tab, choose an external group and add the build you want tested, with Automatically notify testers ticked.
- In that group, invite each address under Testers → Email, then tell us.
You don’t add our agents under Users and Access for this route. For each new build, add it to the same group.
Step-by-step guide
Before you start
- You’ve contacted us and we’ve sent you the agent email addresses for your app. Use exactly those addresses — there’s no single Semaloop address that works for everyone.
- You have the Account Holder, Admin or App Manager role in App Store Connect.
- The build you want tested was not uploaded as TestFlight Internal Only. Those builds can only go to internal groups — use route 3 instead.
- The build supports iOS 18 or later.
Steps
- In App Store Connect, go to Apps, select your app and open the TestFlight tab. Check it’s the right app.
- In the sidebar, under External Testing, select the group you want us in, or click + next to External Testing to create one.
- Add the build and get it approved and available, as in steps 3 to 6 of route 1: Add Builds, What to Test, Submit Review or Start Testing, then Notify Testers if you didn’t tick Automatically notify testers.
- On the group page, click + next to Testers and choose Email.
- Enter each agent email address we sent you, with any first and last name (for example, “Semaloop Agent”), and add them.
- Tell us you’ve sent the invitations, through your shared Slack channel or by email.
Inviting testers and making a build available are separate steps. The agents can accept an invitation before any build is ready, but they can only install builds that are in their group with the status Testing. For each new build, add it to the same group and get it to Testing — you don’t need to invite the agents again.
Checklist
- The group is under External Testing, in the right app.
- Every agent address we sent you is in the group’s Testers list, spelled exactly as we sent it.
- The build you want tested is in that group, with the status Testing.
- You’ve told us the invitations are sent, and we’ve confirmed our agents have accepted.
Once an agent accepts, App Store Connect shows its name and email address in the group’s tester list.
3. Internal TestFlight
Section titled “3. Internal TestFlight”What you need to do
- Get the agent email addresses for your app from us.
- In Users and Access, add each address as a user with the Developer or Marketing role and access to this app only. We accept the invitations on our side.
- In your app’s TestFlight tab, add the agents to an internal group.
- Make sure each build reaches that group, either with Enable automatic distribution or by adding it with Add Builds.
A build only reaches us when all four are in place.
Step-by-step guide
Before you start
- You’ve contacted us and we’ve sent you the agent email addresses for your app.
- You have the Account Holder or Admin role (to add users), or App Manager (to manage groups once the users exist).
- Your internal group has room — Apple allows up to 100 internal testers per app.
Give each agent an App Store Connect account
- In App Store Connect, go to Users and Access, and under People, click +.
- Enter a first and last name (for example, “Semaloop Agent”) and the agent email address exactly as we sent it.
- Under roles, select Developer or Marketing only. Both can be internal testers and can be limited to specific apps. Don’t give the agents Admin or Account Holder — internal testing doesn’t need them.
- Don’t grant access to reports or to Certificates, Identifiers & Profiles. Either one gives the user access to all of your apps.
- Click Next, select only the app you want tested, and click Invite.
- Tell us you’ve sent the invitations. We accept them on our side. Apple’s invitations expire after three days — if we miss that window, we’ll ask you to resend it from the user’s page in Users and Access.
Add the agents to an internal group
- Go to Apps, select your app and open the TestFlight tab.
- In the sidebar, under Internal Testing, select your group, or click + next to Internal Testing to create one.
- When you create a group, decide whether to tick Enable automatic distribution. With it on, each build you upload from Xcode goes to everyone in the group automatically. With it off, you add each build by hand.
- Click Invite Testers (or + next to Testers), tick each agent and click Add.
Add the build
If automatic distribution is on and you upload from Xcode, new builds reach the group without any action from you. Otherwise, and always for builds from Xcode Cloud:
- On the group page, click Add Builds (or + next to Builds).
- Choose the build, click Next, fill in What to Test and click Add.
Internal builds don’t need TestFlight App Review, and both regular and TestFlight Internal Only builds work.
If an agent isn’t in the tester picker
The Invite Testers list only shows users who can be internal testers for this app. If an agent is missing, check in Users and Access:
- The account exists and uses the address we sent you.
- We’ve accepted the invitation. Until we have, the agent may not be available to add. Ask us to check, or resend the invitation if it’s expired.
- The role is eligible. Account Holder, Admin, App Manager, Developer and Marketing can be internal testers; Sales, Customer Support and Finance can’t.
- The user has access to this app. If you limited their app access, this app must be selected.
Checklist
- Each agent address is a user in Users and Access, with Developer or Marketing and access to this app.
- We’ve confirmed we’ve accepted every invitation.
- Each agent is in the internal group under TestFlight → Internal Testing.
- The build you want tested is in that group — automatically, or added by hand.
Uploading a build (iOS)
Section titled “Uploading a build (iOS)”If you don’t want to connect your app with TestFlight, you can also send a build to us directly with the Semaloop CLI.
First, you’ll need to generate an API key in Settings → API keys → Manage keys.

Upload a .app artefact to run your tests on a simulator.
Upload a .ipa artefact to run your tests on a real device. You’ll need to
sign it with Semaloop device UDIDs before pushing it to us — see
Apple’s Xcode documentation.
Contact us to get our UDID list.
Uploading a build (Android)
Section titled “Uploading a build (Android)”Android apps connect by uploading a build to us from your CI. There is no Play Console integration — we take the artefact your build already produces.
You’ll need an API key scoped to the Android app, generated the same way as above in Settings → API keys → Manage keys. With it, the Semaloop CLI or the GitHub Action pushes the APK for you. To call the API directly instead, use the key as a bearer token and make three calls:
POST /api/v1/uploads— the response contains anuploadIdand anuploadUrl.PUTthe raw APK bytes touploadUrl, with aContent-Typeofapplication/octet-stream. Don’t wrap the APK in a ZIP.POST /api/v1/uploads/finalizewith{ "id": "<uploadId>" }.
The APK’s package ID has to match the app the key is scoped to. App bundles,
XAPK or APK-set containers, and individual split APKs are rejected — send a
single installable APK. If your app has native code, the APK needs x86_64 or
arm64-v8a libraries; x86_64 runs fastest on our emulators.
Exporting an APK from an app bundle
Section titled “Exporting an APK from an app bundle”Semaloop does not accept an Android App Bundle (.aab). An upload that
contains one is rejected when you finalize it, so export a single installable
APK first. There are two ways to do that.
Build an APK directly. This is the simplest route. Run
./gradlew assembleRelease (or assembleDebug) and upload the APK it writes
under app/build/outputs/apk/. In Android Studio, choose Build →
Generate Signed App Bundle / APK and select APK.
Convert an existing .aab with
bundletool. A universal
APK contains the code and resources for every device configuration in one
file:
bundletool build-apks --bundle=app.aab --output=app.apks --mode=universal \ --ks=release.keystore --ks-key-alias=<alias>unzip app.apks universal.apkThe .apks file is a ZIP archive, and the universal.apk inside it is the
file to upload. If you leave out the signing flags, bundletool signs with your
debug keystore when it finds one. Check that the APK has x86_64 or
arm64-v8a native libraries, as described above.
Your Android package ID can be the same as your iOS bundle ID. Semaloop treats them as two separate apps, each with its own tests, builds and API key.
Android tests run on emulators. See supported platforms for what that does and doesn’t cover today.
Staging, beta and production builds
Section titled “Staging, beta and production builds”Semaloop treats each bundle ID or package ID as its own app, with its own
tests, builds and API key. If your staging or beta builds use a different
bundle ID from production, such as com.example.app.beta,
contact us and we’ll add it as a second app,
copying your tests across.
If your environments share one bundle ID, Semaloop can’t tell two builds apart when both arrive through TestFlight. Either give each environment its own bundle ID, or send them through different channels, for example production through TestFlight and staging as an upload from your CI. Each channel has its own setting for which tests run automatically, so you can use tags to run your production-only tests on one and your staging-only tests on the other.
TestFlight doesn’t tell Semaloop which branch a build came from, only its version and build number. To run different tests for different branches, upload those builds from your CI instead and choose which tests run there.