Docs/Concepts/License & Activation

License & Activation

In one sentence

A license key unlocks the SDK. It is verified on the first call to Octet.start(...) and the SDK works from a local cache afterwards.

Getting a license

Free license keys are issued via sdk.octetproof.com/signup. The free tier covers up to 1,000 signed proofs per month, per key. Paste the key into OctetConfig.licenseKey and call Octet.start(...). Nothing else is required.

Use of the SDK is governed by the Mobile SDK terms. The current terms live at /terms/mobile/; a dated snapshot lives at /terms/mobile/vMM.DD.YYYY/.

The first call activates the license over the network. Subsequent launches read from a local cache. The SDK does not contact the activation backend again until the license needs to renew.

Validity

License keys renew automatically. The free tier covers up to 1,000 signed proofs per month, per key, and resets each month; beyond that, proofs are billed per signed proof. You should not need to replace a working key.

Install on as many devices as you like. There is no per-license device cap.

License states

stateDiagram-v2
    [*] --> NOT_ACTIVATED: license verified locally
    NOT_ACTIVATED --> ACTIVE: activation succeeds
    ACTIVE --> RENEWAL_RECOMMENDED: < 30 days to expiry
    ACTIVE --> GRACE_PERIOD: past 90-day validity window
    RENEWAL_RECOMMENDED --> GRACE_PERIOD: same trigger
    GRACE_PERIOD --> EXPIRED: past grace period
    NOT_ACTIVATED --> INVALID: signature / server reject
    ACTIVE --> INVALID: server reject
    EXPIRED --> [*]
    INVALID --> [*]

Read the state at any time:

// iOS
if let status = sdk.licenseStatus {
    print("state: \(status.state), days left: \(status.daysUntilHardStop ?? -1)")
}
// Android
sdk.licenseStatus?.let { status ->
    println("state: ${status.state}, days left: ${status.daysUntilHardStop ?: -1}")
}

LicenseStatus.state drives in-app UI only. It never drives the cryptographic gate. Forcing state = ACTIVE in your own code accomplishes nothing.

Failure modes

Octet.start(...) throws a typed LicenseError. The complete taxonomy is in License Types. The common cases:

  • MalformedKey. The key isn't a valid signed token. Fix: re-copy the key.
  • NoActivation. First launch, and the device is offline. Fix: retry when network returns.
  • Expired. License past the grace period. Fix: request a new key.
  • ActivationWindowClosed. A fresh device tries to activate after the 90-day window. Fix: request a new key.
  • Revoked. Admin revoke (key leaked, abuse). Fix: contact support.
  • Network(message:). Transient. Fix: retry.
  • ServerRejected(httpStatus:, reason:). Anything else from the backend. Fix: see reason.

Usage telemetry

The SDK reports aggregate, privacy-preserving usage counters to the license backend, indexed by your license: how many proofs were generated, uploaded, or could not be produced, by coarse level and region type. The counters carry no location data: no coordinates, no region IDs, no proof contents. They are buffered in an encrypted file in the app's private storage and uploaded at most once a day.

It is on by default. Disable it with telemetryEnabled = false on OctetConfig. Disabling deletes any buffered file.

Where to go next