# Authentication

All public API requests are authenticated with a **workspace API key**. Create one in the app under **API & Webhooks → API keys**. The full secret is shown **once at creation** — copy it immediately. We only store its SHA-256 hash, so we cannot show it to you again.

Pass the key in the `Authorization` header using the `Bearer` scheme:

```
Authorization: Bearer qac_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

Example:

```bash
curl https://api.qacrow.com/api/me \
  -H "Authorization: Bearer qac_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
```

## Scopes

Each key carries a list of scopes that determine what it can do. Pick the narrowest set that works for your integration.

| Scope       | Grants                                               |
|-------------|-----------------------------------------------------|
| `runs:read` | List and inspect runs and their issues.             |
| `runs:write`| Start and cancel runs (charges credits).           |
| `plans:read`| List and read test plans.                           |
| `plans:write`| Create, update, and delete test plans.             |
| `issues:read`| Read issues across all runs.                       |
| `*`         | Full access. Use sparingly — only for trusted CI.   |

A request that is missing the scope it needs returns `403 forbidden` with a machine-readable error code.

## Operational notes

- **Rotate routinely.** Revoke a key any time from the dashboard; revoked keys stop working immediately.
- **Last-used timestamp.** We update `lastUsedAt` on every successful call so you can spot dormant keys.
- **Never ship keys to a browser.** Use them from a server, a CI job, or a private webhook handler. Browser-bound keys can be lifted from a page's network tab.
- **Workspace identity.** A key acts as the workspace owner. There are no per-user keys.
