appAttest Start in sandbox

Get started

Bring up appAttest in an iOS app.

End-to-end, this takes about ten minutes on a real device. Each step is small. The docs go deeper on every part — this page is the path.

01 Account

Create your appAttest account.

Sign up with your email. We verify with a one-time code. Add a team — your Apple Team ID becomes the work + billing boundary.

02 Register the app

Create the app in the dashboard.

In the dashboard, click New app. Enter the bundle identifier from your Xcode project — they must match exactly. Pick a team. Two environments are created: development and production.

  • Bundle ID is global. If someone else owns it, registration fails — claim yours early.
  • You can rename the app any time. The bundle ID is the identity.
Dashboard · New app
03 Add secrets

Drop your sandbox values into the dashboard.

Open the app in the dashboard, select the development environment, click Add secret, give it a name (e.g. OPENAI_API_KEY) and paste the value. Repeat for each secret. Production values come later, when you're ready to ship.

  • Values are shown once on creation. Copy elsewhere if you need to.
  • Names are case-sensitive and become the keys you read from Keychain.
Dashboard · Add secret
04 Apple Developer Console

Enable App Attest on your identifier.

App Attest is an Apple capability you turn on per-identifier. Open developer.apple.com → Certificates, Identifiers & Profiles → Identifiers → your app identifier. Scroll to App Services. Enable App Attest. Save.

  • No new provisioning profile needed. Xcode automatic signing picks it up on next build.
  • If you use manual provisioning, regenerate the profile after saving.
developer.apple.com · App Services
05 Xcode capability

Add the App Attest capability in Xcode.

In Xcode, open your project. Select your app target. Go to Signing & Capabilities. Click + Capability and add App Attest. Xcode adds the entitlement automatically.

Xcode · Signing & Capabilities
06 Add the SDK

Add the Swift Package.

In Xcode: File → Add Package Dependencies. Paste the SDK URL. Pick "Up to Next Major Version" from the latest tagged release. Add the AppAttest product to your app target.

SDK URL
https://github.com/AppAttest/sdk
07 Initialize

Wire it up in @main.

The SDK has no configuration. Bundle ID and Team ID come from the signed app at runtime — there is no key to paste in. One synchronous call in your App init runs the whole bootstrap.

  • AppAttest.start() is idempotent and returns in microseconds. The actual attest and sync run in the background.
  • On every launch after the first, secrets are hydrated from Keychain before the first frame — synchronous-feeling reads.
MyApp.swift
import SwiftUI
import AppAttest

@main
struct MyApp: App {
    init() { AppAttest.start() }

    var body: some Scene {
        WindowGroup { ContentView() }
    }
}
08 Read a secret

Read a secret by name.

Wherever your code needs a value, ask for it by the name you used in the dashboard. The read is a synchronous subscript on a process-wide observable; SwiftUI re-renders any view reading it when the value changes.

  • No async / await on the read path. No throws. The subscript returns String? — nil while the first sync is still running, the value once it lands.
  • Need to gate a flow on a specific value being present? Use AppAttest.waitForReady() once during bootstrap; it throws on .subscriptionRequired / .creditsRequired / .unavailable.
  • For tests / previews, inject AppAttestClient.shared via .environment(AppAttestClient.self) and replace it with a stub at injection time.
ContentView.swift
struct ContentView: View {
    var body: some View {
        if let key = AppAttest.secrets["OPENAI_API_KEY"] {
            Text("Ready")
        } else {
            ProgressView("Loading…")
        }
    }
}
09 Verify

Run on a real device. Watch the dashboard.

App Attest needs real Apple-signed hardware to produce attestations — the simulator does not work without a debug stub. Build and run on a device. In the dashboard, open your app and watch Recent activity for one attestation.succeeded and one sync.succeeded with the count of delivered secrets.

  • No activity within ~30 seconds? Check entitlements and capability, then read AppAttest.state in your UI to surface the current condition.
  • Need to test in the simulator? Set AppAttest.debugMode = .sandbox (real network, no Apple attestation) or .local(stubs: […]) (no network at all). #if DEBUG-gated; stripped from Release.
Dashboard · Recent activity
10 Production

When you're ready, subscribe to go live.

Add production secrets in the production environment. Click Subscribe in the dashboard — subscribing IS going live. Signed-store builds then attest as production and receive production values; debug builds keep getting sandbox values.

That's it.

The keys live in Keychain on the device that attested. They never ship in your binary. Rotate a secret in the dashboard and running apps pick it up within ~15 minutes of foregrounding.

For AI agents — this page is available as markdown:
View markdown