> ## Documentation Index
> Fetch the complete documentation index at: https://api.visor.vin/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication

> Create API credentials, send bearer tokens safely, and choose the right scopes.

All public API requests use the same production base URL:

```txt theme={null}
https://api.visor.vin/v1
```

Send API keys in the `Authorization` header:

```sh theme={null}
export VISOR_API_KEY="vis_live_..."

curl "https://api.visor.vin/v1/listings?limit=1&make=toyota" \
  -H "Authorization: Bearer $VISOR_API_KEY"
```

<Warning>
  Do not put API keys in query strings, prompts, shared config files, screenshots, shell history, or URLs. Query-string keys such as `?api_key=...`, `?apiKey=...`, `?key=...`, and `?access_token=...` are rejected.
</Warning>

## Keys and accounts

API keys belong to an API account, not to one endpoint. All keys on the same account share that account's billing balance, monthly spend cap, and Usage Tier rate limits.

Create and revoke keys from the Visor dashboard credentials area. The secret is shown once, so store it in a password manager or secret manager before leaving the page.

For local development, use an environment variable:

```sh theme={null}
export VISOR_API_KEY="vis_live_..."
```

For server-side production code, store the key in your deployment platform's secret manager and inject it as an environment variable. Avoid committing `.env` files.

## Scopes

Keys can be scoped. Give a key only the scopes it needs:

| Scope            | Allows                                                 |
| ---------------- | ------------------------------------------------------ |
| `inventory.read` | Listing search, listing detail, facets, and VIN lookup |
| `dealers.read`   | Dealer search, dealer detail, and dealer inventory     |
| `usage.read`     | Account usage summaries from `/v1/usage`               |

If a key is valid but missing a scope, the API returns `403 permission_error` with `code: "missing_scope"`.

## Check a key

If the key has `usage.read`, `/v1/usage` is a good connectivity check because it is not billable:

```sh theme={null}
curl "https://api.visor.vin/v1/usage" \
  -H "Authorization: Bearer $VISOR_API_KEY"
```

If the key only has inventory or dealer scopes, run a deliberately small request:

```sh theme={null}
curl "https://api.visor.vin/v1/listings?limit=1&fields=id,vin" \
  -H "Authorization: Bearer $VISOR_API_KEY"
```

## Common authentication failures

| Status | Code                            | Meaning                                                                          |
| ------ | ------------------------------- | -------------------------------------------------------------------------------- |
| `400`  | `query_string_api_key_rejected` | A key-like query parameter was sent. Move the key to the `Authorization` header. |
| `401`  | `missing_api_key`               | No bearer token was provided.                                                    |
| `401`  | `invalid_api_key`               | The token is malformed, revoked, or unknown.                                     |
| `402`  | `billing_state_blocked`         | The API account cannot make paid requests in its current billing state.          |
| `402`  | `monthly_spend_cap_exceeded`    | The request would exceed the account's monthly spend cap.                        |
| `403`  | `missing_scope`                 | The key is valid but does not include the scope required by the endpoint.        |

## Agents and OAuth

For Claude, ChatGPT, Codex, Claude Code, OpenCode, and other MCP clients, the hosted MCP server can use OAuth so you do not copy an API key into the client:

```txt theme={null}
https://mcp.visor.vin/mcp
```

See [Connect to your AI agent](/docs/mcp-setup) for app-specific setup.
