Device Approval (Consoles & TVs)
A console has no browser, so it cannot run a passkey ceremony at all. Device Approval moves the ceremony to a device that can: your game shows a short code, the player approves on their phone, and your game polls until it hears back. It is the OAuth 2.0 Device Authorization Grant (RFC 8628) — the same “enter this code on your phone” flow every console and TV app uses — so you can reach for an existing client library rather than write one.
When you need it
Use this anywhere the device running your game cannot perform WebAuthn: consoles, TV apps, and native desktop builds without a real browser origin. You do not need it on web, iOS or Android — those run the ceremony in-process.
It is available to every title, with nothing to configure
The constraint is a property of the device, not of your game. A title that ships a website and a console build uses the normal ceremony in the browser and this one on the console. There is no flag to set and no domain to verify — the ceremony happens on INVO’s own domain, which is the whole point.
The flow
1. Your server starts an approval
After you initiate a transfer, ask INVO to start an approval for that transaction. You get back a short code, two URLs, a device code, a poll interval and an expiry.
2. Your game shows the code and a QR
Render verification_uri_complete as a QR code and print the user_code underneath. The QR already contains the code, so most players scan and never type anything.
3. The player approves on their phone
They land on an INVO page, see what they are approving, and confirm with their passkey — fingerprint, face or screen lock. Nothing about this step touches your servers.
4. Your game polls until it hears back
Poll with the device code at the interval INVO gave you. You can also subscribe to the device_approval.approved webhook and learn the moment it lands, instead of waiting for the next poll.
Starting an approval
Server-to-server, with the player’s SDK session token. flow is the action being approved: transfer, send, send_receipt or transfer_receipt.
POST /api/sdk/approvals/device/begin
Authorization: Bearer <sdk_session_token>
Content-Type: application/json
{
"transaction_id": "TXN_...",
"flow": "transfer"
}200 OK
{
"device_code": "b1s4...", // secret; keep it on your server
"user_code": "K7QP-3MRD", // show this
"verification_uri": "https://invo.network/device",
"verification_uri_complete": "https://invo.network/device?user_code=K7QP-3MRD",
"expires_in": 600,
"interval": 5
}Polling
Poll no faster than interval seconds. The error codes are the RFC 8628 ones, so a standard client understands them without translation.
POST /api/sdk/approvals/device/poll
Authorization: Bearer <sdk_session_token>
{ "device_code": "b1s4..." }| Response | Meaning | What to do |
|---|---|---|
status: approved | The player approved | Continue — complete the transfer |
authorization_pending | Not yet | Keep polling at interval |
slow_down | You are polling too fast | Back off, then resume |
expired_token | The code timed out | Start a new approval |
access_denied | The player declined | Stop; do not retry silently |
invalid_grant | Unknown or not yours | Start a new approval |
The completion webhook
Subscribe to device_approval.approved and your server hears the moment an approval lands. Polling still works on its own — the webhook is a latency improvement, not a replacement, and you should not rely on it as your only signal.
{
"event": "device_approval.approved",
"schema_version": "1.0",
"data": {
"transaction_id": "TXN_...",
"flow": "transfer",
"identity_id": "9f2c...",
"method": "device_grant_webauthn"
}
}Rules worth knowing
One approval authorises one transaction
Unlike the plain RFC 8628 grant, which authorises a client, an INVO device code is bound to the single transaction you named and is consumed when it is used. It cannot approve anything else, and it cannot be reused.
Codes are short-lived, and only one is live per transaction
A code expires in minutes. Starting a second approval for a transaction that already has a live one returns 409 DEVICE_APPROVAL_ALREADY_PENDING — reuse the code you have, or wait for it to expire.
Keep the device code on your server
The user_code is meant to be seen; the device_code is not. Poll from your backend, not from the game client.
The player needs an INVO passkey
The approval page uses a passkey registered with INVO. A passkey a player set up on your domain is a different credential and cannot be used here — that is how passkeys work, not a limitation of this flow. The page tells them plainly when they need to set one up.
What this is not for
Currency purchases on a console go through that console’s own store, as required by the platform holder. This flow is for approving transfers and sends — moving currency a player already has.