# Authentication

> How VectorFast Render API keys work, how to create, list, and revoke them, and the per-key rate limits for REST and MCP requests.

Canonical URL: https://vectorfast.ai/render/docs/authentication
Markdown URL: https://vectorfast.ai/render/docs/authentication.md
Last modified: 2026-10-30

**Short answer:** every `/v1` request and every MCP request carries `Authorization: Bearer vf_live_…`. Keys are shown once, stored only as a hash, limited to 60 requests per 60 seconds each, and revoking one rejects the very next request.

## Key format [#key-format]

```text
vf_live_<key_id: 12 characters><secret: 32 characters>
```

Both parts use lowercase letters and digits. The `key_id` is public: it appears in key listings, as the `k` parameter of signed image URLs, and in rate-limit buckets. The secret part is never shown again after creation; VectorFast stores only its SHA-256 hash.

## Create, list, and revoke keys [#create-list-and-revoke-keys]

Keys belong to your VectorFast account. A key management screen is not built yet; until it ships, these account endpoints use your signed-in browser session (not an API key):

| Request                                         | Result                                                                              |
| ----------------------------------------------- | ----------------------------------------------------------------------------------- |
| `GET /api/render/keys`                          | `{ "keys": [...], "limit": 10 }`: your keys without secrets                         |
| `POST /api/render/keys` with `{ "name": "CI" }` | `201 { "key": {...}, "secret": "vf_live_…" }`; the only time the secret is returned |
| `DELETE /api/render/keys/{key_id}`              | `{ "key": {...} }` with `revoked_at` set                                            |

An account can have up to **10 active keys**; revoked keys do not count. Creating an eleventh returns `400 invalid_params`.

Revocation is immediate: authentication reads the key table on every request and never caches the result, so the next request with a revoked key gets `401 unauthorized`. Signed image URLs that were already issued keep working, because they are verified with the signing secret, not with the API key.

## Use the key [#use-the-key]

```bash
curl https://vectorfast.ai/v1/templates \
  -H "Authorization: Bearer $VECTORFAST_API_KEY"
```

The same header authenticates the [MCP server](/render/docs/mcp). Missing, malformed, unknown, and revoked keys all answer `401` with a `WWW-Authenticate: Bearer` header and the [`unauthorized`](/render/docs/errors#unauthorized) error code.

## Rate limits [#rate-limits]

| Scope                                    | Limit                             | When exceeded                             |
| ---------------------------------------- | --------------------------------- | ----------------------------------------- |
| `/v1/*` and `/mcp`, per key              | 60 requests per 60 seconds        | `429 rate_limited` with `Retry-After: 60` |
| `POST /v1/brand-kits/{id}/logo`, per key | 3 uploads a minute and 10 an hour | `429 rate_limited`                        |

Only authenticated requests count against a key, so unauthenticated traffic cannot use up your allowance. `GET /v1/openapi.json` needs no key.

## Keep keys safe [#keep-keys-safe]

* Keep keys on servers, in CI secrets, or in your agent client's credential store. Never ship one in browser JavaScript, a mobile app, or a public repository.
* Use one key per environment or integration so you can revoke one without breaking the others.
* If a key leaks, revoke it and create a new one; nothing else needs to change.

## OAuth for agents [#oauth-for-agents]

MCP clients currently send an API key as a header. OAuth 2.0 sign-in (authorization code with PKCE) is planned so that clients such as Claude and ChatGPT can connect with a sign-in flow instead of a pasted key. Until it ships, the server answers unauthenticated MCP requests with `401` and an OAuth discovery pointer whose metadata document is not published yet.
