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.