---
title: "App Store"
description: "Use the App Store for MainSDK app updates on iOS - update prompts, minimum versions enforced on the server, main.yaml, testing and swapping."
section: "integrations"
canonical: "https://mainsdk.dev/docs/integrations/app-store"
updated: "2026-10-28"
---

# App Store

> Use the App Store for MainSDK app updates on iOS - update prompts, minimum versions enforced on the server, main.yaml, testing and swapping.

Canonical: https://mainsdk.dev/docs/integrations/app-store · Updated: 2026-10-28

The App Store driver serves [`updates`](https://mainsdk.dev/docs/interfaces/updates) for iOS apps. When a new version is ready, your app shows a prompt that opens your App Store listing; when a version is too old or insecure, it shows an "Update required" screen and your server refuses requests from it. Pick it for any iOS build you ship through the App Store, next to Google Play for Android.

> **Note:** `updates` has no spec yet. The calls and options on this page are provisional, taken from the catalog and the product requirements, and may change when the spec lands.

## Interfaces it serves

### App updates and version blocking (`updates`)

- Status: Building for 0.7 · ships as a beta API
- Driver: `app-store` (App Store). 1.1; opens the store page, iOS has no in-app update API
- Docs: https://mainsdk.dev/docs/interfaces/updates.md

```yaml
updates:
  driver: app-store
```

Swap to another provider: `local`, `expo-updates`, `google-play`, `tauri`.

## Before you start

You need an Apple Developer Program membership and an app record in App Store Connect.

1. **Ship your app through App Store Connect.** The driver points users at your public listing, so the app must be live (or in TestFlight while you test).
2. **Note your app's App Store ID.** It identifies your listing; the prompt uses it to open the right page.
3. **Version consistently.** Keep the app version in semantic versioning (2.4.1). App stores accept only numbers in a version, and `updates` compares versions to decide what to prompt or block.

## Configure

Set the driver for your app's iOS build:

```yaml title="main.yaml"
updates:
  driver: app-store
  # [TBD] how the App Store ID and the minimum version are declared
```

The mobile target is one target with `platforms: [ios, android]`; how you give iOS and Android different `updates` drivers is not decided yet [TBD]. A target overlay such as `main.target.web.yaml` can set a different driver for web. How you declare the minimum version, staged rollout percentages and markets is not decided yet. The App Store driver needs no secret for the prompt itself; whether it reads anything from App Store Connect is [TBD].

## Use it

```ts title="app/startup.ts"
import { updates } from "mainsdk";

export async function onStartup() {
  const u = await updates.check();
  if (u.required) showUpdateScreen(u);   // your own screen; it opens the App Store
}
```

`updates.minVersion()` sets the oldest version you still accept after a security fix. The change is audited and the server refuses older versions. Its arguments arrive with the spec.

## Local development and testing

- **Simulator and TestFlight:** run `updates.check()` against a TestFlight build to see the prompt before you release.
- **Tests:** `createTestApp()` from `@mainsdk/testing` runs `updates` on an in-memory fake, so tests reach no app store, and `chaos.on("updates", { outage: true })` simulates the update check failing. Helpers to set a minimum version on the fake arrive with the spec.

## What MainSDK adds on top

- Blocking enforced by the server as well as the app, so a modified client cannot skip it.
- Blocked users can still export their data.
- Every change to the minimum version audited.
- Version spread from [`analytics`](https://mainsdk.dev/docs/interfaces/analytics), so you see who an update block would hit before you set it.

See [App updates and version blocking](https://mainsdk.dev/docs/interfaces/updates) for the full contract.

## Limits and notes

- Planned driver, not in a spec yet: `updates` is phase 2.
- iOS has no in-app update API, so the prompt opens the App Store rather than updating in place.
- JavaScript-only changes can go over the air with [Expo](https://mainsdk.dev/docs/integrations/expo) Updates where Apple's rules allow; native changes go through App Store review.
- MainSDK Cloud Teams adds release dashboards; Fleet adds fleet-wide version rules.

## Swap to or from it

Most apps set a driver per platform rather than swapping one:

```yaml title="main.yaml"
updates:
  driver: expo-updates   # was app-store
```

Your `updates.check()` and `updates.minVersion()` calls stay the same.

## FAQ

**Can an iOS app update itself without the App Store?** Not for native code. The prompt opens your listing; only JavaScript-only changes can go over the air, where Apple's rules allow.

**Does blocking an old version lock users out of their data?** No. Blocked users can still export their data.

**Can I roll out to some users first?** Staged rollouts by percentage and market are part of the phase 2 design; App Store phased release is configured in App Store Connect.

## Next

- [App updates and version blocking](https://mainsdk.dev/docs/interfaces/updates) and [Where the app is used](https://mainsdk.dev/docs/interfaces/analytics)
- [Google Play](https://mainsdk.dev/docs/integrations/google-play), [Expo](https://mainsdk.dev/docs/integrations/expo) and [Tauri](https://mainsdk.dev/docs/integrations/tauri)
