Know the device, not the person.
A stable device ID that survives reinstalls, decided on your server and never derived from personal data.
One package. One method call. Android and iOS.
// 1. Start the SDK once, at launch. await Devicesign.initialize(apiKey: 'pk_live_...'); // 2. Ask who this device is. final device = await Devicesign.identifyDevice(); print(device.deviceId); // 72af366e-be84-481b-8a68-ca804f114758 print(device.isNew); // false print(device.matchMethod); // MatchMethod.hardwareId print(device.confidence); // 0.98
Device IDs break exactly when you need them
Every platform identifier was designed to be resettable, and app storage disappears with the app. So the same phone comes back as a stranger.
Reinstalls wipe your storage
Anything saved in app storage is gone. On iOS even the vendor identifier resets once the last app from you is removed.
One phone, many identities
Without a way to recognise it, a single device becomes a new record after every reinstall, inflating device counts and breaking per-device limits.
Many phones, one identity
Matching on a coarse fingerprint alone merges identical models in the same country into one record. Wrong in the other direction, and harder to notice.
Five signals, strongest first
Matching runs on the server, never in the app. Each tier is checked in order, and every one of them is vetoed by a hardware identifier that disagrees.
Stored token
A UUID the SDK keeps on the device. Survives app updates and everyday use.
Hardware identifier
ANDROID_ID or identifierForVendor, stored only as an HMAC. Survives reinstalls.
Your user ID
Optional: pass your own account ID and it becomes a matching signal.
Exact fingerprint
Model, OS major, locale and timezone. Used only when exactly one device carries that fingerprint.
Similar fingerprint
A weighted match against similar devices, refused when two candidates look equally good.
Otherwise: a new device
When nothing is certain enough, a new record is created. An extra row is cheaper than the wrong identity.
Numbers from a harness, not a brochure
Live traffic cannot tell you whether two sightings were the same phone, so accuracy is measured against a simulated population where the answer is known: duplicated popular models, reinstalls, OS upgrades, travel, and cloud restores onto new hardware.
| Measure | Result |
|---|---|
| Matched the right device | 93.9% |
| Recognised a returning device | 99.1% |
| Identity taken over by a restore | 0 |
| Emulator merged with a phone | 0 |
Precision is the one that matters — Handing one phone another device’s identity corrupts data quietly. Creating an extra record does not.
Every decision is explainable — Each answer carries the tier that produced it and the confidence behind it, so a match can be audited instead of trusted.
Ambiguity is refused, not guessed — When two devices look equally likely, the match is declined and a new device is recorded.
Built to hold less
Identification needs signals about the hardware, not about the person using it.
Hardware IDs are never stored raw
They arrive over TLS and are immediately HMAC-hashed with a server-side pepper. The database never holds the original.
IDs are scoped per API key
A device ID means something only inside your account. The same phone in another customer’s app is a different record.
Nothing personal in the fingerprint
Model, OS version, locale and timezone. No advertising ID, no contacts, no location, and nothing that identifies a human.
Questions
Does the device ID survive a reinstall?
Usually. The stored token goes with the app, but the hardware identifier normally survives and recovers the same ID. A factory reset, or removing every app you publish on iOS, starts a new identity by design.
Can someone copy a device ID to impersonate a device?
A copied token is not enough. Every tier is checked against the hardware identifier, so a token restored onto another phone is rejected; that phone gets its own identity and a fresh token.
Why does matching run on your server?
Anything shipped inside the app can be patched out. The SDK collects signals and asks; the decision, and the licence check behind it, happen where a customer cannot edit them.
What happens when the answer is uncertain?
A new device is recorded. Refusing a doubtful match keeps one device from inheriting another’s history, which is the expensive mistake.