# Targets and provider keys

> Set, replace or remove the provider key of a target, and add or delete your own HTTPS targets for the hosted egress gateway.

A **target** is a provider API your agents may call: one of the [catalog](https://developers.openwaf.dev/egress/cloud/reference/#catalog) (OpenRouter, OpenAI, Anthropic and others) or a **custom target** you add. Each target has at most one **provider key** for the whole organization; every agent allowed to call the target uses it. Every change needs an organization-wide `admin`.

## How keys are kept

- A key is write-only. OpenWAF stores it encrypted in its credential store and never returns it, logs it or keeps it in its database; the API and the dashboard only show its fingerprint (`sha256:` and 12 hex characters), who set it and when.
- It can be set from the dashboard or the API, never over MCP: it would pass through the assistant's conversation. MCP can remove a key.
- A key is 1 to 8,192 characters, without spaces or control characters.
- The gateway caches a key for up to five minutes, so a replaced or removed key can still be used for that long.

## Set or replace a key

Saving a key replaces the current one for every agent at once.

**Dashboard**

In **AI egress → Credentials**, choose **Set key** (or **Replace key**) on the provider's row, paste the key and save.
**API**

```sh
read -rs KEY && printf '{"secret":"%s"}' "$KEY" | curl -sS -X PUT \
  "https://dash.openwaf.dev/v1/orgs/$ORG/egress/targets/openai/credential" \
  -H "Authorization: Bearer $OPENWAF_TOKEN" -H "Content-Type: application/json" --data-binary @- && unset KEY
```


## Remove a key

Agents that call the target get `502 credential_resolution_failed` until a new key is set.

**Dashboard**

In **AI egress → Credentials**, remove the key from the provider's row and confirm.
**API**

```sh
curl -sS -X DELETE "https://dash.openwaf.dev/v1/orgs/$ORG/egress/targets/openai/credential" \
  -H "Authorization: Bearer $OPENWAF_TOKEN" -H "X-Change-Reason: provider no longer used"
```
**MCP**

`egress_remove_credential` with `target` and `reason`, then again with `confirm=true`.


## Add a custom target

Any HTTPS API your agents call with an API key, such as a self-hosted model server or a provider outside the catalog.

| Field | Rule |
|---|---|
| `id` | 2 to 32 lowercase letters, digits or hyphens, starting with a letter, and not a catalog id. It appears in the gateway URL |
| `name` | Display name, up to 100 characters |
| `base_url` | `https://` on the default port 443, with a public DNS name: no IP address, credentials, query or fragment, and no `.local`, `.internal`, `.localhost`, `.lan`, `.home.arpa`, `.onion` or reverse-DNS names |
| `auth_header` | Header that carries the key. Default `Authorization` |
| `auth_prefix` | Text written before the key, up to 32 characters. Default `Bearer ` with `Authorization`, empty with any other header |

The gateway also checks at request time that the name resolves only to public addresses (`403 ssrf_blocked`).

**Dashboard**

In **AI egress → Credentials**, choose **Add custom target**, fill in **Identifier**, **Name**, **Base URL**, **Auth header** and **Auth prefix**, and save. Then set its key.
**API**

```sh
curl -sS -X POST "https://dash.openwaf.dev/v1/orgs/$ORG/egress/targets" \
  -H "Authorization: Bearer $OPENWAF_TOKEN" -H "Content-Type: application/json" \
  -d '{"id": "my-llm", "name": "In-house LLM", "base_url": "https://llm.example.com/v1"}'
```
**MCP**

`egress_add_target` with `id`, `name`, `base_url`, optionally `auth_header` and `auth_prefix`, and `reason`; then again with `confirm=true`. Set its key in the dashboard or the API.


## Delete a custom target

Deleting a custom target deletes its key too, and cannot be undone. It is refused with `409 target_in_use` while an agent allows it: remove it from those agents first. Catalog targets cannot be deleted (`422 invalid`); remove their key instead.

In the dashboard, delete it from its row in **AI egress → Credentials**; in the API send `DELETE …/egress/targets/{id}`; over MCP call `egress_remove_target`.

## Audit log

Each change leaves an entry in the organization's audit log: `egress.credential.set` (with the fingerprint), `egress.credential.delete`, `egress.target.create` and `egress.target.delete`.
