Manage provider credentials
Store the OpenAI, Anthropic, Google, Azure or local-model API keys the gateway calls out with, and assign each to one account or one group.
- Version: 0.4
- Role: admin_user
- Type: task
A credential is an upstream LLM provider's API key — the key CID222 presents when it calls OpenAI, Anthropic, Google, Azure OpenAI or a local model server. Without a working credential there is no chat, no AI filter builder and no conversational help assistant.
What do I need?
- Licence
- Any
- Role
admin_user
Prerequisites
- You hold an API key from the provider, with quota on it.
- The appliance can reach the provider — or, on an air-gapped box, a local OpenAI-compatible endpoint is running.
- The account or tenant group that should own the credential already exists.
Note
These are not the same as gateway API keys. A credential is what CID222 uses to call a provider;
a cid_key_ is what a machine client presents to call CID222. Those live on
Access keys.
/assets/screenshots/credentials@0.4.pngAdd a credential
Open the page
Select Administration → Credentials.
The summary line under the table reads {total} credentials · {active} active on this page ·
keys encrypted at rest.
Start a new credential
Select Add credential.
The Create New Credential dialog opens.
Name it and choose the provider
Enter a Name — for example Production OpenAI Key — and pick the provider under
AI Provider.
The dialog notes Provider cannot be changed after creation. To move a credential to another provider, delete it and create a new one.
Choose the owner
Set Assign To:
- Tenant Group (Shared) — every member of the group you pick under Tenant Group can use it. This is how a department shares one provider key.
- Individual Tenant — only the account you pick under Tenant can use it.
A credential has exactly one owner. The dialog notes Assignment cannot be changed after creation.
Paste the key
Enter the provider's key in API Key.
The field is masked as you type, and the note The API key will be masked and encrypted states what happens to it. For Azure OpenAI, also fill Azure Endpoint (required) with your resource URL, and API Version (optional) if you need a version other than the default.
Set the optional limits
Fill Rate Limit (per min) and Daily Budget (USD) if you cap this credential, and Region (optional) where the provider needs one.
Leaving the rate limit empty applies the default of 60 requests per minute.
Save
Select Create.
A Credential created successfully toast appears, and the appliance immediately tests the
key once — reporting either Credential verified ({ms}ms) or Credential saved but
unreachable: {error}.
Test a credential
CID222 never calls a provider on a schedule of its own. Health is only ever the result of a test you ran, or of a real request.
Run the test
Select Open menu → Test connection on the credential's row.
The gateway makes one cheap call to the provider with a five-second timeout.
Read the result
The Health column changes.
Verified ✓ with Provider reachable ({ms}ms), or Unreachable ✗ with Unreachable:
{error}. Hovering the cell shows the last error and Last checked {when}. Untested
means nobody has run a test yet — it does not mean broken.
Rotate a key
Open the credential
Select the credential's row.
The Edit Credential dialog opens with AI Provider and Assign To disabled, and the key field labelled API Key (leave empty to keep current). The stored key is never prefilled.
Paste the new key and save
Enter the new key and select Update.
A Credential updated successfully toast appears. Run Test connection afterwards — an edit does not re-test on its own.
Retire a credential
Set Status to Inactive in the edit dialog to stop the gateway selecting it while keeping the row, or select Open menu → Delete to remove it. Deletion is confirmed with This will permanently delete the credential and This action cannot be undone.
Warning
Deleting the last active credential for a provider deactivates that provider's models. Users who depended on it lose those models from their model list.
How the gateway picks a credential
For a request from a given account to a given provider, the gateway resolves in this order and stops at the first match:
- An active credential owned by that account for that provider.
- An active credential owned by any tenant group the account belongs to, for that provider.
If neither exists the request fails with No active credential found for tenant {id} and provider
{code}. An inactive credential is never selected at either step, and a group credential is only
reachable through membership — so removing somebody from a group removes their access to that
provider.
How keys are stored
The provider key is encrypted at rest with AES-256-GCM, under a key derived from JWT_SECRET, and
is written as v1:-prefixed ciphertext. The API never returns it: list and detail responses carry
only a masked form showing the first characters and the last four.
Danger
Rotating JWT_SECRET makes every stored provider key undecryptable. The rows survive but the
keys read as empty and every provider call fails until you paste each key in again.
Rows written before encryption existed pass through unchanged, so an appliance upgraded from an early build can still hold a plaintext key. Re-saving the key on such a row encrypts it.
Fields reference
| Field | Required | Rule | What it does |
|---|---|---|---|
| Name | Yes | Free text | Identifies the credential in the list. Not sent to the provider |
| AI Provider | Yes | One of the configured providers | Which provider this key belongs to. Locked after creation |
| Assign To | Yes | Tenant Group (Shared) or Individual Tenant | Chooses the single owner. Locked after creation |
| Tenant Group / Tenant | Yes | An existing group or account | The owner |
| API Key | Yes on create | Free text, masked | The provider secret. Left empty on edit, the stored key is kept |
| Azure Endpoint (required) | Azure only | http or https URL | The Azure OpenAI resource endpoint |
| API Version (optional) | No | Version string | Azure OpenAI API version. Defaults to 2024-08-01-preview |
| Region (optional) | No | Free text | Provider region, where one applies |
| Rate Limit (per min) | No | Number | Requests per minute. Defaults to 60 |
| Daily Budget (USD) | No | Number | A recorded daily budget for this credential |
| Status | No | Active or Inactive | Only an active credential is selected by the resolver. Defaults to Active |
List columns
| Column | Shows |
|---|---|
| Name | The credential's name |
| Provider | The provider badge |
| API Key | The masked key. The real key is never returned |
| Assigned to | Group: {name} or Tenant: {name} |
| Rate limit | {limit} / min |
| Budget / day | The daily budget, where one is set |
| Status | Active or Inactive |
| Health | Untested, Verified ✓ or Unreachable ✗, with Last checked {when} |
| Created | The date the credential was created |
Note
The Filter credentials… box and the Status filter narrow only the page in front of you. Page through the list rather than concluding a credential is absent.
Verify
- The Health column reads Verified ✓ after Test connection.
- Open Models. The provider's models are listed and carry no No route warning.
- Sign in as an account that owns the credential — directly or through its group — and start a chat. The provider's models are offered and a message completes.
- Credential changes are not written to the audit trail in 0.4: no
RESOURCE_CREATED,RESOURCE_UPDATEDorRESOURCE_DELETEDrow is produced. Use the list and the health column as the record.
If it fails
- Credential must be assigned to either a tenant or a tenant group, but not both — the request named both owners or neither. In the dashboard this cannot happen; a scripted call can.
- Provider with ID
{n}not found — the provider id does not exist on this appliance. - Tenant with ID
{id}not found / Tenant group with ID{id}not found — the owner does not exist, or you are anadmin_useracting outside your own scope. Out-of-scope owners refuse identically to non-existent ones, so the answer does not reveal which. - Credential with ID
{n}not found — the credential does not exist, or it belongs to a department you do not own. - Credential saved but unreachable:
{error}/ Unreachable:{error}— the key was stored but the provider did not answer. Check the key itself, then egress from the appliance to the provider, then the endpoint URL if this is Azure or a local model. - Test failed to run — the test itself could not be executed. Reload and try again.
- Failed to create credential / Failed to update credential / Failed to delete credential — the gateway refused the write; the specific message above accompanies it.
- Only administrators can manage provider credentials. — your role cannot use this page.
- No AI provider is configured yet banner on Models — no credential exists at all yet. Add one here.
Next steps
- Models — check which models each provider now offers, and which have no route.
- Tenant groups — share one credential across a department.
- Access keys — issue the gateway keys machine clients use to reach CID222 itself.
Last updated on