CLI & Agent Auth
Authenticate Gmail from a terminal, CLI tool, or AI agent — no callback server needed.
How it works
- Your CLI calls
POST /api/device/codeto get an auth URL - The user opens the URL in a browser and authenticates with Google
- They land on inbox.dog's hosted page showing a one-time code
- They copy the code and paste it back into the terminal
- Your CLI calls
POST /oauth/tokento exchange the code for Gmail tokens
Prerequisites
- An inbox.dog API key (
client_id+client_secret) - A terminal or environment that can make HTTP requests
Don't have an API key? Create one:
curl -s -X POST https://inbox.dog/api/keys \
-H "Content-Type: application/json" \
-d '{"name": "my-agent"}' Step 1: Get the auth URL
curl -s -X POST https://inbox.dog/api/device/code \
-H "Content-Type: application/json" \
-d '{
"client_id": "id_YOUR_CLIENT_ID",
"client_secret": "sk_YOUR_CLIENT_SECRET",
"scope": "email:full"
}' Response:
{
"auth_url": "https://inbox.dog/oauth/authorize?client_id=id_...&redirect_uri=https%3A%2F%2Finbox.dog%2Fconnect%2Foauth&scope=email%3Afull",
"redirect_uri": "https://inbox.dog/connect/oauth",
"expires_in": 600
} Step 2: User authenticates
Print the auth_url to the terminal. The user opens it in their browser, signs in with Google, and sees a page with a code to copy.
Step 3: Exchange the code
Once the user pastes the code back, exchange it for Gmail tokens:
curl -s -X POST https://inbox.dog/oauth/token \
-H "Content-Type: application/json" \
-d '{
"code": "PASTED_CODE_HERE",
"client_id": "id_YOUR_CLIENT_ID",
"client_secret": "sk_YOUR_CLIENT_SECRET"
}' Response:
{
"access_token": "ya29.a0AfH6SM...",
"refresh_token": "1//0eXy...",
"token_type": "Bearer",
"expires_in": 3599,
"email": "user@gmail.com"
} The code is one-time use and expires in 5 minutes.
Node.js Example
Using the inbox.dog npm package:
import InboxDog from "inbox.dog";
import * as readline from "node:readline/promises";
const dog = new InboxDog();
const clientId = process.env.INBOXDOG_KEY!;
const clientSecret = process.env.INBOXDOG_SECRET!;
// 1. Get the auth URL
const { auth_url } = await dog.getDeviceCode(clientId, clientSecret, "email:full");
console.log(`Open this URL to authenticate:\n${auth_url}\n`);
// 2. Wait for user to paste the code
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
const code = await rl.question("Paste the code here: ");
rl.close();
// 3. Exchange for tokens
const tokens = await dog.exchangeCode(code.trim(), clientId, clientSecret);
console.log(`Authenticated as ${tokens.email}`);
// 4. Use Gmail
const gmail = dog.gmail(tokens, clientId, clientSecret);
const { messages } = await gmail.list({ query: "is:unread", maxResults: 5 });
console.log(`${messages.length} unread messages`); Scopes
| Scope | Access |
|---|---|
| Read-only Gmail + email address | |
| email:read | Read-only Gmail + email address |
| email:send | Send email + email address |
| email:full | Full Gmail access (read, send, modify) |
API Reference
POST
/api/device/code Start device auth Validates your API key and returns an auth URL with redirect_uri preset to inbox.dog's hosted code display page.
Request Body
{
"client_id": "id_...", // required
"client_secret": "sk_...", // required
"scope": "email:full" // optional, defaults to "email"
} Response 200
{
"auth_url": "https://inbox.dog/oauth/authorize?...",
"redirect_uri": "https://inbox.dog/connect/oauth",
"expires_in": 600
}