Skip to main content

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 appWhat you call
1App launchesInitialize SDK
2Driver enters the ≥250 m delivery geofenceStart Tracking
3Driver takes POD or confirms drop-off in-appMark Drop-off
4Driver exits the ≥250 m delivery geofenceStop Tracking

1. Initialize SDK

Initialize the SDK once, early in your app's lifecycle, typically in your App struct or AppDelegate.

MyApp.swift
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

ParameterTypeDefaultDescription
keyStringn/aJWT issued by DoorstepAI; sent as Authorization: Bearer <key>
initCollectorsBooltrueEagerly initialize collector singletons so the first startDelivery* is faster
shouldGetConfigBooltrueWhen 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)
API Key Security

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:

ParameterTypeDescription
deliveryIdStringRequired. Unique per session; correlate it on your side
timeoutSecondsInt?Auto-stops tracking after this duration, a backstop if the exit geofence is missed
autoStopAfterDropoffSecondsInt?Auto-stops this many seconds after markDropoff. nil falls back to remote config; 0 or negative disables auto-stop
coordinatesLatLngObject?(AddressType / address-string variants only) pairs a textual address with a lat/lng you resolved upstream
customerIdString?Optional customer identifier passed through to session creation, for correlation on your backend
driverIdString?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

ParameterTypeDescription
deliveryIdStringRequired. The session you're marking
dropoffTypeDropoffType.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*.

ContentView.swift
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* / markDropoff in do/catch and 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 stopDelivery on geofence exit (or rely on timeoutSeconds as a backstop).

Next Steps

  1. 💡 View Examples: complete implementation examples with error handling