Skip to main content
ChappieSignIn is the primary way to let users authenticate with their ChatGPT account. Drop it into any SwiftUI view alongside your ChappieAuthSession and the button handles the entire device-code flow — requesting the code, copying it to the clipboard, opening the verification URL, and polling for approval — all with an optional onboarding sheet that walks the user through each step.

Basic usage

Attach your authSession and apply any standard SwiftUI button modifiers:
@StateObject private var authSession = Chappie.authSession()

var body: some View {
    ChappieSignIn(authSession: authSession)
        .buttonStyle(.borderedProminent)
        .padding()
}
The button disables itself while sign-in is in progress and hides once the user is signed in, so no additional conditional logic is required.
ChappieSignIn requests notification permission before starting the device-code flow by default. When the user approves the device code in their browser, the SDK fires a local notification — “ChatGPT Linked! Return to the app” — so they know it’s time to switch back.

Onboarding sheet

By default ChappieSignIn presents a built-in sheet that guides users through three steps:
  1. Open OpenAI — a button that launches the verification URL in Safari
  2. Continue with ChatGPT — a reminder to tap Continue when prompted
  3. Paste your device code — the device code displayed in a tap-to-copy chip
This sheet is the recommended experience for most apps because it eliminates the need for custom instructions.

Handling the device code yourself

If you want to integrate the device code into your own UI — for example, to display it inline or deep-link into a custom web view — disable the onboarding sheet and receive the code in the onDeviceCode closure:
ChappieSignIn(
    authSession: authSession,
    showsOnboardingSheet: false,
    onDeviceCode: { deviceCode in
        print("User code:", deviceCode.userCode)
        print("Verification URL:", deviceCode.verificationURL)
    }
)
The button opens the verification URL automatically when showsOnboardingSheet is false. You can use onDeviceCode to update your own UI state at the same time.

Controlling notification permission

ChappieSignIn asks for notification permission the first time the button is tapped. You can suppress this if your app manages notification permission elsewhere:
ChappieSignIn(
    authSession: authSession,
    requestsNotificationPermission: false
)
When you opt out, the SDK still sends the “ChatGPT Linked” local notification if permission was already granted through another code path.

Custom label

Provide a label closure to replace the default ChappieSignInLabel with any SwiftUI view. The closure receives the button’s current title string so you can incorporate it into your own layout:
ChappieSignIn(authSession: authSession) { title in
    Label(title, systemImage: "person.badge.plus")
        .font(.headline)
}
The title string updates automatically as sign-in progresses — "Sign in with ChatGPT""Preparing sign in""Open ChatGPT sign in".

Legacy wrapper: SignInWithChatGPTButton

SignInWithChatGPTButton is a pre-styled wrapper around ChappieSignIn that fills the available width and applies a bold font. It is still available for compatibility, but new code should use ChappieSignIn directly for full control over layout and customisation.
SignInWithChatGPTButton(authSession: authSession)

Manual device-code flow

For advanced scenarios — custom authentication screens, command-line tooling, or integration tests — you can start the device-code flow directly without using any button:
let deviceCode = try await authSession.startDeviceCodeSignIn()

// Present these to the user however you like:
print("User code:", deviceCode.userCode)
print("Verification URL:", deviceCode.verificationURL)

// Then watch state or deviceLinkState for completion:
// authSession.state → .signedIn(expiresAt:)
// authSession.deviceLinkState → .linked(expiresAt:)
startDeviceCodeSignIn() returns as soon as the device code is ready. Background polling starts immediately — you don’t need to call anything else. Observe authSession.state or authSession.deviceLinkState to detect when the user approves the code.

ChappieDeviceLinkState values

CaseMeaning
.idleNo sign-in is in progress
.requestingCodeThe SDK is requesting a device code from OpenAI
.awaitingUserCode(ChappieDeviceCode)The device code is ready and waiting to be presented to the user
.polling(ChappieDeviceCode)The SDK is polling OpenAI to check whether the user has approved the code
.linked(expiresAt:)Sign-in succeeded; the credential is stored in Keychain
.expiredThe device code expired before the user approved it
.cancelledSign-in was cancelled
.failed(ChappieAuthError)An error occurred during the device-code exchange
deviceLinkState gives you finer-grained progress than state. Use it when you want to show a progress indicator that distinguishes between requesting the code, waiting for user action, and active polling.

Full initialiser reference

ChappieSignIn(
    authSession: authSession,                       // Required
    showsOnboardingSheet: true,                     // Default: true
    requestsNotificationPermission: true,           // Default: true
    onDeviceCode: nil                               // Default: nil
)