<!-- tempo-docs-context -->
> Source: [/docs/accounts/authentication/device-keys](https://tempo.xyz/developers/docs/accounts/authentication/device-keys.md)
> Section: [Accounts](https://tempo.xyz/developers/docs/accounts.md). Create accounts, set up signing methods, policies, access keys, key rotation, and fees, and follow guides for users, automations, agents, and teams.
> [Documentation index](https://tempo.xyz/developers/llms.txt) · [Docs skill](https://tempo.xyz/developers/SKILL.md)

> Tempo MCP: Use `search`, `find_pages`, `read_page`, and `code` at `https://mcp.tempo.xyz` for Tempo and related documentation.
> If an indexed page is missing or reflects an older site, read this site’s [documentation index](https://tempo.xyz/developers/llms.txt) and Markdown pages directly.

# Device Keys

A device key lets the customer's phone, computer, or browser pay without asking the customer to approve each payment.

<span id="what-a-device-key-is" />

## Overview

A device key is a P-256 key that the device's own key store creates and never exports. The customer's passkey authorizes it once as an [access key](https://tempo.xyz/developers/docs/accounts/access-keys). Tempo rejects any payment it signs over its spending limit or after it expires. On a server, use a [private key](https://tempo.xyz/developers/docs/accounts/authentication/private-keys) in your KMS or HSM instead.

<span id="how-it-works" />

## Key Stores

Each platform keeps device keys in its own key store:

<span id="device-key-stores-by-platform" />

| Platform | Key store |
| --- | --- |
| iPhone, iPad, and Mac | Secure Enclave |
| Android | Android Keystore, backed by StrongBox or other secure hardware where available |
| Windows | TPM, through the Microsoft Platform Crypto Provider |
| Browsers | Non-extractable WebCrypto key, kept in IndexedDB |

<span id="what-a-device-key-trusts" />

Your servers and wallet providers never hold the device key. Anyone who unlocks the device can pay with it, up to its [spending limit](https://tempo.xyz/developers/docs/accounts/access-keys/spending-limits) and until it [expires](https://tempo.xyz/developers/docs/accounts/access-keys/expiry). Add a device key as an access key to get that cap. A signer has no spending limit.

<span id="create-the-key-on-the-device" />

<span id="authorize-it-from-a-signer" />

<span id="pay-with-it" />

<span id="how-a-device-key-starts-paying" />

## Create a Device Key

In the interactive web page, create a non-extractable P-256 key with WebCrypto, kept in this browser’s IndexedDB, and see that the browser refuses to export it. Fund its test account on the Tempo Accounts devnet from the faucet, pay 1 AlphaUSD with no prompt, reload to see the key restored, then delete it. Each payment is a real devnet transaction.

The demo makes the device key its own account on the Tempo Accounts devnet to show signing without a prompt. Reload the page and the key is still there.

In your app, add the key to the customer's account as an access key instead. The device creates the key. The customer's passkey authorizes it for up to 500 OUSD a day for 30 days. The first payment carries that authorization.

On mainnet and testnet today, a device key can be an access key on a single-key account. That account's one key is the customer's passkey.

:::warning
**Multiple signers arrive with the [T14 network upgrade](https://tempo.xyz/developers/docs/protocol/upgrades/t14).** Until T14 activates, an account with several signers and a threshold runs only on the [Tempo Accounts devnet](https://tempo.xyz/developers/docs/accounts/create#connect-to-the-devnet), not on mainnet or testnet, and may still change.
:::

This example uses a configurable account with the passkey as its signer. `client.ts` connects to the devnet ([set up the devnet key](https://tempo.xyz/developers/docs/accounts/create#connect-to-the-devnet)). In `device-key.ts`, `account` is the customer's funded account, built as in [Passkeys](https://tempo.xyz/developers/docs/accounts/authentication/passkeys#create-a-passkey-signer).

:::code-group
```ts [device-key.ts]
import { parseUnits } from 'viem'
import { Account, Expiry, WebCryptoP256 } from 'viem/tempo'
import { client } from './client'

// A test stablecoin on the devnet
const stablecoin = '0x20c0000000000000000000000000000000000001'

// Non-extractable. Save keyPair in IndexedDB so it survives a reload.
const keyPair = await WebCryptoP256.createKeyPair() // [!code hl]
const deviceKey = Account.fromWebCryptoP256(keyPair, { access: account }) // [!code hl]

// approved by the customer's passkey
const keyAuthorization = await client.accessKey.signAuthorization({ // [!code hl]
  accessKey: deviceKey, // [!code hl]
  account, // [!code hl]
  expiry: Expiry.days(30), // [!code hl]
  limits: [{ token: stablecoin, limit: parseUnits('500', 6), period: 86_400 }], // [!code hl]
}) // [!code hl]
```

```ts [client.ts]
import { http } from 'viem'
import { tempoDevnet } from 'viem/chains'
import { createClient } from 'viem/tempo'

// The Tempo Accounts devnet. Its RPC needs a key, which Tempo gives you.
const rpcKey = process.env.TEMPO_DEVNET_RPC_KEY

export const client = createClient({
  chain: tempoDevnet,
  transport: http('https://rpc-t14-checkpoint.devnet.tempoxyz.dev', {
    fetchOptions: { headers: { Authorization: `Basic ${btoa(`previews:${rpcKey}`)}` } },
  }),
})
```
:::

Pass `keyAuthorization` with the device key's first payment, signed by `deviceKey`, as in [Access keys](https://tempo.xyz/developers/docs/accounts/access-keys#authorize-an-access-key). Later payments need only `deviceKey`.

<span id="device-key-limits" />

## Limits

* Each device needs its own key, authorized by the customer's passkey.
* Clearing site data deletes a browser key. Authorize a new one the same way.
* If a device is lost, [revoke its key](https://tempo.xyz/developers/docs/accounts/access-keys/revocation#revoke-an-access-key). The account's signers don't change.

## Related

[Access Keys](https://tempo.xyz/developers/docs/accounts/access-keys): Covers keys that pay alone within limits, expiry, and scopes.

[Spending Limits](https://tempo.xyz/developers/docs/accounts/access-keys/spending-limits): Covers how much of one TIP-20 token an access key can spend.

[Revocation](https://tempo.xyz/developers/docs/accounts/access-keys/revocation): Use for revoking a lost device's key.

[Passkeys](https://tempo.xyz/developers/docs/accounts/authentication/passkeys): Covers the customer's passkey, which authorizes each device key.

[Private Keys](https://tempo.xyz/developers/docs/accounts/authentication/private-keys): Covers keys in a wallet, a wallet provider, or your KMS or HSM.
