getSession() when the user performs a sensitive action, and POST the sealed token to your backend for verification.
The mobile SDKs are currently in private beta. Contact support for access credentials and distribution instructions.
Requirements
- iOS 14+, macOS 11+, tvOS 14+, or Mac Catalyst 14+
- Swift 5.9+
- Xcode 15+
Install
Add Tripwire as a Swift Package Manager dependency. While the SDK is in private beta, add it by local path:https://github.com/abxy-labs/tripwire-ios and pin a release tag.
Configure on startup
Configure once at app launch — typically from yourApp initializer — so signal collection is running by the time the first screen appears.
TripwireConfiguration
| Field | Default | Description |
|---|---|---|
publishableKey | — | Required. Must start with pk_live_ or pk_test_. Secret keys (sk_*) are rejected at configure-time. |
enableBehavioralSignals | true | CoreMotion sampling and opt-in touch observers. |
enableAntiTamper | true | Jailbreak, debugger, simulator, and hook-detection signals. |
enableHiddenWebView | true | Enables the attach(to:) handoff so an in-app WKWebView shares this session. |
enableCloudIdentifier | false | Opt-in iCloud KVS continuity hint. Requires the iCloud Key-Value Store entitlement on your app to survive reinstall. |
Get a session at action time
CallgetSession() from an async context right before the sensitive action — not on app launch.
SessionHandoff is a small value type:
sessionIdis stable for the life of the client.sealedTokenis fresh on every call. Send the most recent one to your backend.- The SDK never surfaces verdicts, scores, or visitor IDs to the device — verify on your server.
Behavioral capture
Touch-stroke dynamics are opt-in per screen. CallobserveTouches(on:) once the view is mounted.
UIViewRepresentable wrapper to expose the underlying UIView.
WebView correlation
If your app hosts Tripwire-protected web content in aWKWebView, attach it so the web SDK reuses the native session.
window.__TRIPWIRE_NATIVE__, which the browser SDK picks up when loaded inside the WebView.
API reference
| Method | Description |
|---|---|
TripwireClient.shared.configure(_:) | Validates the publishable key and starts the runtime. Throws TripwireError on invalid input. |
TripwireClient.shared.getSession() async throws -> SessionHandoff | Flushes pending observations and returns a sealed handoff. Every call produces a fresh sealedToken. |
TripwireClient.shared.waitForFingerprint() async throws | Resolves when the durable visitor fingerprint is ready. Optional — getSession() works without it. |
TripwireClient.shared.observeTouches(on:contextId:) | Attaches a non-consuming gesture recognizer to the view. Call once per screen. |
TripwireClient.shared.attach(to:) | Shares the current session with a hosted WKWebView. |
TripwireClient.shared.destroy() | Stops timers and releases resources. Rarely needed outside tests. |
Error handling
TripwireError is a Sendable struct carrying a stable code, a human-readable message, an optional underlying error, and a retryable flag.
| Code | Retryable | When it happens |
|---|---|---|
config.invalid_publishable_key | no | publishableKey is missing, uses the sk_* secret prefix, or doesn’t match pk_live_* / pk_test_*. |
client.not_configured | no | A client method was called before configure(_:). |
session.create_failed | varies | Session handshake with the Tripwire API failed. |
session.handshake_expired | no | The server expired the session. Call configure(_:) again to mint a new one. |
transport.batch_post_failed | varies | A signal batch upload failed. |
transport.rate_limited | yes | HTTP 429 from the API. Back off and retry. |
transport.upgrade_required | no | HTTP 410/426. The SDK version is too old — upgrade the app. |
transport.network | yes | DNS, TLS, or connectivity failure. |
crypto.failure | no | A crypto primitive failed. Usually a platform issue worth reporting. |
internal | no | Unexpected state. File a support ticket with the message and underlying error. |
code values are stable. Category prefixes (config.*, transport.*) are safe to branch on with a wildcard — new codes within a category keep the same retry semantics.
Fallback policy
If Tripwire fails, your app should still work. Log the error and continue without a handoff.Best practices
- Configure once at launch so signals are collecting before any screen opens.
- Call
getSession()late — right before the sensitive action, from an async context. - Degrade gracefully — never block the user if the SDK fails to produce a handoff.
- Reuse the shared client —
TripwireClient.sharedis a process-wide singleton.
What’s next
Server verification
Verify the sealed token on your backend
Browser SDK
Equivalent guide for the web surface
Android SDK
Native Android integration
Going to production
Rollout checklist and monitoring