Documentation Index
Fetch the complete documentation index at: https://turnkey-0e7c1f5b-graham-docs-revamp.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Overview
This guide shows how to implement email or SMS OTP authentication using the Turnkey Swift SDK and the Auth Proxy.
You’ll send an OTP to a user’s contact, present a verification screen, and complete the flow with a single call that handles login or signup.
Before you begin:
- Ensure you’ve completed the setup in Getting Started and enabled the Auth Proxy with Email/SMS OTP in the Turnkey Dashboard.
- Make sure your app is configured with
TurnkeyConfig and TurnkeyContext.configure(...).
Send an OTP code
Create or update your login screen to collect the user’s email. When the user submits the form, call initOtp(contact:otpType:) with the email and .email.
This sends a one-time code to the provided address.
On success, keep the returned otpId along with the email so you can navigate to your OTP screen. In the next section, you’ll verify the code the user enters.
import SwiftUI
import TurnkeySwift
struct LoginView: View {
@EnvironmentObject var turnkey: TurnkeyContext
@State private var email = ""
@State private var errorMessage: String?
var body: some View {
VStack(spacing: 12) {
TextField("you@example.com", text: $email)
.keyboardType(.emailAddress)
.textInputAutocapitalization(.never)
.autocorrectionDisabled()
.frame(height: 48)
.overlay(RoundedRectangle(cornerRadius: 8).stroke(.gray.opacity(0.3)))
Button("Continue with email") {
Task {
guard email.contains("@") else {
errorMessage = "Please enter a valid email"
return
}
do {
let result = try await turnkey.initOtp(contact: email, otpType: .email)
// Navigate to your OTP screen with `email` and `result.otpId`
// Example: OtpScreen(email: email, otpId: result.otpId)
} catch {
errorMessage = "Failed to initialize OTP"
}
}
}
.disabled(!email.contains("@"))
}
.padding()
.alert("Error", isPresented: .constant(errorMessage != nil)) {
Button("OK") { errorMessage = nil }
} message: {
Text(errorMessage ?? "")
}
}
}
Verify the OTP code
On your OTP screen, call completeOtp(...) with the user-entered code.
This will verify the code and automatically complete login or signup as needed.
import SwiftUI
import TurnkeySwift
struct OtpScreen: View {
@EnvironmentObject var turnkey: TurnkeyContext
@Environment(\.dismiss) private var dismiss
let email: String
let otpId: String
@State private var code = ""
@State private var errorMessage: String?
var body: some View {
VStack(spacing: 12) {
TextField("Enter 6-digit code", text: $code)
.keyboardType(.numberPad)
.textContentType(.oneTimeCode)
.multilineTextAlignment(.center)
.frame(height: 48)
.overlay(RoundedRectangle(cornerRadius: 8).stroke(.gray.opacity(0.3)))
.onChange(of: code) { newValue in
code = String(newValue.prefix(6))
}
Button("Verify") {
Task {
guard code.count == 6 else {
errorMessage = "Please enter a 6-digit code"
return
}
do {
_ = try await turnkey.completeOtp(
otpId: otpId,
otpCode: code,
contact: email,
otpType: .email
)
// Navigate to your main app upon success
dismiss()
} catch {
errorMessage = "Invalid code. Please try again."
}
}
}
.disabled(code.count != 6)
}
.padding()
.alert("Error", isPresented: .constant(errorMessage != nil)) {
Button("OK") { errorMessage = nil }
} message: {
Text(errorMessage ?? "")
}
}
}
SMS OTP
For SMS, pass an E.164-formatted phone number and use otpType: .sms:
let result = try await turnkey.initOtp(contact: "+15551234567", otpType: .sms)
// Navigate to your OTP screen with `contact` (phone) and `result.otpId`
Tip: You can use a library like PhoneNumberKit to normalize user input to E.164.
Notes
- Default OTP length is 6; if you’ve customized the OTP length in the dashboard, validate accordingly (up to 9 digits).
- To resend a code, call
initOtp(contact:otpType:) again with the same contact.
Next steps