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

# Authentication

> Sign up, mint your own API key, and understand how credits meter Corpus requests.

Corpus is self-serve. Sign in, create a key, and start querying — there is no approval queue and
no per-dataset request. Every account gets the full public data surface immediately; what bounds
usage is **credits**, not permissions.

## Get a key

Sign up at [corpus.onera.app/signup](https://corpus.onera.app/signup) with an email and
password, then create a key from your account page. Your account is provisioned with 100,000
credits on sign-up — no approval step.

<Note>
  There is no password reset by email yet, and addresses are not verified. Store your password
  safely; if you are locked out, contact your Corpus administrator.
</Note>

You can also do it over the API. Sign in for a session token:

```bash theme={"dark"}
curl -X POST "https://corpus-api.onera.app/account/login" --header "content-type: application/json" --data '{"email":"you@company.com","password":"your password"}'
```

Then create a key with it:

```bash theme={"dark"}
curl -X POST "https://corpus-api.onera.app/account/keys?name=laptop" --header "Authorization: Bearer $SESSION_TOKEN"
```

```json theme={"dark"}
{
  "key_id": "key_9f2a1c4e77b30d51",
  "api_key": "ck_live_XU3n...",
  "key_prefix": "ck_live_XU3n",
  "scopes": ["china:read", "data:export", "india:read", "litigation:read", "rag:search", "search:read", "us:read"],
  "message": "Store this key now. It cannot be retrieved again."
}
```

<Warning>
  The `api_key` value is returned **once**. Corpus stores only its SHA-256 digest, so a lost key
  cannot be recovered — create a new one and revoke the old. This also means a disclosure of the
  Corpus database cannot be turned back into working credentials.
</Warning>

Your first sign-in provisions an account and grants **100,000 credits** automatically.

## Use the key

```bash theme={"dark"}
curl "https://corpus-api.onera.app/china/prices?code=sh.600519" --header "X-API-KEY: ck_live_XU3n..."
```

`GET /catalog` is unauthenticated and free. Everything else needs a key and costs credits.

## Permissions

Every self-serve key carries the full public surface. You do not request these individually.

| Permission        | Access                                                           |
| ----------------- | ---------------------------------------------------------------- |
| `us:read`         | United States datasets                                           |
| `india:read`      | India datasets                                                   |
| `china:read`      | China A-share datasets                                           |
| `search:read`     | Document search                                                  |
| `rag:search`      | Natural-language Ask and governed retrieval                      |
| `litigation:read` | India court judgments; also requires `india:read`                |
| `data:export`     | India CSV, XLSX, and Parquet exports; also requires `india:read` |

A valid key without a required permission returns `403 Forbidden`.

### What self-serve does not include

Two surfaces sit outside self-serve because they are legal and privacy controls rather than
product gating, and no amount of credit unlocks them:

* **The PII vault.** Tokenized PAN and litigation-party records live on an isolated database role
  and are not reachable from any public credential at any permission. The court-judgment dataset
  under `litigation:read` is the separate, public-record surface.
* **Redistribution rights.** Reading a dataset is not a licence to republish it. Several sources —
  including China prices and Indian exchange bhavcopy data — are internal-only precisely because
  Corpus holds no redistribution licence for them. `resale:read` is provisioned separately and is
  not part of self-serve. See [Data Provenance](/data-provenance).

## Credits

Each request debits your balance. Reads are cheap; work that fans out across documents or builds
an export costs more.

| Request                                                     | Credits |
| ----------------------------------------------------------- | ------: |
| Any standard read (prices, securities, filings, financials) |       1 |
| `POST /us/search`, `POST /india/search`                     |      10 |
| `POST /ask`                                                 |      25 |
| `GET /india/prices.csv`                                     |      25 |
| `POST /india/exports`                                       |      50 |

Check your balance and the ledger that explains it:

```bash theme={"dark"}
curl "https://corpus-api.onera.app/account/credits" --header "Authorization: Bearer $SESSION_TOKEN"
```

When the balance cannot cover a request, Corpus returns **`402 Payment Required`** — not `403`.
The distinction is deliberate: your key still holds every permission it needs, so the fix is to
top up, not to change your access.

The ledger is append-only: a balance is the sum of its entries, so every debit is attributable to
a route and a key.

## Managing keys

| Operation         | Endpoint                        |
| ----------------- | ------------------------------- |
| Create a key      | `POST /account/keys`            |
| List keys         | `GET /account/keys`             |
| Revoke a key      | `DELETE /account/keys/{key_id}` |
| Balance and usage | `GET /account/credits`          |

Account management uses your **session bearer token**, not an API key. An API key deliberately
cannot mint further keys — otherwise one leaked key would become permanent, self-renewing access.
Revocation takes effect immediately.

Do not put a long-lived API key in browser source code. Frontend applications should obtain a
scoped credential through their authenticated server session.
