> ## Documentation Index
> Fetch the complete documentation index at: https://developers.circle.com/llms.txt
> Use this file to discover all available pages before exploring further.

# How-to: Collect device risk signals

> Run a web device check with @circle-fin/device-checks before you submit a Stablecoin KYB application

<Note>
  The End User Onboarding API base URL is `https://api-sandbox.circle.com` for
  sandbox and `https://api.circle.com` for production. All requests require a
  Bearer token obtained via Circle key exchange in the `Authorization` header. All
  `POST` requests require an `X-Idempotency-Key` header with a client-generated
  UUID v4.
</Note>

Stablecoin KYB requires a Persona Sentinel device check before you submit or
resubmit the application. Install
[`@circle-fin/device-checks`](https://www.npmjs.com/package/@circle-fin/device-checks)
and call `checkDevice` in the browser. The SDK loads an iframe, Circle records
the result, and you then call submit. Circle looks up that result on submit and
RFI resubmit.

<Note>
  `@circle-fin/device-checks` is web only. It cannot run in Node.js or other
  server-side environments.
</Note>

## Prerequisites

Before you begin, ensure that you've:

* Obtained an API key for the End User Onboarding API from the
  [Circle Console](https://console.circle.com).
* Created and populated a Stablecoin KYB application. See
  [Create and populate applications](/end-user-onboarding/howtos/create-and-populate-applications).

## Steps

### Step 1. Check whether your template requires a device check

Confirm that the application uses a Stablecoin KYB template. Only Stablecoin KYB
requires this check. For other templates, go to
[Submit and track applications](/end-user-onboarding/howtos/submit-and-track-applications).

### Step 2. Run `checkDevice` in the browser

Install the SDK in your web project:

```bash theme={null}
npm install @circle-fin/device-checks
```

Follow the
[`@circle-fin/device-checks` README](https://www.npmjs.com/package/@circle-fin/device-checks)
for token setup and options. Then call `checkDevice` in your web client:

```typescript theme={null}
import { checkDevice } from "@circle-fin/device-checks";

const { deviceId }: { deviceId: string } = await checkDevice({
  token: deviceCheckToken, // mint a short-lived token per the README
  environment: "sandbox", // use "production" for live applications
});
```

`checkDevice` loads an iframe and collects device signals. Circle records the
result. For the full list of options, see the
[`@circle-fin/device-checks` README](https://www.npmjs.com/package/@circle-fin/device-checks).

### Step 3. Submit the application

Call `POST .../submit` (or resubmit after you address RFIs). See
[Submit and track applications](/end-user-onboarding/howtos/submit-and-track-applications#step-2-submit-the-application).

Use `code` to identify the outcome. A declined device check still submits.
Review of a declined check is manual.

| Result                                        | HTTP  | Code                                                       | Status      | Partner action                        |
| --------------------------------------------- | ----- | ---------------------------------------------------------- | ----------- | ------------------------------------- |
| Device check recorded as approved or declined | `200` | —                                                          | `SUBMITTED` | Continue.                             |
| Device check was not run                      | `404` | [`181110`](/api-reference/end-user-onboarding/error-codes) | Unchanged   | Run `checkDevice`, then retry submit. |
| Device check has not finished                 | `504` | [`181111`](/api-reference/end-user-onboarding/error-codes) | Unchanged   | Retry submit later.                   |
| Device-check lookup failed                    | `500` | [`181108`](/api-reference/end-user-onboarding/error-codes) | Unchanged   | Retry later.                          |

`181110` and [`181103`](/api-reference/end-user-onboarding/error-codes) both
return HTTP `404` and `message: "Not found"`. `181111` and
[`181109`](/api-reference/end-user-onboarding/error-codes) both return HTTP
`504` and `message: "Gateway timeout"`. Use `code` to tell them apart.
