Docs / Licensing
Licensing
Trial and production licences, app-ID binding, online activation and offline licence files. Licences are signed tokens verified on the device.
How licences work
A Facevity licence is a signed token (JWS, ES256: ECDSA P-256 with SHA-256). The SDK verifies it on the device with a public key it ships with, so no network call is ever made on the frame path. The token states which apps may use it, which features are enabled and when it expires.
Licence requests never carry camera images, landmarks or biometrics. Online activation and refresh send only the licence key or token, your app ID, its signing-certificate SHA-256, a random per-install ID and the SDK version. This happens at activation, about once a day to refresh, and on deactivation.
Licence types
| Trial | Production | |
|---|---|---|
| Issued by | The Facevity team, on request | The Facevity team, under a licence agreement |
| Length | 1 to 90 days | One year by default |
| Watermark | “Facevity Trial” on processed frames (can be turned off on request) | None |
| Installs | Device-capped (5 by default) | Set per licence (or unlimited) |
| Bound to | Your Android package names | Your package names, optionally your signing certificates |
Trial to production. When you upgrade, the same key, app IDs and activations carry over; the watermark is removed and a new expiry is set. Installed apps pick it up at their next refresh (within about a day). No new key and no app update are needed.
When a trial ends. Once the token expires, effects stop and “Facevity trial expired” is drawn on frames.
Licence features
Each licence lists the features it enables. A feature that is missing is simply ignored at render time; the rest keeps working. During unlicensed evaluation (watermarked), segmentation, makeup and accessories are available so you can try them.
| Feature | Enables |
|---|---|
beauty.basic |
Effects without watermark: skin smoothing, tone, eyes, teeth whitening, the natural lip boost, colour filters and backlight compensation |
beauty.reshape |
Slim face, jaw (V-line) and eye enlarging |
buffer.path |
NV21, NV12 and I420 input |
beauty.segmentation |
Pixel-level skin and hair segmentation for the masks (0.2) |
beauty.makeup |
Lipstick shades and finish (0.3) |
ar.props |
AR accessories (0.3.1) |
Existing licences need the new features added before an app can use them in production; tell us which ones you need. fv.capabilities() reflects the licence, so your app can hide controls for features it does not have.
App-ID binding
Each licence lists the Android package names it is valid for (and iOS bundle IDs for the future iOS SDK). Matching is exact. A licence can also pin signing-certificate SHA-256 fingerprints, as printed by:
apksigner verify --print-certs app-release.apk
# or
keytool -list -v -keystore release.jks -alias <alias>
A per-licence option, Allow debug/dev builds (off by default), also accepts <your id>.dev, .debug and .dev.debug so your debug variants work during development. Those variants are not certificate-pinned. Listing every variant explicitly always works too.
Option 1: online activation
val fv = Facevity.initialize(context, FacevityOptions.Builder()
.licenseServerUrl("https://<licence server from your trial>")
.offlineGraceDays(7) // 1..30, default 7
.build())
fv.activateLicense("FV-XXXX-XXXX-XXXX-XXXX") { info ->
// called on a background thread
if (info.status != LicenseStatus.VALID) Log.w("App", "Facevity: ${info.status}")
}
Activate once per install. The token is cached and refreshed in the background about once a day. If the device is offline, the cached token keeps working for the grace period (7 days by default).
Option 2: offline licence file
For apps that cannot reach a licence server, we issue a signed .fvl file for one app ID, valid until the licence’s expiry and not bound to a device. Ship it at:
app/src/main/assets/facevity/license.fvl
It is loaded automatically at initialize(). Or load it yourself:
fv.setLicenseFile(context.assets.open("licences/facevity.fvl"))
Any edit to the file breaks its signature. Revocation cannot reach air-gapped apps, so offline files are usually issued with shorter expiries.
Option 3: token from your backend
If your backend fetches the token for your app, pass it straight in:
fv.setLicenseToken(token)
What the SDK checks
All checks run locally, in this order: signature by a trusted key → key environment → issuer → app ID in the allowed list → signing certificate (if pinned) → install binding (device-capped licences) → validity dates → offline grace. Release (non-debuggable) builds reject development-environment tokens.
What happens without a valid licence
| Situation | Result |
|---|---|
| Valid trial | Effects + “Facevity Trial” watermark |
| Valid production licence | Effects, no watermark |
| Trial expired | Effects stop; “Facevity trial expired” is drawn |
| No licence / invalid | UnlicensedBehavior.WATERMARK (default): effects + “Facevity · unlicensed”; or PASSTHROUGH: frames unchanged |
beauty.reshape not licensed |
Slim face, jaw and eye warps are ignored |
beauty.makeup not licensed |
Lipstick shades are ignored (the natural lip boost still works) |
ar.props not licensed |
setProp has no visible effect |
buffer.path not licensed |
Buffer frames are watermarked |
Suspension and revocation take effect at the app’s next validation (within about a day while online) or when its offline grace ends.
Checking status in code
val info = fv.licenseInfo
Log.i("App", "${info.status} ${info.type} expiresAtMs=${info.expiresAtMs}")
fv.addLicenseListener { updated -> /* react to refreshes, expiry, revocation */ }
Ready to evaluate? Request a trial licence with your package names.
Need help with an integration? Contact the Facevity team. We answer integration questions during trials.