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

# Provider Keys

> Store your OpenAI / Anthropic / Bedrock credentials once, then forward them server-side on every request

A **Provider Key** is an upstream LLM credential (e.g. `sk-...` for OpenAI, `sk-ant-...` for Anthropic) that you store with PromptGuard once. The gateway then attaches it as the `Authorization` header when forwarding to the provider, replacing whatever your app sends.

This is the single biggest reason teams use PromptGuard in front of their LLM provider: your application code never embeds a vendor key, your CI never leaks one, and key rotation is a one-click operation in the dashboard instead of a multi-service deploy.

## When you need this vs. when you don't

<Tabs>
  <Tab title="Use Provider Keys">
    * You're proxying through `/api/v1/proxy/...` endpoints (PromptGuard forwards to the upstream provider on your behalf).
    * You want a single rotation point for your vendor credential.
    * You don't want browser/mobile clients to ever see the upstream key.
    * You're running multi-tenant inference and want PromptGuard to pick the right key per project.
  </Tab>

  <Tab title="Skip Provider Keys">
    * You're only calling `/api/v1/guard` to evaluate prompts before/after your own LLM call. PromptGuard never touches the upstream — there's nothing to forward.
    * You're using a self-hosted model (vLLM, Ollama, Bedrock with IAM) where the credential is provided by the network/IAM layer.
  </Tab>
</Tabs>

## Storing a key

Open **Dashboard → Gateway → Provider Keys → Add Provider Key**, pick the provider, paste the key, give it a name. The key is encrypted at rest with the same envelope used for your dashboard API keys; the plaintext is never written to logs.

```bash theme={"system"}
# Or via the API:
curl -X POST https://api.promptguard.co/dashboard/provider-keys \
  -H "Authorization: Bearer $DASHBOARD_TOKEN" \
  -H "X-CSRF-Token: $CSRF" \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "openai",
    "name": "Production OpenAI",
    "key": "sk-proj-..."
  }'
```

The response contains the key's `id` and `prefix` (the first 12 characters of the masked key, used for display) but **not** the plaintext. To see the plaintext again use the [reveal endpoint](#revealing-an-existing-key) — the action is audit-logged.

## Resolution order

When PromptGuard needs to forward a proxy request, it picks a Provider Key in this priority:

1. The most recently created **active** key for the request's project + provider.
2. If no project-scoped key exists, the most recently created active key for the **user** + provider.
3. If neither exists, the request's own `Authorization` header is forwarded as-is.

This matches the access-list scoping model: project rules win, user-wide rules are the safety net.

## Revealing an existing key

```bash theme={"system"}
curl -X POST https://api.promptguard.co/dashboard/provider-keys/$KEY_ID/reveal \
  -H "Authorization: Bearer $DASHBOARD_TOKEN" \
  -H "X-CSRF-Token: $CSRF"
```

Returns the decrypted plaintext key. This action writes an audit-log entry (`provider_key.reveal`) recording the actor, IP, and timestamp. Use it for break-glass recovery, not as a runtime fetch path — fetching the plaintext on every request defeats the purpose of having PromptGuard hold it for you.

## Rotation

Rotation is a four-line workflow:

1. Create a new Provider Key in the dashboard for the same provider.
2. Mark the old one inactive (`PATCH /dashboard/provider-keys/{old_id}` with `is_active=false`) — *don't delete it yet*. New traffic will pick up the new key on the next request thanks to step 1 of resolution order.
3. Watch the dashboard for failed upstream calls for one rotation cycle.
4. Delete the old key. The audit log retains the deletion event for your retention period.

No application redeploy required.
