What's new in 3.1

SDK 3.1.0 for iOS and Android adds content commitments, and proofs now bind the region they answer for. The React Native wrapper ships alongside it. 3.1.1 and 3.1.2 change only how the iOS framework is packaged, with no change to the API or to proofs. If you add the framework with Carthage or by hand, set it to Embed & Sign from 3.1.2 (see Carthage). Android is unchanged. The full release notes are in the octet-sdk-ios and octet-sdk-android changelogs, and the 3.0 docs stay at /docs/v3.0/.

What you may need to change

  • Update your verifier to octet-verify 1.8.0 or later. A 3.1 proof uses semantic binding v3, which octet-verify 1.5.0 and later check. Older verifiers fail every 3.1 proof. Checking content commitments needs 1.8.0, built with --features caller-metadata. Update the verifier before your apps ship 3.1. See Verifying a commitment.
  • No confidence score or assurance tier. To keep the answer simple, 3.1 reports neither: confidence holds 0 and empty lists, spoofingVerdict is UNSPECIFIED, and requireVerdict is ignored. Act on result and reason, which don't change. If you need more device intelligence or your own scoring logic, Octet offers it as a custom feature or license. See OctetVerdict.
  • CheckStatus has a new case, inconclusive. A switch (Swift) or when (Kotlin) over CheckStatus without a default branch no longer compiles. Add the case or a default branch. See Octet.verify.
  • isAuthentic is false when a check is INCONCLUSIVE. Today only the content check can be inconclusive, so this changes nothing unless you pass callerMetadata.
  • Handle a license that stops while the app runs. Predicates can now return INDETERMINATE with reason licenseInactive / LICENSE_INACTIVE, and LicenseState has a new case, revoked / REVOKED. A switch (Swift) or when (Kotlin) over ReasonCode or LicenseState without a default branch no longer compiles. On Android, the same goes for a when over BootstrapReason. See License Types.
  • Android: recompile. AdvancedConfig has a new constructor parameter, so code compiled against 3.0 that calls its constructor or copy must be recompiled.

Deprecated

These still work in 3.1 and are removed in 4.0.

  • OctetConfig.licenseKey. Octet.start doesn't use it, so leave it out: OctetConfig() needs no arguments. Code that still passes it builds with a deprecation warning.
  • overallScore, spoofingRiskScore, sensorContributions and flags on ConfidenceSummary, and VerifyOptions.requireVerdict.
  • Octet.creditStatus() and CreditStatus. Usage reporting never refuses, so they always reported that you're not over quota. To detect the free-plan device limit, handle the newDevicesBlocked start error (NEW_DEVICES_BLOCKED in React Native) and open its upgradeUrl. See Handling newDevicesBlocked.

New

  • Content commitments. Pass content to isWithin, isOutside, or contains, and the device signs a commitment to your content (a note, a photo, a video, a document) into the proof. The proof lists the items as contentCommitments. The SDK salts each item by default. Caller content must be enabled for your license. See Content Commitments.
  • Hash large files first. Octet.hashContent hashes a file of any size before the proof call. Pass the result as a digest item.
  • Upload content to your storage. If enabled for your license, the SDK uploads items you mark with upload to your own storage after the proof is made, never to Octet. Register Octet.setContentUploadProvider. See Uploading content.
  • Check content on the device. VerifyOptions.callerMetadata checks a commitment against the content, and requireCallerMetadata fails a proof that commits none. See Octet.verify.
  • Proofs bind the region they answer for (semantic binding v3). A proof can't be presented as the answer to a different region.
  • BootstrapReason.appPendingContested. Octet.start fails with it when another license claims the same app and your pending registration lost that claim. Register the app again, or contact Octet support.
  • Check your session nonce offline. Pass the sessionNonce you asked with as VerifyOptions.expectedSessionNonce. The session-binding check fails a proof made for another nonce, or for none. See Proof Binding.
  • Android: set the location notification. AdvancedConfig.foregroundNotification sets the title, text, icon, channel and tap action of the notification Android shows while the SDK collects location, or lets you build the whole notification. See AdvancedConfig.
  • React Native. @octetproof/react-native 0.1.0, the wrapper's first release, ships with this release and uses native SDK 3.1.0. content on PredicateOpts, Octet.hashContent and content uploads are in the wrapper. Uploads run in the foreground only. Octet.verify stays native-only. See React Native.

Changed

  • A license that is withdrawn or expires stops the running session. Predicates then return INDETERMINATE with reason licenseInactive / LICENSE_INACTIVE and make no proof, and licenseStatus.state reads REVOKED or EXPIRED. The next Octet.start throws a LicenseError.
  • Positions at sea next to Crimea, Sevastopol and the other occupied Ukrainian regions resolve to Ukraine. Within 22 km of their coast, the country is UA and the region is that Ukrainian region.
  • Android dependencies: androidx.work:work-runtime-ktx 2.12.0 and bcprov-jdk18on 1.86. minSdk stays 30.

Fixed

  • The first proof after Octet.start waits for a usable fix. Since 3.0 a proof asked for during startup waits for the SDK to start. Once it had started, a fresh proof used to return noFix / NO_FIX straight away while positioning warmed up. It now waits up to 30 seconds for a usable fix, so allow for this if your app times out its first call.

  • Country proofs work with approximate location. When the user allows only approximate location (Precise Location off on iOS, Approximate on Android), country proofs now work. Finer levels return INSUFFICIENT_PRECISION, and a proof from approximate location is never VERIFIED.

  • Proof uploads ride out a busy server. When your proof upload endpoint answers 503 or 429, the SDK waits as Retry-After asks and keeps retrying, instead of dropping the proof after three quick retries.
  • Proofs you ask for after a pause are uploaded again. The SDK fetches a fresh upload challenge first when the prepared one has expired.
  • iOS: the privacy manifest declares coarse location for Analytics, as well as for App Functionality. Check your App Store privacy label. See Data collection.
  • iOS: Octet.start throws a LicenseError on a device without App Attest, .bootstrapFailed(reason: .attestationInvalid), instead of the system error. See LicenseError.
  • Android: location keeps running while your app is off screen. Collection could fail to start its foreground service after Octet.start, and then stopped when your app left the screen. It now starts reliably, and the SDK restores it each time your app comes on screen.
  • License problems you can fix are written to the device log, so you can see why a start fails.
  • OctetConfig.advanced.logLevel takes effect. See AdvancedConfig.
TermsPrivacy© 2026 Understone, Inc. d/b/a Octet