## DeviceAtlas Device Verification QR Code
This guide explains how to integrate DeviceAtlas Device Verification QR codes into your website. When scanned with a mobile device, the QR code triggers device verification and returns results to your page.
## Table of Contents
- [Quick Start](#quick-start)
- [Methods](#methods)
- [DeviceAssure.qr()](#devicevalidationqr)
- [DeviceAssure.parseQrRedirect()](#devicevalidationparseqrredirect)
- [Configuration Options](#configuration-options)
- [Response Format](#response-format)
- [Examples](#examples)
- [Basic Setup](#basic-setup)
- [With Callback](#with-callback)
- [Device Redirect](#device-redirect)
- [Host Redirect](#host-redirect)
- [Auto-Refresh](#auto-refresh)
- [Custom Destination](#custom-destination)
- [IMEI Corroboration](#imei)
- [Custom Tags](#custom-tags)
- [Styling](#styling)
- [Troubleshooting](#troubleshooting)
- [Redirect URLs](#troubleshooting-redirect-urls)
- [Content Security Policy](#troubleshooting-csp)
- [Callback Naming](#troubleshooting-callback-naming)
---
Quick Start
```html
```
---
Methods
DeviceAssure.qr()
Generates and displays a QR code in the specified container.
```javascript
DeviceAssure.qr({
containerId: 'deviceassure-qr-container', // The div to insert the QR code iframe into
licence: '',
callback: function(result) { console.log(result); },
imei: '',
tags: [
{ key: 'customTag1', value: 'value1' },
{ key: 'customTag2', value: 'value2' }
],
size: 250,
json: false,
scannedMessage: 'Code was scanned',
expiredMessage: 'Code has expired',
lifecycle: 'default',
responseDelay: 2000,
redirect: 'https://example.com/host-redirect',
deviceRedirect: 'https://example.com/device-redirect',
destination: 'https://example.com/custom-destination',
script: {
defer: true,
async: true,
nonce: 'randomNonceValue'
}
});
```
DeviceAssure.parseQrRedirect()
Parses the base64-encoded response from a redirect URL.
| Parameter | Type | Default | Description |
|----------------|---------|---------|---------------------------------------------------------------------------------------------------------------------|
| `data` | string | | Base64 string representing the JSON response. If not provided, the `response` query parameter from the URL is used. |
| `options.json` | boolean | `false` | When `true`, returns the parsed JSON object. When `false`, returns the decoded string. |
```javascript
// Processes the response query parameter and returns a string
DeviceAssure.parseQrRedirect();
// Processes the response query parameter and returns an object
DeviceAssure.parseQrRedirect(null, { json: true });
// Processes the passed in base64 string and returns a string
DeviceAssure.parseQrRedirect('eyJjb2RlIjoi...');
// Processes the passed in base64 string and returns an object
DeviceAssure.parseQrRedirect('eyJjb2RlIjoi...', { json: true });
```
---
Configuration Options
| Parameter | Type | Default | Description |
|------------------|----------|-----------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `containerId` | string | `deviceassure-qr-container` | ID of the container element for the QR code iframe |
| `licence` | string | | Your DeviceAssure licence key for accessing licence-specific device properties and configurations. |
| `callback` | function | | Function called when a scan result is received |
| `size` | number | `250` | QR code size in pixels (min: 50, max: 500) |
| `json` | boolean | `false` | When `true`, hides the iframe after scan and returns data via callback |
| `scannedMessage` | string | `Code was scanned` | Message displayed after successful scan |
| `expiredMessage` | string | `Code has expired` | Message displayed when QR code expires |
| `lifecycle` | string | `default` | `default`: shows scanned message after scan. `auto-refresh`: automatically generates new code once scanned |
| `responseDelay` | number | `2000` | The time delay after a scan. Usually used in conjunction with the `auto-refresh` lifecycle and host `redirect` in order to show a message before transitioning. |
| `redirect` | string | | URL to redirect the host page after scan |
| `deviceRedirect` | string | | URL to redirect the scanning device after scan |
| `imei` | string | | Provide an IMEI for use as another identifier for device verification. When `imei` is provided, it must be a non-empty string containing a valid IMEI. |
| `tags` | array | `[]` | A list of tags to add to the API request. Allows for custom parameters to be returned in the API Response. The `key` and `value` must be strings.
Maximum length for keys and values is 64 and 128 respectively |
| `script.defer` | boolean | false | Injects the `defer` attribute |
| `script.async` | boolean | false | Injects the `async` attribute |
| `script.nonce` | string | | Adds a `nonce` to the script |
---
### Callback Response
When using the `callback` option, results are returned in this format:
```json
{
"type": "com.deviceassure.payload.result",
"data": {
"code": "bd3f41f0-ace0-4c77-ae33-da195f2675ff",
"deviceAssure": {
"result": "AUTHENTIC",
"reason": "Properties match",
"deviceAtlasProperties": {
"vendor": "Google",
"marketingName": "Pixel 6a"
},
"referenceId": "871d26e2-94fb-400a-92ab-3b9a672b4c53"
},
"meta": {}
}
}
```
| Property | Type | Description |
|----------|------|-------------|
| `type` | string | Response type: `com.deviceassure.payload.result`, `com.deviceassure.payload.redirect`, or `com.deviceassure.payload.reload` |
| `data.code` | string | Unique QR code identifier |
| `data.deviceAssure` | object | Device verification result (see Implementation Guide for details) |
### Redirect Response
When using `redirect` or `deviceRedirect`, the target URL receives a `response` query parameter containing a base64-encoded JSON string:
```
https://example.com/redirect?response=eyJjb2RlIjoiYmQzZjQx...
```
The decoded response has a flattened structure (no `type` or `data` wrapper):
```json
{
"code": "bd3f41f0-ace0-4c77-ae33-da195f2675ff",
"deviceAssure": {
"result": "AUTHENTIC",
"reason": "Properties match",
"deviceAtlasProperties": {
"vendor": "Google",
"marketingName": "Pixel 6a"
},
"referenceId": "871d26e2-94fb-400a-92ab-3b9a672b4c53"
},
"meta": {}
}
```
---
Examples
Basic Setup
This example will:
- Display a QR code with default settings
- Show standard scan/expired messages in the iframe
```html
```
With Callback
This example will:
- Display a 300px QR code
- Hide the iframe after scan (`json: true`)
- Call the callback function with the scan result
- Display the result on the page
```html
```
Device Redirect
This example will:
- Display a QR code on the host page
- Redirect the scanning device to a results page after scan
- Pass the scan result as a base64-encoded `response` query parameter
- The redirect page parses and displays the result
**Host Page:**
```html
```
**Redirect Page (device-result):**
```html
```
**Alternative without DeviceAssure library:**
```html
```
Host Redirect
This example will:
- Display a QR code on the host page
- Redirect the host page (desktop) to a results page after scan
- Pass the scan result as a base64-encoded `response` query parameter
- The redirect page parses and displays the result
```html
```
> **Note:** The redirect page handling is the same as [Device Redirect](#device-redirect).
Auto-Refresh
This example will:
- Display a QR code on the host page
- Show a custom "Device verified!" message after scan
- Wait 2000ms then automatically generate a new QR code
- Call the callback function with each scan result
```html
```
IMEI Corroboration
The `imei` can be added as a parameter to the QR code generation. This allows the IMEI to be used as an additional identifier for device verification.
An example implementation is shown below:
```html
```
The `tags` can be added as a parameter to the QR code generation. This allows for custom tags to be returned in the response for further use.
An example implementation is shown below:
```html
```
Custom Destination
The `destination` can be added a parameter to the QR code generation. This controls where the QR code 'points' to. It is
useful when wanting to point to a custom page rather than the default DeviceAssure page. This can be used in conjunction with the `redirect` and `deviceRedirect`
parameters to control the flow of the QR code.
This page will need to collect the payload and send it on to our API in order to get the device verification result.
The `destination` can be used to point to this page and the `redirect` and `deviceRedirect` can be used to control where the host and scanning device go after the scan respectively.
**Note:**
The `deviceRedirect` implementation will need to be handled in the custom page the QR points to. However, the message returned to this page
will contain the redirect url for use.
An example implementation is shown below:
```html
```
###### Example Destination Page Implementation
Below shows how to collect and send the payload to the DeviceAtlas QR API. The payload will be collected by the `DeviceAssure.load()` function and then sent to the API using `fetch()`.
The QR code ID is needed to correlate the device and the qr code. It is passed in to the url via a query parameter when the QR code is scanned. This can be extracted and included in the header of the API request for correlation purposes.
Example URL:
```http request
https://localhost:8091/deviceassure?deviceatlas-qr-code=bd3f41f0-ace0-4c77-ae33-da195f2675ff&other-parameters=you-can-include
```
```html
```
---
Styling
Customize the QR code iframe appearance with CSS:
```css
/* Size the iframe */
#deviceassure-iframe {
width: 325px;
height: 325px;
}
/* Center the QR code container */
#deviceassure {
display: flex;
justify-content: center;
align-items: center;
}
```
---
Troubleshooting
Redirect URLs
When using `redirect` or `deviceRedirect`, the URL must be accessible from the scanning device. The following will **not** work:
- `localhost`
- `127.0.0.1`
- `0.0.0.0`
Use a network IP address or domain name accessible to the scanning device.
Content Security Policy (CSP)
If your site uses a Content Security Policy (CSP), ensure that the following domains are allowed:
- `qr-code.deviceatlas.com` (Iframe)
- `cdn.devicevalidation.io` (Web Library Scripts)
An Example setup could look like:
```http
Content-Security-Policy: frame-src 'self' https://qr-code.deviceatlas.com;
script-src 'self' https://cdn.devicevalidation.io https://qr-code.deviceatlas.com;
```
The DeviceAssure API url might need to be added to the CSP too. The following urls might need to be configured too:
- `https://api1.devicevalidation.io`
- `https://api2.devicevalidation.io`
- `https://api3.devicevalidation.io`
These can be set in the CSP by:
```http
Content-Security-Policy: connect-src 'self' https://api1.devicevalidation.io https://api2.devicevalidation.io https://api3.devicevalidation.io;
```
A full CSP for DeviceAssure could look like:
```http
Content-Security-Policy: frame-src 'self' https://qr-code.deviceatlas.com;
connect-src 'self' https://api1.devicevalidation.io https://api2.devicevalidation.io https://api3.devicevalidation.io;
script-src 'self' https://cdn.devicevalidation.io https://qr-code.deviceatlas.com;
```
Callback Naming
When using `DeviceAssure.qr()`, your callback can have any name — the library internally wires it to the global `_deviceAssureResultReceived` function.
However, if you use the raw snippet directly (without the library wrapper), you **must** define the callback with the exact name `_deviceAssureResultReceived`:
```html
```
---
## Copyright
Copyright (c) DeviceAtlas Limited 2026. All rights reserved. https://deviceatlas.com