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

# Credentials

> Manage encrypted API keys for downstream providers

Backs the [Credentials page](/guides/api-keys). Requires a signed-in session; every
operation is scoped to your current organization.

## List credentials

#### `GET /api/admin/credentials`

Returns every **active** credential for your organization. Keys themselves are never
included — only metadata.

```json theme={null}
{
  "credentials": [
    {
      "id": "b3f1...",
      "provider": "prospeo",
      "label": "default",
      "key_hint": "px_live_••••2345",
      "is_active": true,
      "verified_at": null,
      "verify_error": null,
      "created_at": "2026-07-31T18:02:11.000Z"
    }
  ]
}
```

## Save a key

#### `POST /api/admin/credentials`

Encrypts and stores a key. If an active key already exists for the same
`(provider, label)`, it's deactivated (not deleted) first — this is a rotation, not an
overwrite.

### Request body

```json theme={null}
{ "provider": "prospeo", "apiKey": "px_live_...", "label": "default" }
```

<ParamField body="provider" type="string" required>
  One of `harvest`, `serper`, `anthropic`, `prospeo`.
</ParamField>

<ParamField body="apiKey" type="string" required>
  The plaintext key. Must be at least 8 characters. Encrypted (AES-256-GCM) before the
  database write — see [API Keys → How this stays secure](/guides/api-keys#how-this-stays-secure).
</ParamField>

<ParamField body="label" type="string" default="default">
  Lets a single provider have more than one named credential, if that's ever needed.
</ParamField>

### Response

```json theme={null}
{ "ok": true }
```

## Deactivate a key

#### `DELETE /api/admin/credentials/:id`

Marks the credential inactive (`retired_at` set) rather than deleting the row — the
audit trail of every key that was ever active is preserved.

```json theme={null}
{ "ok": true }
```

### Errors

All three endpoints return `401 { "error": "Sign in required" }` without a session.
`POST` returns `400` with a validation message if `provider` or `apiKey` fail
validation. Anything else surfaces as `500` with the underlying error message.
