Dashboard

iOS SDK

Sentriq is the native Swift client SDK for iOS — a thin wrapper over the same public-key POST /v1/events ingestion contract @sentriq/browser uses. It never invents a new backend endpoint, auth scheme, or event schema. Targets iOS 15+, Swift 5.9+, distributed via Swift Package Manager only.

Requirements

  • iOS 15.0 or later
  • Swift 5.9 or later (Swift Concurrency required)
  • Xcode with Swift Package Manager

Install (Swift Package Manager)

Not yet published to a package registry or a standalone git repository — add it as a local path dependency against a checked-out commit of this repository until a release process exists:

dependencies: [
    .package(path: "../sentriq/sdks/ios")
]

No CocoaPods support is provided — SwiftPM is Apple's own current first-party dependency manager and covers every currently-maintained iOS project.

Configure

import Sentriq

let options = SentriqOptions(publicKey: "pub_test_xxx")
try Sentriq.configure(options)

Call this once, typically in your App's init() or your AppDelegate's application(_:didFinishLaunchingWithOptions:). Safe to call again later (the latest call wins) — there is no hidden one-time-only guard.

Never embed a secret key in a mobile app
Anything inside a shipped app binary is public. SentriqOptions has no secret-key field at all; passing one throws SentriqError.configuration immediately.

Track an event

func handleLogin(userId: String) async {
    do {
        let result = try await Sentriq.track(
            .login,
            account: SentriqAccountReference(id: userId),
            screenName: "login-screen"
        )
        // result.risk.decision: "allow" | "monitor" | "challenge" | "block"
    } catch {
        // SentriqError.network, .timeout, .api, .validation, ...
    }
}

track is async throws — Swift Concurrency, not a callback. screenName is optional and analogous to a browser's window.location.pathname: it becomes part of a synthetic app:// URL sent as page.url, since a native app has no real page URL concept. Or use the underlying client directly for multi- instance/testing scenarios:

let client = try SentriqClient(options: options)
let result = try await client.track(.pageView)

Account association

Pass account: SentriqAccountReference(id: ...) to track() once you know who the current user is — your own opaque reference for them, never a password or email. Omit it entirely for anonymous events (e.g. a pre-login page view).

Device, session, and installation identity

Handled automatically — you never construct these yourself. An SDK-generated, random installation identifier (never a hardware ID) persists in the Keychain across app launches and resets on reinstall. A session identifier renews after 30 minutes of inactivity. See the Browser SDK's privacy notes for the shared design; the full field-by-field detail lives in docs/architecture/MOBILE_SDK_FOUNDATION.md in the repository.

Concurrency

SentriqClient is a Swift actor — every method is safe to call concurrently from multiple tasks without any locking of your own. Networking never runs on the main actor.

Error handling

switch error {
case let sentriqError as SentriqError:
    switch sentriqError {
    case .configuration(let message): // bad SDK usage — fix your code
    case .network, .timeout: // couldn't reach the server
    case .cancelled: // the enclosing Task was cancelled
    case .decoding: // unexpected response shape
    case .api(let status, let code, let message, let requestId):
    case .validation(let status, let code, let message, let requestId, let fields):
    }
default:
    break
}

Custom API URL (local/dev)

let options = SentriqOptions(
    publicKey: "pub_test_xxx",
    apiURL: URL(string: "http://localhost:8000")!
)

Privacy

This SDK never reads IMEI, MAC address, hardware serial number, or any advertising identifier. It collects only permission-free device signals (locale, timezone, screen metrics, CPU/memory counts) plus the SDK-generated installation and session identifiers described above. No consent-gating mechanism exists in this SDK — the same as the Browser SDK, which has none either; if your app needs one, gate your own call to Sentriq.configure/track.

Simulator and device notes

Works identically in the iOS Simulator and on a real device — both have real Keychain and UIKit access.

Troubleshooting

  • SentriqError.configuration on configure — check your public key matches pub_(test|live)_...; a sec_... secret key or a malformed string is rejected client-side.
  • Requests time out locally — if testing against localhost, remember the Simulator shares your Mac's network directly; a physical device needs a reachable LAN address instead.

Limitations

  • No React Native, Flutter, or Expo wrapper — this is the native Swift SDK only.
  • No optional browser-only signals (private-browsing detection, DOM interaction telemetry) — no equivalent concept exists on iOS.