# Authentication

> For the complete documentation index, see [llms.txt](https://inkstudioai.com/developers/llms.txt). Every page has a markdown version: add `.md` to its URL.

Get an API key with the CLI, the account page, or the device login, and send it as a Bearer token.

## API keys

API keys start with `isk_`. Send the key in the `Authorization` header of each request:

```http
Authorization: Bearer isk_...
```

These endpoints are public and need no key: `GET /styles`, `GET /pricing`, `GET /gallery`, `POST /auth/device`, and `POST /auth/token`. All other endpoints answer `401` with `code: "unauthorized"` when the key is missing, unknown, or revoked.

## Get a key

- **CLI:** run `npx inkstudioai login`. The browser opens, you approve the request, and the CLI saves the key on your computer.
- **Account page:** create a key at [https://inkstudioai.com/account?view=api-keys](https://inkstudioai.com/account?view=api-keys). The full key is shown only once.
- **Device login:** your own tool can sign in the user with the device login below, the same way as the CLI.

New accounts get one free design. You do not need a card to sign up.

## Key rules

- An account has at most 10 active keys.
- An account can create 10 keys per hour. Keys from the account page and approved device logins count together.
- The account owner gets an email for each new key.
- The server stores only a SHA-256 hash of the key and its first 12 characters for display.
- Delete a key on the account page. It stops working at once. When the account is deleted, all of its keys stop working.

## Device login

The device login follows the OAuth device flow (RFC 8628). The user approves the request in the browser, and your tool gets a key. The user does not copy a key by hand.

1. Start the login with `POST /auth/device`. The body is optional: `{ "clientName": "my-tool on ana-laptop" }`, up to 80 characters.

   ```json
   {
     "deviceCode": "<secret, 43 characters>",
     "userCode": "WDJB-MJHT",
     "verificationUrl": "https://inkstudioai.com/cli/authorize",
     "verificationUrlComplete": "https://inkstudioai.com/cli/authorize?code=WDJB-MJHT",
     "expiresIn": 600,
     "interval": 5
   }
   ```

2. Show `userCode` and open `verificationUrlComplete` for the user. The user signs in or creates an account, checks that the code is the same, and approves.
3. Send `POST /auth/token` with `{ "deviceCode": "..." }` every `interval` seconds until you get a final answer:
   - `400` with `code: "authorization_pending"`: the user did not approve yet. Send the request again.
   - `400` with `code: "slow_down"`: add 5 seconds to the interval.
   - `400` with `code: "access_denied"` or `code: "expired_token"`: stop.
   - `400` with `code: "validation"`: the account already has 10 active keys. Ask the user to revoke one at [https://inkstudioai.com/account?view=api-keys](https://inkstudioai.com/account?view=api-keys), then poll again before the code expires.
   - `429` with `code: "rate_limited"`: wait for `retryAfterSeconds`, then poll again.
   - `200` with `{ "apiKey": "isk_...", "keyId": "...", "email": "ana@example.com" }`: done. A device code gives a key only once.

`POST /auth/device` allows 10 requests per minute per IP address, and `POST /auth/token` allows 60.

## CORS

CORS: No. The API does not send CORS headers, so a web page cannot call it from the browser. Use the API from a server, the CLI, or the MCP server, and keep the API key out of browser code. Only the OpenAPI spec at [https://inkstudioai.com/api/v1/openapi.json](https://inkstudioai.com/api/v1/openapi.json) allows requests from any origin.
