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

# Authenticate Requests to the VyomFlow API

> The public VyomFlow API (api.vyomflow.co.in/api/public/v1 and /api/mcp) is authenticated with a scoped, Clerk-issued API key sent as a bearer token.

The public VyomFlow API — `/api/public/v1/*` REST and `/api/mcp` — is authenticated with an API key, not a Clerk session token. API keys are for programmatic and agent access (scripts, MCP clients, CI); they are not a replacement for the browser session flow the first-party app (`https://www.vyomflow.co.in`) uses.

## Creating a key

Sign in to `https://www.vyomflow.co.in` and open **Settings → API Keys** (`/settings/api-keys`), reachable from the app sidebar's "API Keys" row. This page renders Clerk's own `<APIKeys />` widget, so key creation, naming, expiration, and revocation are handled by Clerk directly — VyomFlow never stores or displays the key value itself after creation.

Each key can be granted one or more scopes:

| Scope                | Grants                                       |
| -------------------- | -------------------------------------------- |
| `chats:read`         | List chats, read messages                    |
| `chats:write`        | Create chats                                 |
| `runs:read`          | Read run state, stream a run's output        |
| `runs:write`         | Send messages (dispatch a run), cancel a run |
| `waitpoints:respond` | Answer a pending waitpoint                   |
| `credits:read`       | Read your credit balance                     |

Grant only the scopes a given key actually needs.

## Sending the key

Every request must include:

```text theme={null}
Authorization: Bearer <api-key>
```

<Warning>
  Never place the key in a query parameter or anywhere else in the URL. No public route accepts a key via query string — only the `Authorization` header is honored.
</Warning>

```bash theme={null}
curl -H "Authorization: Bearer $VYOMFLOW_API_KEY" \
  https://api.vyomflow.co.in/api/public/v1/chats
```

## Expiration, revocation, and instance scoping

Keys can be set to expire and can be revoked at any time from the same Settings page. A key is also scoped to the Clerk instance that issued it — if your application ever migrates to a different Clerk instance, keys minted under the previous instance stop working and must be reissued.

## 401 vs. 403

These are distinct failure modes and worth handling differently:

**401 `UNAUTHORIZED`** — the key is missing, malformed, expired, or revoked:

```json theme={null}
{
  "error": { "code": "UNAUTHORIZED", "message": "Authentication required." }
}
```

**403 `FORBIDDEN`** — the key is valid but lacks a scope the endpoint requires:

```json theme={null}
{
  "error": { "code": "FORBIDDEN", "message": "Missing required scope(s): runs:write." }
}
```

A 403 tells you exactly which scope to add; a 401 tells you the credential itself is the problem, not its permissions.

## Secrets hygiene

Treat an API key like any other credential:

* Never commit it to source control.
* Never log it, including in request/response logging middleware.
* Store it in an environment variable or secret manager, not in application code.
* Rotate (revoke and reissue) a key if you suspect it leaked.

## Authenticating the Mintlify playground

The **API Reference** tab on this site includes a live "Try it" panel for every endpoint. To use it, click the panel's bearer-auth field and paste your API key — Mintlify stores it locally in your browser for the session and attaches it as the `Authorization` header on requests the playground sends directly to `https://api.vyomflow.co.in`.

## Security model

* API keys are bearer credentials — anyone holding the key value can use it with whatever scopes it carries.
* Scopes are enforced server-side on every request, not just at key-creation time.
* Keys can expire or be revoked at any time from Clerk's key-management UI.
* Keys are never accepted via query parameter, only the `Authorization` header.
* Secrets must never appear in logs.
* Public CORS (`Access-Control-Allow-Origin: *`) on `/api/public/v1/*` and `/api/mcp` does **not** imply anonymous access — every request still requires a valid, scoped key. This is safe because bearer auth carries no ambient credential (unlike a cookie), so an arbitrary origin reading the response is not a session-riding risk.
* API-key auth is completely independent of first-party browser session auth (`/api/v1/*`, Clerk session cookie/token) — the two never mix on the same route.
* Keys are scoped to the issuing Clerk instance.
* The public API never returns Trigger.dev realtime tokens, stream keys, or other internal Trigger.dev identifiers in any response — the SSE stream (`/api/public/v1/runs/{runId}/stream`) is VyomFlow's own re-emitted event feed, not a pass-through of the internal Trigger.dev token.

## Ownership and access control

Every resource — chats, messages, runs, attachments, and waitpoints — is scoped to the authenticated caller. Requesting a resource owned by another user returns `404 NOT_FOUND`. It never returns `403` or otherwise confirms that the resource exists.
