iOS
Integrate Phonelink phone verification in native iOS apps with Swift.
Overview
The PhoneLink Swift SDK uses ASWebAuthenticationSession for secure in-app verification. The user stays within your app — PhoneLink opens a system-managed browser session, the user verifies their phone number, and the result is returned directly via a completion handler.
Install
Swift Package Manager
Add the dependency to your Package.swift:
dependencies: [
.package(url: "https://github.com/phonelink-sdk/phonelink-swift.git", from: "0.1.0")
]Or in Xcode: File > Add Package Dependencies and enter the repository URL.
CocoaPods
pod 'PhoneLink', '~> 0.1.0'Then run pod install.
Basic usage
1. Configure
Add PhoneLink.configure to your AppDelegate or App init. Call this once at launch before any verification calls.
import PhoneLink
PhoneLink.configure("your-client-id")2. Verify
Call PhoneLink.verify to start the verification flow. The SDK opens a secure browser session where the user enters and verifies their phone number.
PhoneLink.verify { result in
if let phone = result.phoneNumber, let token = result.token {
// Send token to your server for validation
print("Verified: \(phone)")
} else if let error = result.error {
print("Error: \(error)")
}
}How it works
When you call PhoneLink.verify:
- The SDK opens the Phonelink verification page in an
ASWebAuthenticationSession - The user enters their phone number and completes verification
- Phonelink redirects back to your app with a signed JWT token
- The browser session closes and the completion handler fires with a
PhoneLinkResult
The result contains the verified phoneNumber in E.164 format and a signed token for server-side validation.
Prefilled phone number
If you already have the user's phone number, skip the number entry screen by passing it directly:
PhoneLink.verify(phoneNumber: "+14155551234") { result in
if let token = result.token {
// Send token to your server
}
}The user will go straight to the verification code screen.
Error handling
The PhoneLinkResult.error property contains a PhoneLinkError if something went wrong:
PhoneLink.verify { result in
if let error = result.error {
switch error {
case .notConfigured:
print("Call PhoneLink.configure() before verifying")
case .cancelled:
print("User dismissed the verification screen")
case .missingToken:
print("Verification completed but no token was returned")
case .sessionFailed(let underlying):
print("Auth session failed: \(underlying.localizedDescription)")
}
return
}
// Success
print("Phone: \(result.phoneNumber ?? "unknown")")
}Full example
A complete SwiftUI view with state management:
import SwiftUI
import PhoneLink
struct PhoneVerificationView: View {
@State private var phone: String?
@State private var error: String?
@State private var isVerifying = false
var body: some View {
VStack(spacing: 16) {
if let phone {
Text("Phone verified: \(phone)")
} else {
if let error {
Text(error)
.foregroundStyle(.red)
}
Button(action: handleVerify) {
if isVerifying {
ProgressView()
} else {
Text("Verify Phone Number")
}
}
.disabled(isVerifying)
}
}
}
private func handleVerify() {
isVerifying = true
error = nil
PhoneLink.verify { result in
DispatchQueue.main.async {
isVerifying = false
if let err = result.error {
if case .cancelled = err { return }
error = "Verification failed. Try again."
return
}
guard let token = result.token else { return }
Task {
do {
var request = URLRequest(url: URL(string: "https://api.myapp.com/verify-phone")!)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try JSONEncoder().encode(["token": token])
let (data, _) = try await URLSession.shared.data(for: request)
let response = try JSONDecoder().decode(VerifyResponse.self, from: data)
phone = response.phone
} catch {
self.error = "Server verification failed. Try again."
}
}
}
}
}
}
struct VerifyResponse: Decodable {
let phone: String
}Server verification
The result.token contains a signed JWT that should be validated on your server before trusting the phone number. The server-side verification is identical across all platforms — see the Server Verification guide.
Requirements
- iOS 15.0+
- Swift 5.9+
- Xcode 15+