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

# Authentication

> How Audity Personal Access Tokens (PATs) work, scopes, rotation, and what gets logged.

## Overview

Audity uses **Bearer token authentication** for all agent API calls. The token is a Personal Access Token (PAT) you generate from your Audity settings page. Every API request must include:

```http theme={null}
Authorization: Bearer aky_<your-token>
```

A PAT resolves to your Clerk user identity in middleware. From there, every request is gated by exactly the same stack that protects the web app:

* **Subscription tier**, gates which features are callable
* **Supabase Row-Level Security**, you only ever see rows your `user_id` owns
* **Credit balance**, write operations that cost credits deduct from your balance
* **Rate limits**, per-token

There is no separate permission model for agents.

## Token format

```
aky_<32 random base62 characters>
```

The `aky_` prefix is reserved. The middleware uses it to distinguish PATs from Clerk session JWTs without doing a database lookup on every request.

Tokens are stored as bcrypt hashes plus an HMAC lookup digest. The plaintext leaves the database after creation and is never written to logs.

## Generating a token

1. Sign in at [app.auditynow.com](https://app.auditynow.com)
2. Go to **Settings → API Tokens**
3. Click **Create Token**
4. Choose:
   * **Label**, a human-readable name (e.g., `Claude on my MacBook`, `n8n production`)
   * **Scopes**, `read`, `write`, or both
   * **Expiry** (optional), set an expiry date or leave blank
5. Click **Create**
6. **Copy the token immediately**, it will not be shown again

<Warning>
  We cannot recover a lost token. If you lose one, revoke it and create a new one.
</Warning>

You can have up to **10 active tokens per user**. Creating an 11th returns 409, revoke an old one first.

## Scopes

| Scope   | What it allows                                                                              |
| ------- | ------------------------------------------------------------------------------------------- |
| `read`  | All `GET` requests on agent-allowlisted routes                                              |
| `write` | All `POST` / `PATCH` / `DELETE` on agent-allowlisted routes (also implicitly grants `read`) |

For most integrations, **`read` + `write`** is what you want. Use `read` only for read-only dashboards or reporting where the agent should never spend credits or mutate state.

`GET`, `HEAD`, and `OPTIONS` requests don't require a scope (read is implicit). `POST`, `PATCH`, and `DELETE` require `write`.

## What's exposed to PATs (the agent surface)

The PAT-accessible route allowlist is intentionally narrow. As of v1:

* `GET /api/user/current`, `GET /api/user/tier`, `GET /api/user/credits`
* `GET /api/projects`, `POST /api/projects`
* `GET /api/projects/{id}`, `PATCH /api/projects/{id}`
* `POST /api/projects/{id}/audit-analysis`, `GET /api/projects/{id}/audit-analysis`
* `POST /api/agent/projects/{id}/audit-analysis/async`, `GET /api/agent/jobs/{id}`
* `GET /api/projects/{id}/opportunities`
* `GET /api/projects/{id}/deliverables`
* `GET /api/lead-generation/leads`, `GET /api/lead-generation/leads/{id}`
* `POST /api/lead-generation/leads/{id}/convert`
* `GET/POST/PATCH/DELETE /api/agent/readylinks` and `/api/agent/readylinks/{id}`
* `GET/POST/PATCH/DELETE /api/agent/assessment-configs` and `/api/agent/assessment-configs/{id}`
* All `/api/nucleus/{captures,memories,contacts,insights,suggestions}` endpoints documented in the [API Reference](/api-reference/openapi.json)

Routes outside the allowlist return `403 PAT_ROUTE_NOT_ALLOWED`. This includes web research, billing, admin, and the PAT management endpoints themselves.

<Note>
  The async audit endpoint requires current document and interview analysis records for the project. If those prerequisites are missing, it returns a prerequisite error; use the synchronous project audit endpoint for the standard end-to-end synthesis path.
</Note>

## Tier requirements

Tier gating is enforced on every request the same way the web app enforces it. Public pricing names can change faster than API enum names, so treat `GET /api/user/tier` as the source of truth for your account. Roughly:

* **Read-only or lead-generation-focused plans** can read available workspace data but may not be able to create projects, convert leads, or spend credits.
* **Paid audit-capable plans** unlock write operations, subject to token scope and available credits.
* **Higher plans** may unlock additional quotas and features such as higher usage limits or custom-domain ReadyLinks.

For current pricing and exact tier features, see [the Audity pricing page](https://auditynow.com/pricing). A 403 with `requiredTier` in the body tells you what to upgrade to.

## Rate limits

Per-token, enforced by Audity's existing rate limiter:

| Endpoint class                                         | Limit                               |
| ------------------------------------------------------ | ----------------------------------- |
| Standard reads                                         | 100 / minute                        |
| Writes (create, update, delete)                        | 20 / minute                         |
| Async job polling (`GET /api/agent/jobs/{id}`)         | 120 / minute                        |
| Capture submissions (`POST /api/nucleus/capture/note`) | 30 / hour                           |
| Expensive operations (audit synthesis)                 | Lower internal guardrails may apply |

A 429 response includes `Retry-After` (in seconds). Back off and retry.

## Rotation

We recommend rotating PATs every 90 days. Multiple active tokens make this zero-downtime:

1. Create a new token with the same label suffixed `-rotate` (or with the new date)
2. Update your agent's connection settings to use the new token
3. Verify with a `GET /api/user/current` round-trip
4. Revoke the old token

Both tokens work in parallel until you revoke the old one. There's no cutover window.

## Revocation

To revoke a token: **Settings → API Tokens → Revoke**. The token stops working immediately on the next request (no caching).

Revoke immediately if:

* A token may have been exposed (committed to git, pasted into a chat, leaked to a screen recording)
* A device is lost or stolen
* An integration goes rogue or you stop trusting it

Revocation is a soft delete (`revoked_at` is set). The row stays in the database for audit history.

## Security guidelines

<AccordionGroup>
  <Accordion title="Never commit tokens to git">
    Add `.env`, `.env.local`, `*.env` to your `.gitignore`. Use environment variables or a secret manager.
  </Accordion>

  <Accordion title="Never paste tokens into chat conversations">
    Tokens belong in connection settings, not message bodies. If you paste one accidentally, revoke it.
  </Accordion>

  <Accordion title="Use one token per integration">
    One token per device or integration. Easier to revoke a single compromised token without breaking everything else.
  </Accordion>

  <Accordion title="Set expiry for shared environments">
    For tokens used in n8n, Zapier, or shared workflows, set a 30–90 day expiry. Forces rotation hygiene.
  </Accordion>

  <Accordion title="Use read-only tokens where you can">
    If your agent only fetches data (dashboards, reporting), give it a `read` token. Reduces blast radius.
  </Accordion>
</AccordionGroup>

## Error codes

Authentication and validation errors return JSON with a stable `code` field. Branch on `code` (the human-readable `error` string may change). All error responses on `/api/...` routes are JSON, the middleware never returns HTML for an auth failure.

### Authentication and authorization

| HTTP | `code`                           | When it fires                                                                                                                                                         |
| ---- | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 401  | `PAT_MALFORMED`                  | The `Authorization` header carries a `Bearer aky_...` token whose format is invalid (wrong length, wrong charset). Don't retry, regenerate the token.                 |
| 401  | (no code)                        | A correctly-shaped `aky_...` token that doesn't resolve to an active key. The token was revoked, expired, or never existed. Generate a new one.                       |
| 403  | `PAT_ROUTE_NOT_ALLOWED`          | Valid PAT, but the route is not on the agent allowlist. Use a browser session for non-allowlisted routes.                                                             |
| 403  | `PAT_NOT_SUPPORTED_FOR_ENDPOINT` | Valid PAT hitting a defense-in-depth Clerk-only endpoint (e.g. `/api/user/api-keys`). PATs cannot manage other PATs.                                                  |
| 403  | `PAT_SCOPE_INSUFFICIENT`         | Token is valid but missing a scope. The `error` message lists what's missing (e.g. `Token missing required scope(s): write`). Generate a token with the right scopes. |
| 503  | `PAT_DISABLED`                   | The agent API is gated behind a kill switch (`AUDITY_AGENT_API_ENABLED`). If you see this on prod, the switch is off, contact support.                                |

### Endpoint validation errors

| HTTP | `code`                     | Endpoint                                                       |
| ---- | -------------------------- | -------------------------------------------------------------- |
| 400  | `EMPTY_PATCH`              | `PATCH /api/projects/{id}` with no allowed fields              |
| 400  | `INVALID_DESCRIPTION_TYPE` | `PATCH /api/projects/{id}` with a non-string `description`     |
| 400  | `DESCRIPTION_TOO_LONG`     | `PATCH /api/projects/{id}` with `description` over 5,000 chars |

## Out of scope for v1

A few capabilities are intentionally **not** exposed via the agent API:

* **Document upload.** Files (PDFs, transcripts, contracts) are uploaded through the web app. Agents read them via project detail and trigger analysis on what's already there.
* **Streaming responses.** Audity is not a chatbot. Agents call the API for structured outputs, not for token-by-token completion. Stream prose with your own LLM; use Audity for synthesis, memory, and project state.
* **Deliverable document regeneration.** The synthesis pipeline produces stakeholder memos and other deliverables when `audit-analysis` runs. Agents read them via `GET /api/projects/{id}/deliverables`.
* **Web research.** The `POST /api/projects/{id}/web-research` route exists but is not on the agent allowlist in v1. It runs from the web app.
* **PAT management via PAT.** Tokens are created and revoked from the browser. PATs cannot manage other PATs.

If you need any of these in your workflow, [tell us](mailto:support@auditynow.com).

## What gets logged

Two systems run in parallel:

**The Nucleus action audit log** (`nucleus_actions` table). Populated by the `withAudit` wrapper that sits around Nucleus's internal AI tools and slash commands when you use Nucleus *inside the web app*. Records the user, tool, payload, and outcome for every Nucleus tool call.

**The agent API has its own surface and is not currently mirrored into `nucleus_actions`.** PAT writes (create project, trigger audit, create memory, etc.) are persisted in their own tables (the rows themselves are the record), but there's no per-call audit trail in v1. If you need an audit log for compliance reasons, run your agent-side requests through your own logging proxy until we ship a dedicated PAT activity feed.

## What's stored when you create a token

* A **bcrypt hash** of the plaintext token
* An **HMAC lookup digest** so the resolver can find the row without scanning every hash
* The **first 6 characters** (e.g. `aky_a1b`) for visual identification in your settings
* The label, scopes, expiry, created/last-used timestamps

When a request comes in, the middleware extracts the token, computes the lookup digest, fetches the row, verifies the bcrypt hash, updates `last_used_at`, and lets the request proceed with your normal Clerk identity attached.

## Programmatic access

The PAT mechanism is designed for **user-initiated, user-pasted** integrations: a consultant pastes their token into Claude or n8n. Embedded SaaS-to-SaaS auth (where another product needs to issue and rotate tokens on a user's behalf) is out of scope today. If you have a use case like that, [reach out](mailto:support@auditynow.com).

## Need help?

* [How to connect Claude (Desktop / claude.ai)](/guides/claude)
* [How to use with Claude Code (no connector)](/guides/claude-code)
* [How to connect ChatGPT](/guides/chatgpt)
* [Email support](mailto:support@auditynow.com)
