# Authentication

Authenticate OSINTOne API requests with an ov_ API key.

URL: https://osintverse.com/docs/authentication

Authenticated endpoints require an API key in the `x-api-key` header. Create keys in [Dashboard → API keys](https://osintverse.com/dashboard/api). The [Python SDK](https://osintverse.com/docs/python) sets this header for you from `OSINTVERSE_API_KEY` or `api_key=`.

```http
x-api-key: ov_your_secret_key
Content-Type: application/json
```

> **Key format.** Secrets are prefixed with `ov_`. The full value is shown once at creation. OSINTverse stores a hash, not the plaintext secret.

## Access levels and daily caps

Each key has an access level, chosen when you create it under Dashboard → API keys:

| Access          | Can do                                                                               | MCP scopes                 |
| --------------- | ------------------------------------------------------------------------------------ | -------------------------- |
| Read only       | `GET /v1/providers`, `POST /v1/search/quote`, read existing searches. Never charges. | `osint:read`               |
| Search and read | Everything above, plus paid lookups (`POST /v1/search`, bulk, unlock, premium)       | `osint:read`, `search:run` |
| Full access     | Everything, including creating and filling cases over MCP                            | all three                  |

A call outside the key's level returns **403** with `error.code: "forbidden"`. Keys created before access levels existed have full access.

A key can also have a **daily spend cap** in USD. Paid calls stop with **403** once the key's charged spend for the UTC day, plus the call being made, would pass the cap. It counts every search the key runs, over the REST API, the CLI, and MCP, and resets at 00:00 UTC. Team keys also stay inside the team's provider allowlist and monthly cap.

## Sign in from a terminal or agent

`npx osintverse login` gets a key without copying one by hand. It uses the device authorization flow (RFC 8628):

1. The CLI asks `POST https://osintverse.com/api/cli/device/code` for a code and prints it with a link.
2. You open `https://osintverse.com/device`, sign in, check the code matches your terminal, and pick the wallet the key bills (personal, or a team you own or administer).
3. The CLI polls `POST https://osintverse.com/api/cli/device/token` with its `device_code` (form or JSON body). It gets `authorization_pending` or `slow_down` until you approve, then a new `ov_` key once: `{ "api_key", "key_id", "key_name", "workspace" }`.

The key is created at that last step, so its secret is never stored on our side, and it appears under Dashboard → API keys as `CLI: <hostname>`, where you can revoke it. Codes expire after ten minutes and work once. Any agent that can make HTTP requests can use the same three calls; only approve codes you started yourself.

## Rate limits

Each key is limited to **1,000 requests per day**, counted per calendar day in UTC and reset at 00:00 UTC. Every authenticated HTTP request counts once: a create, a quote, each poll (`GET /v1/search/:id`, including SDK `wait=True`), and a bulk call (one request however many jobs it starts). Responses carry `RateLimit-Remaining` and `RateLimit-Reset`, and a used-up key gets **429** with `Retry-After` rather than 401 ([details](https://osintverse.com/docs/api/errors#rate-limit-headers)). Create more keys from the dashboard if you need isolation between apps.

## Public vs authenticated

| Endpoint                      | Auth     |
| ----------------------------- | -------- |
| `GET /health`                 | None     |
| `GET /v1/providers`           | None     |
| `POST /v1/search`             | Required |
| `POST /v1/search/bulk`        | Required |
| `GET /v1/search/:id`          | Required |
| `POST /v1/search/:id/unlock`  | Required |
| `POST /v1/search/:id/premium` | Required |

Unauthenticated or invalid keys return **401**. A banned account returns **403**. See [HTTP errors](https://osintverse.com/docs/api/errors).

## Dashboard session vs API key

The SearchIn UI uses your logged-in session through the Next.js BFF and charges the **active workspace** (personal or team). Scripts, CI, and third-party apps should use `x-api-key` against `https://apiv1.osintverse.com` — never call internal Next.js `/api/*` routes with an API key.

* **Personal keys** always bill `user.balance`. They ignore any team context.
* **Team keys** are created while a team workspace is selected. They always bill that team’s wallet. See [Teams](https://osintverse.com/searchin/team) for shared wallets and roles. For SSO, MFA, allowlists, and audit export, see [Enterprise onboarding](https://osintverse.com/docs/enterprise-onboarding).

- [Get an API key](https://osintverse.com/dashboard/api)
- [OpenAPI spec](https://osintverse.com/openapi.json) and [Swagger UI](https://apiv1.osintverse.com/docs)
- [API sandbox (free, mock data)](https://osintverse.com/developers/sandbox)
- [Pricing](https://osintverse.com/pricing.json)
