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

# Authentication

> Mint a v2 API key and authorize every request.

Every v2 endpoint requires a bearer token. v1 keys (`pl_v1_*`) do **not** work - they're managed by a separate system and the secrets aren't recoverable. Mint a fresh v2 key.

## Mint a key

1. Open **[Settings → Integrations → API](https://productlane.com/settings/integrations/api)**.
2. Click **Create API key**.
3. Pick a preset:
   * **Full access** - every scope. Equivalent to a v1 key.
   * **Custom** - check only the scopes you need.
4. Copy the secret. **It's shown once and never again.** If you lose it, revoke and mint a new one.

v2 keys are prefixed `pl_v2_`. The dashboard shows the first four characters after the prefix as a preview so you can distinguish keys without revealing the secret.

## Use the key

Set the `Authorization` header on every request:

```bash theme={null}
curl -H "Authorization: Bearer pl_v2_..." \
  https://productlane.com/api/v2/me
```

The workspace id is **inferred from the key** - you never pass it in the URL.

## Scopes

Keys can be locked down to specific resources. The available scopes are:

```
threads:read       threads:write
messages:write
comments:write
contacts:read      contacts:write
companies:read     companies:write
changelogs:read    changelogs:write
docs:read          docs:write
portal:read
projects:read      projects:write
issues:read        issues:write
admin
```

`admin` is required for member management and webhook management.

If a request hits an endpoint your key doesn't have the scope for, we return `403 scope_required`:

```json theme={null}
{
  "error": {
    "code": "scope_required",
    "message": "This endpoint requires the `threads:write` scope.",
    "details": {
      "required": ["threads:write"],
      "granted": ["threads:read"]
    },
    "request_id": "req_..."
  }
}
```

The `details` payload tells you exactly which scope to add. Edit the key in the dashboard and either widen the existing key's scopes or mint a new, narrower one.

## Verify a key

`GET /me` confirms the key is valid and tells you which workspace and scopes it carries:

```bash theme={null}
curl -H "Authorization: Bearer $PRODUCTLANE_V2_KEY" \
  https://productlane.com/api/v2/me
```

```json theme={null}
{
  "workspace_id": "wks_abc123",
  "api_key_id": "key_def456",
  "scopes": ["threads:read", "threads:write"]
}
```

## Common auth errors

| HTTP | Code                      | Meaning                                                          |
| ---- | ------------------------- | ---------------------------------------------------------------- |
| 401  | `unauthenticated`         | Missing or malformed `Authorization` header.                     |
| 401  | `unauthenticated`         | Key revoked or unknown.                                          |
| 403  | `scope_required`          | Key is valid but doesn't carry the scope this endpoint needs.    |
| 403  | `forbidden`               | Authenticated but blocked for another reason (e.g. plan gating). |
| 410  | `unsupported_key_version` | You passed a v1 key (`pl_v1_*`) to a v2 endpoint. Mint a v2 key. |

## Rotate a key

1. Mint a new key with the same scopes.
2. Deploy it.
3. Once traffic has moved over, revoke the old key in the dashboard.

There's no atomic "rotate" endpoint - a brief overlap is the safe way to do it.
