Credential Vault
Most sensors don't take a raw secret inline. Instead they reference a secret stored in the named credential vault by its id. You create the credential once, then point one or more sensors at it. The sensor worker resolves the id to the decrypted secret at poll time — the secret is never written into a sensor_configs row and never echoed back by the API.
The vault is org-scoped and admin-only: every endpoint requires an org admin. Credentials are shared between sensors and action channels that consume the same secret shape (a GitHub PAT, for example, is one github_token credential whether a sensor or a GitHub Issue action channel uses it).
Credential types
Each credential has a type that declares its shape. The types a sensor can reference:
| Type | Used by | Secret shape |
|---|---|---|
github_token | GitHub sensor | GitHub PAT with read access to the org/repos |
slack_bot_token | Slack sensor | Bot token, xoxb-… |
google_service_account_json | Google Meet, Google Drive sensors | Full service-account key JSON |
jira_api_token | Jira sensor | Atlassian Cloud API token |
shellcrm_api_key | shell-crm sensor | shell-crm API key (client_id:client_secret) |
Other types (slack_webhook, generic_webhook) exist for action channels and are not referenced by sensors. The Jenkins sensor uses no vault credential — its webhook token is generated server-side at create time.
The live list for your instance:
curl -sS https://your-corveil-host/api/credentials/types \
-H "Authorization: Bearer <admin-session-or-key>"Returns each registered type with its human-readable display name.
Create a credential
POST /api/credentials
{
"type": "github_token",
"name": "acme-readonly-pat",
"secret": "ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}curl -sS -X POST https://your-corveil-host/api/credentials \
-H "Authorization: Bearer <admin-session-or-key>" \
-H "Content-Type: application/json" \
-d '{"type":"github_token","name":"acme-readonly-pat","secret":"ghp_..."}'The response echoes the stored credential's metadata — including its id — but never the secret. The secret is validated at write time for the given type, so a malformed value is rejected with a 400 before it lands in the vault.
Copy the returned id; that's what you put in a sensor's credentials block.
List, read, update, delete
| Method & path | Purpose |
|---|---|
GET /api/credentials | List all credentials (metadata only). Add ?type=github_token to filter. |
GET /api/credentials/{id} | Fetch one credential's metadata. |
PATCH /api/credentials/{id} | Rename ({"name": "..."}) or rotate the secret ({"secret": "..."}). |
DELETE /api/credentials/{id} | Remove a credential. |
How a sensor references a credential
When you create a sensor, the credentials block holds the credential id (a UUID), not the secret:
{
"sensor_type": "github",
"name": "Acme GitHub",
"config": { "org": "acme" },
"credentials": { "token": "6f1c2b8e-0a4d-4d6a-9f2e-1c3b5a7d9e11" }
}The token key is the credential field the GitHub sensor declares; its value is the id returned by POST /api/credentials. Every sensor guide in this section lists exactly which credential type its credential field expects.
The Add sensor UI renders a dropdown of matching credentials for each credential field, so you rarely assemble this JSON by hand — but the same shape is what the API expects for programmatic setup.