iOS SDK Usage & Integration
The DoorstepAI SDK has four touchpoints in your driver app. Wire up each one and you're done. Everything else on this page is reference detail for those four calls.
| # | When this happens in the driver app | What you call |
|---|---|---|
| 1 | App launches | Initialize SDK |
| 2 | Driver enters the ≥250 m delivery geofence | Start Tracking |
| 3 | Driver takes POD or confirms drop-off in-app | Mark Drop-off |
| 4 | Driver exits the ≥250 m delivery geofence | Stop Tracking |
1. Initialize SDK
Initialize the SDK once, 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 | n/a | 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)
Request permissions up-front
Trigger Motion/Fitness + Location prompts before the first delivery so they're ready when tracking starts:
// Defaults to requesting "Always" location authorization.
DoorstepAI.requestAllPermissions()
// Use when-in-use only:
DoorstepAI.requestAllPermissions(requestAlwaysLocation: false)
Store your API key securely using environment variables or a secure configuration service. Never hardcode API keys in production builds.
2. Start Tracking
Call startDelivery… when the driver enters the delivery geofence around the target building, not once inside it. Use a unique deliveryId per session: a meaningful identifier you can correlate on your side. Wrap calls in do/catch to handle failures such as an invalid key or denied permissions.
Pick whichever address format you have (startDeliveryByPlaceID, startDeliveryByAddressType, or startDeliveryByAddressString):
Task {
do {
// By Google Place ID
try await DoorstepAI.startDeliveryByPlaceID(
placeID: "some_place_id",
deliveryId: "delivery_12345"
)
// By address components
let address = AddressType(
streetNumber: "123",
route: "Main Street",
subPremise: "Apt 4B",
locality: "San Francisco",
administrativeAreaLevel1: "CA",
postalCode: "94102"
)
try await DoorstepAI.startDeliveryByAddressType(
address: address,
deliveryId: "delivery_12345"
)
// By single address string, with optional coordinates and knobs
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),
timeoutSeconds: 1200
)
} catch {
// Handle invalid key, denied permissions, or bad input
}
}
Start parameters
Every start method takes a deliveryId plus these optional knobs:
| Parameter | Type | Description |
|---|---|---|
deliveryId | String | Required. Unique per session; correlate it on your side |
timeoutSeconds | Int? | Auto-stops tracking after this duration, a backstop if the exit geofence is missed |
autoStopAfterDropoffSeconds | Int? | Auto-stops this many seconds after markDropoff. nil falls back to remote config; 0 or negative disables auto-stop |
coordinates | LatLngObject? | (AddressType / address-string variants only) pairs a textual address with a lat/lng you resolved upstream |
customerId | String? | Optional customer identifier passed through to session creation, for correlation on your backend |
driverId | String? | Optional driver identifier passed through to session creation, for correlation on your backend |
Deprecated start methods
startDeliveryByPlusCode and startDeliveryByLatLng are deprecated. Use startDeliveryByAddressString / startDeliveryByAddressType with coordinates instead. They remain for backwards compatibility:
try await DoorstepAI.startDeliveryByPlusCode(
plusCode: "some_plus_code",
deliveryId: "delivery_12345",
timeoutSeconds: 1200
)
try await DoorstepAI.startDeliveryByLatLng(
latitude: 37.7749,
longitude: -122.4194,
subUnit: "Apt 4B",
deliveryId: "delivery_12345",
timeoutSeconds: 1200
)
3. Mark Drop-off
When the driver completes the delivery (takes a POD or confirms drop-off in-app), mark it. markDropoff is the preferred API:
Task {
do {
try await DoorstepAI.markDropoff(
deliveryId: "delivery_12345",
dropoffType: .pod // or .non_pod
)
} catch {
// Handle error
}
}
markDropoff parameters
| Parameter | Type | Description |
|---|---|---|
deliveryId | String | Required. The session you're marking |
dropoffType | DropoffType | .pod (proof of delivery captured) or .non_pod |
Custom Events
Use newEvent to record a custom event on a delivery:
Task {
try await DoorstepAI.newEvent(
eventName: "taking_pod",
deliveryId: "delivery_12345"
)
}
4. Stop Tracking
Call stopDelivery when the driver exits the delivery geofence surrounding the building, not while inside it:
Task {
await DoorstepAI.stopDelivery(deliveryId: "delivery_12345")
}
That covers the full lifecycle. The sections below are reference for the calls above.
Advanced APIs
SwiftUI root component (legacy)
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 {
Text("Welcome to My Delivery App")
DoorstepAIRoot() // optional legacy root component
}
}
}
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
)
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
- Always handle errors. Wrap
startDelivery*/markDropoffindo/catchand surface invalid-key, denied-permission, and bad-input failures to the user. - Update UI on the main thread. SDK calls run in
Tasks; hop back to the main actor before touching UI. - Let tracking run in the background. The SDK handles backgrounding automatically, so don't stop a delivery just because the app is backgrounded. Only call
stopDeliveryon geofence exit (or rely ontimeoutSecondsas a backstop).
Next Steps
- 💡 View Examples: complete implementation examples with error handling