iOS SDK Usage & Integration
Learn how to initialize the DoorstepAI SDK and integrate delivery tracking into your iOS application.
SDK Initialization
Basic Setup
Initialize the SDK early in your app's lifecycle, typically in your App struct or AppDelegate:
import SwiftUI
import DoorstepDropoffSDK
@main
struct MyApp: App {
init() {
// Initialize DoorstepAI with your API key.
// The SDK kicks off a config fetch immediately by default.
DoorstepAI.setApiKey(key: "YOUR_API_KEY_HERE")
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
setApiKey Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
key | String | — | JWT issued by DoorstepAI; sent as Authorization: Bearer <key> |
initCollectors | Bool | true | Eagerly initialize collector singletons so the first startDelivery* is faster |
shouldGetConfig | Bool | true | When true, fetch config immediately. When false, defer until the first startDelivery* call |
// Defer config fetch until the first delivery starts:
DoorstepAI.setApiKey(key: "YOUR_API_KEY_HERE", shouldGetConfig: false)
Requesting Permissions Up-Front
Trigger Motion/Fitness + Location permission prompts before the first delivery:
// Defaults to requesting "Always" location authorization.
DoorstepAI.requestAllPermissions()
// Use when-in-use only:
DoorstepAI.requestAllPermissions(requestAlwaysLocation: false)
SwiftUI Integration
For SwiftUI applications, you can render the SDK root component for legacy support. This is no longer required for new integrations; tracking starts when you call startDelivery*.
import SwiftUI
import DoorstepDropoffSDK
struct ContentView: View {
var body: some View {
VStack {
// Your app content
Text("Welcome to My Delivery App")
// Optional legacy root component
DoorstepAIRoot()
}
}
}
Store your API key securely using environment variables or a secure configuration service. Never hardcode API keys in production builds.
Core Functionality
Delivery IDs are designed to be unique identifiers for each delivery session. Use meaningful, unique identifiers that help you track and manage your deliveries effectively.
Starting Delivery Tracking
The SDK provides multiple methods to start delivery tracking based on different address formats.
Every start method accepts two optional safety knobs:
timeoutSeconds— auto-stops tracking after the given duration, as a backstop in case an exit geofence is missed.autoStopAfterDropoffSeconds— auto-stops tracking the given number of seconds aftermarkDropoffis called. Ifnil, the SDK falls back to the value in remote config; if0or negative, no auto-stop is scheduled.
The AddressType and address-string variants additionally accept coordinates: LatLngObject? so you can pair a textual address with the lat/lng you already resolved upstream.
1. Start by Place ID
Task {
do {
try await DoorstepAI.startDeliveryByPlaceID(
placeID: "some_place_id",
deliveryId: "delivery_12345",
timeoutSeconds: 1200, // optional
autoStopAfterDropoffSeconds: 600 // optional
)
print("✅ Delivery started successfully")
// Handle successful start
} catch {
print("❌ Failed to start delivery: \(error.localizedDescription)")
// Handle error
}
}
Execute startDelivery... when the driver enters the delivery geofence around the target building. Do not start inside the building.
2. Start by Address Components
let address = AddressType(
streetNumber: "123",
route: "Main Street",
subPremise: "Apt 4B",
locality: "San Francisco",
administrativeAreaLevel1: "CA",
postalCode: "94102"
)
Task {
do {
try await DoorstepAI.startDeliveryByAddressType(
address: address,
deliveryId: "delivery_12345",
coordinates: LatLngObject(lat: 37.7749, lng: -122.4194), // optional
timeoutSeconds: 1200, // optional
autoStopAfterDropoffSeconds: 600 // optional
)
print("✅ Address delivery started")
} catch {
print("❌ Address delivery failed: \(error.localizedDescription)")
}
}
3. Start by Address String
Task {
do {
try await DoorstepAI.startDeliveryByAddressString(
address: "123 Main St, Apt 4B, San Francisco, CA 94102",
deliveryId: "delivery_12345",
coordinates: LatLngObject(lat: 37.7749, lng: -122.4194), // optional
timeoutSeconds: 1200, // optional
autoStopAfterDropoffSeconds: 600 // optional
)
print("✅ Address string delivery started")
} catch {
print("❌ Address string delivery failed: \(error.localizedDescription)")
}
}
Deprecated: Start by Plus Code
startDeliveryByPlusCode is deprecated. Use startDeliveryByAddressString (or startDeliveryByAddressType) and pass coordinates if you have them.
// Deprecated — kept for backwards compatibility.
try await DoorstepAI.startDeliveryByPlusCode(
plusCode: "some_plus_code",
deliveryId: "delivery_12345",
timeoutSeconds: 1200
)
Deprecated: Start by Lat/Lng
startDeliveryByLatLng is deprecated. Use startDeliveryByAddressString or startDeliveryByAddressType with the coordinates parameter instead.
// Deprecated — kept for backwards compatibility.
try await DoorstepAI.startDeliveryByLatLng(
latitude: 37.7749,
longitude: -122.4194,
subUnit: "Apt 4B",
deliveryId: "delivery_12345",
timeoutSeconds: 1200
)
Recommended Geofence Settings
- Use both an enter and exit geofence to bound the delivery session.
- A radius of 250m or larger typically yields the best results.
Delivery Events
Track important delivery milestones using event reporting:
Mark Dropoff (POD or non-POD)
Task {
do {
try await DoorstepAI.markDropoff(
deliveryId: "delivery_12345",
dropoffType: .pod // or .non_pod
)
print("✅ Dropoff marked")
} catch {
print("❌ Dropoff mark failed: \(error.localizedDescription)")
}
}
// NOTE: The previous methods of marking a dropoff still work as expected.
Task {
do {
try await DoorstepAI.newEvent(
eventName: "taking_pod",
deliveryId: "delivery_12345"
)
print("Event sent")
} catch {
print("Event send failed: \(error.localizedDescription)")
}
}
Stopping Delivery Tracking
Stop tracking when the delivery is complete:
// Stop delivery tracking
Task {
await DoorstepAI.stopDelivery(deliveryId: "delivery_12345")
print("🛑 Delivery tracking stopped")
}
Execute stopDelivery(...) when the driver exits the delivery geofence surrounding the building. Do not stop inside the building.
Address Types Reference
AddressType Structure
public struct AddressType {
public let streetNumber: String
public let route: String
public let subPremise: String
public let locality: String
public let administrativeAreaLevel1: String
public let postalCode: String
public init(streetNumber: String, route: String, subPremise: String, locality: String, administrativeAreaLevel1: String, postalCode: String)
}
LatLngObject
Pairs a textual address with the lat/lng you already resolved upstream. Pass it as the coordinates: argument on startDeliveryByAddressType or startDeliveryByAddressString.
public struct LatLngObject: Codable, Sendable {
public let lat: Double
public let lng: Double
public init(lat: Double, lng: Double)
}
Usage Examples
// Minimal address
let simpleAddress = AddressType(
streetNumber: "456",
route: "Oak Avenue",
subPremise: "",
locality: "Oakland",
administrativeAreaLevel1: "CA",
postalCode: "94610"
)
// Complete address with apartment
let detailedAddress = AddressType(
streetNumber: "789",
route: "Pine Street",
subPremise: "Suite 100",
locality: "Berkeley",
administrativeAreaLevel1: "California",
postalCode: "94704"
)
Advanced APIs
Remote Logging
Stream SDK logs to DoorstepAI for support investigations:
DoorstepAI.configureRemoteLogging(
enabled: true,
minLevel: .warning, // .debug, .info, .warning, .error
flushInterval: 30, // seconds
batchSize: 50,
maxQueueSize: 1000
)
Dev Mode
Enable dev mode after validating the API token. Returns once validation completes; DoorstepAI.devMode flips to true if the token has dev privileges.
Task {
await DoorstepAI.enableDevMode(apiKey: "YOUR_API_KEY")
if DoorstepAI.devMode {
print("✅ Dev mode active")
}
}
Background URLSession Completion Handler
If you've enabled background uploads, forward the system's completion handler from AppDelegate:
func application(
_ application: UIApplication,
handleEventsForBackgroundURLSession identifier: String,
completionHandler: @escaping () -> Void
) {
DoorstepAI.setBackgroundSessionCompletionHandler(completionHandler)
}
Best Practices
1. Error Handling
Always implement proper error handling for SDK methods:
func startDeliveryWithErrorHandling(placeID: String, deliveryId: String) {
Task {
do {
try await DoorstepAI.startDeliveryByPlaceID(
placeID: placeID,
deliveryId: deliveryId
)
// handle success
} catch {
// handle error
}
}
}
2. Lifecycle Management
Handle app lifecycle changes appropriately:
class DeliveryManager: ObservableObject {
func startDelivery(placeID: String, deliveryId: String) {
Task {
do {
try await DoorstepAI.startDeliveryByPlaceID(
placeID: placeID,
deliveryId: deliveryId
)
// Handle success
} catch {
// Handle error
}
}
}
func handleAppWillEnterBackground() {
// SDK automatically handles background processing
// No additional action required
}
}
3. Thread Safety
Always update UI on the main thread:
private func handleDeliveryCallback() {
Task {
do {
try await DoorstepAI.startDeliveryByPlaceID(
placeID: placeID,
deliveryId: deliveryId
)
// handle success
} catch {
// handle error
}
}
}
Next Steps
Now that you have the SDK installed and configured:
- 📚 Learn SDK Usage - Initialize and use the SDK
- 💡 View Examples - See complete implementation examples