How it works
On first launch the SDK generates an ECDSA P-256 keypair inside the device’s secure hardware:- iOS — Secure Enclave when present (most iPhones since the 5s), software Keychain otherwise. Requires iOS 13+.
- Android — StrongBox when supported (Pixel 3+, recent Samsung), TEE-backed Keystore otherwise. Requires API 23+ (Marshmallow).
secure_enclave, tee, strongbox, or
software.
React Native + Expo Go: native modules can’t load in Expo Go, so the SDK
transparently falls back to a software ECDSA P-256 key. You can evaluate the
entire flow in Expo Go and ship hardware-backed with no code change. The backend
records the
software attestation either way.The publishable key
You ship one publishable key (pk_live_…) in your app binary. Its only
capability is letting a fresh install register a device. It cannot read tickets,
list users, or impersonate anyone.
If your key leaks, an attacker can register throwaway devices (rate-limited and
bounded) — but they cannot touch any existing user’s data, because every
authenticated call is signed by a private key that never left the original
device’s secure hardware.
You ship the key, your users are secure by default. There is no separate “secure mode” to enable.
Identity is optional metadata
identify({ externalId, email, traits }) attaches your user’s identity to the
device row. It is pure metadata — it grants no access, because access is
already established by the device key. If you never call identify(), tickets
still work; agents just see an “Unverified device” badge instead of an email.
This is why identify() is safe to call unconditionally on every launch — see
Identity & lifecycle.