> For the complete documentation index, see [llms.txt](https://verbatim-ai.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://verbatim-ai.gitbook.io/docs/integration/security.md).

# Security Best Practices

Read this before you ship. The API's security model rests on **you** protecting one thing — your RSA private key — and handing untrusted clients only short-lived, scoped [access tokens](/docs/integration/access-keys.md).

***

## The one rule that matters most

> **Never let your RSA private key leave your backend.**

Anyone holding the private key can mint valid tokens for your **entire organization**. That means:

* ❌ Never embed it in browser JavaScript, mobile apps, desktop apps, or any client you distribute.
* ❌ Never commit it to a git repository, paste it into an issue, or log it.
* ❌ Never send it to Verbatim — only the **public** key is ever uploaded.
* ✅ Store it with restrictive permissions (`chmod 600`) or, better, in a secrets manager (Vault, AWS/GCP Secrets Manager, etc.).
* ✅ Give it the smallest possible blast radius: separate keys per environment (staging vs production) and per service.

If a browser or mobile client needs API access, mint an [access token](/docs/integration/access-keys.md) for it instead.

***

## Transport

* **Always use HTTPS.** Use the `https://…verbatim-ai.com` base URLs. Never send a token over plain HTTP — it can be captured in transit.
* Don't put tokens in URLs where you can avoid it (query strings land in server logs, proxy logs and browser history). Prefer the `Authorization` / `X-Access-Token` **headers**.

***

## Least privilege

* **Scope every access token** to exactly what the client needs and nothing more (see [scopes](/docs/integration/authentication.md#scopes-domainaction)). Scope is mandatory for access tokens for this reason.
* For RSA JWTs, remember an **empty scope means unrestricted**. Reserve unscoped JWTs for trusted server-to-server automation; add a `scope` claim when a narrower token will do.
* Prefer separate keys/tokens per integration so you can revoke one without disrupting the others.

***

## Keep token lifetimes short

* Access tokens default to **1 hour** (`ttl` = 3600s). Keep them short; mint fresh ones as needed rather than issuing long-lived tokens.
* Sign RSA JWTs with a short `exp` too (minutes for interactive flows). A leaked token stops working when it expires.
* Provide a lightweight "get me a fresh token" endpoint on your backend for frontends, and refresh **before** expiry.

***

## Rotation & revocation

* **Rotate keys** periodically and immediately on any suspected compromise. Because published PEM content is write-once, rotation is: generate a new pair → publish it → point your signer at the new key id → delete the old key. See [key lifecycle](/docs/integration/rsa-keys.md#key-lifecycle--rotation).
* **Deactivate** a key to instantly (and reversibly) stop honoring tokens signed with it; **delete** to retire it permanently.
* **Revoke access tokens** on sign-out or suspected leak with `DELETE /v1/auth/access-token/{token}`.
* Have a written plan for "a key/token leaked": deactivate/revoke first, rotate, then investigate.

***

## Handling tokens in the browser

* Treat any access token as a bearer secret for its (short) lifetime.
* Avoid persisting tokens in `localStorage` when you can keep them in memory; if you must persist, prefer short TTLs and clear on logout.
* Scope browser tokens tightly (usually read + query only). A leaked, tightly-scoped, short-lived token has limited value.
* Never expose the backend endpoint that *mints* tokens without its own authentication — otherwise anyone can request tokens for your organization.

***

## CORS & origins

The API responds with permissive CORS so browser clients can call it directly. **CORS is not an authorization boundary** — it controls which sites the browser lets read responses, not who may call the API. Your real access control is the **token and its scope**. Don't rely on origin checks for security; rely on short-lived, scoped tokens.

***

## Checklist

* [ ] Private key stored server-side only, `chmod 600` or in a secrets manager.
* [ ] Separate keys per environment (staging / production).
* [ ] Browser/mobile clients use scoped access tokens, never the private key.
* [ ] Access token scopes are minimal.
* [ ] Token lifetimes are short; frontends refresh before expiry.
* [ ] HTTPS everywhere; tokens in headers, not URLs.
* [ ] Documented rotation & revocation procedure.
* [ ] Token-minting endpoint on your backend is itself authenticated.

***

**See also:** [Authentication](/docs/integration/authentication.md) · [RSA keys](/docs/integration/rsa-keys.md) · [Access keys](/docs/integration/access-keys.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://verbatim-ai.gitbook.io/docs/integration/security.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
