---
title: "Device Sign-in: `banksync login --device` and the OAuth Device Grant"
description: "Sign a terminal or a machine without a browser into BankSync with the OAuth 2.0 device authorization grant (RFC 8628): the CLI flow, the endpoints, their errors and limits, and how to revoke it."
section: "API"
canonical: "https://banksync.io/docs/api/device-sign-in"
specs: ["developer","auth"]
operationBindings: [{"capability":"developer","operation":"developer.oauth.device-authorization.start"},{"capability":"developer","operation":"developer.oauth.device-authorization.approve"},{"capability":"developer","operation":"developer.oauth.device-authorization.token"},{"capability":"auth","operation":"auth.sessions.revoke-all"}]
---

Device sign-in signs a machine with no usable browser into BankSync: an SSH session, a container, a CI box you are logged in to. The machine shows a short code; you type it into BankSync in any browser where you're signed in, choose a workspace and approve. It is the standard [OAuth 2.0 Device Authorization Grant](https://www.rfc-editor.org/rfc/rfc8628), offered to BankSync's own CLI client (`banksync-cli`) only; the endpoints below document what the CLI does.

The result is an ordinary OAuth grant: scoped to the permissions you approved and to one workspace, refreshed like any other, listed under **Settings, Developers, Connected apps**, and revocable there.

> **Availability:** 'Device sign-in is rolling out. While it is switched off, discovery still advertises the endpoint, but /device\_authorization answers temporarily\_unavailable (HTTP 503) and banksync login --device exits with device\_login\_unavailable. Use banksync login (browser) or an API key until then.'

## From the CLI

```bash
banksync login --device
banksync login --device --scope transactions:read,feeds:read
```

```text
To sign in, open  https://app.banksync.io/device
and enter the code  BCDF-GHJK

Check that the code there matches this one before you approve.
Waiting for approval (expires in 10 minutes)...
Logged in to Acme Books (profile: default).
```

The CLI stores the credential exactly as `banksync login` does. `banksync logout` forgets it on this machine; revoking it under Connected apps ends it everywhere.

## The endpoints

Discovery (`https://auth.banksync.io/.well-known/oauth-authorization-server`) advertises `device_authorization_endpoint` and the grant type `urn:ietf:params:oauth:grant-type:device_code`.

### 1. The client: `banksync-cli`

The device grant belongs to BankSync's own command line. It uses the first-party public client `banksync-cli`, which BankSync defines itself, so there is nothing to register and no secret. Dynamic client registration refuses the device grant (`invalid_client_metadata`), and `/device_authorization` refuses any other client (`unauthorized_client`). That way the approval page only ever names a client BankSync vouches for. For your own tool, use `banksync login --device` and the CLI's stored credential, an API key, or the browser authorization-code flow.

### 2. Start: `POST /device_authorization`

```http
POST https://auth.banksync.io/device_authorization
Content-Type: application/x-www-form-urlencoded

client_id=banksync-cli&scope=banks:read feeds:read&platform=linux
```

`platform` is a BankSync extension the approval page shows (`web`, `windows`, `mac`, `linux`, `ios`, `android`, `other`).

```json
{
  "device_code": "Q0hBTkdFLU1FLWl0J3MtYS0zMi1ieXRlLXJhbmRvbS12YWx1ZQ",
  "user_code": "BCDF-GHJK",
  "verification_uri": "https://app.banksync.io/device",
  "verification_uri_complete": "https://app.banksync.io/device?code=BCDF-GHJK",
  "expires_in": 600,
  "interval": 5
}
```

Show `user_code` and `verification_uri`, and ask the person to type the code. `verification_uri_complete` is for display (a QR code); the page still asks them to confirm the code against your screen. Keep `device_code` secret.

### 3. Poll: `POST /token`

```http
POST https://auth.banksync.io/token
Content-Type: application/x-www-form-urlencoded

grant_type=urn:ietf:params:oauth:grant-type:device_code&device_code=Q0hBTk...&client_id=banksync-cli
```

Wait `interval` seconds between polls. Until approval the answer is HTTP 400:

| `error`                 | Meaning                                                    | Do                                   |
| ----------------------- | ---------------------------------------------------------- | ------------------------------------ |
| `authorization_pending` | Not approved yet                                           | Poll again after `interval` seconds  |
| `slow_down`             | You polled too soon                                        | Add 5 seconds to `interval` for good |
| `access_denied`         | Denied, or the person was signed out or left the workspace | Stop                                 |
| `expired_token`         | Ten minutes passed, or the grant was already issued        | Stop; start again                    |
| `invalid_grant`         | The device code belongs to another client                  | Stop                                 |

Once approved, one poll gets the standard token response (`access_token`, `refresh_token`, `expires_in`, `scope`). Refresh it with `grant_type=refresh_token` like any BankSync grant.

### Limits

- `/device_authorization` is rate limited per IP, and `/token` per IP and per client; a limited request is HTTP 429 with `Retry-After`.
- The person approving has a budget of five wrong codes in fifteen minutes.
- While device sign-in is turned off, `/device_authorization` answers `temporarily_unavailable` (HTTP 503) and the approval page can't look up or approve a code, so a code issued before it was turned off ends in `expired_token`. `/token` itself isn't switched off: refreshing existing grants keeps working.

## Revoking

- **One device:** Settings, Developers, Connected apps, or `POST /revoke` with its refresh token.
- **Sign out everywhere** (`POST /api/device-signin/sessions/revoke-all` from the app) ends signed-in browser and Excel add-in sessions only. It does not end OAuth grants, API keys or SimpleFIN access, and its response says so in `still_active`; revoke those where they live.

## Security notes

- Approving needs a sign-in from the last ten minutes that passed two-step verification when it's on, on a verified account. A session from the Excel add-in can never approve.
- Only BankSync's own CLI client can start a device sign-in, so the approval page never shows a name someone else chose. It names the client, the permissions, the platform, when and roughly where the device asked, and you choose the workspace and may grant fewer permissions.
- Never approve a code someone else sent you. BankSync staff never ask you to.
