Create a credential
const url = 'https://your-org.evershell.ai/v1/credentials';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"name":"example","provider":"google","kind":"oauth2_authorization_code","scopes":["example"],"provider_config":{},"service_account_json":"example","client_secret":"example","api_key":"example","password":"example","personal":true,"allow_user_override":true}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://your-org.evershell.ai/v1/credentials \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "name": "example", "provider": "google", "kind": "oauth2_authorization_code", "scopes": [ "example" ], "provider_config": {}, "service_account_json": "example", "client_secret": "example", "api_key": "example", "password": "example", "personal": true, "allow_user_override": true }'Permissions: auth:write or auth:write:own. Members
carrying only auth:write:own can create personal
Authorization Code overrides on themselves; everything
else (org-scoped credentials, other AC kinds) needs
auth:write (unscoped).
Creates a credential record + uploads the durable secret to
Vault. Required body fields branch on (provider, kind):
kind: oauth2_jwt_bearer(Google SA) —service_account_json(full SA JSON key)kind: oauth2_client_credentials+kind: oauth2_authorization_code(BYO OAuth) —client_secret,provider_config: { client_id, tenant_id (Microsoft only) }kind: api_key(static token) —api_keykind: basic_auth—password,provider_config: { username }kind: query_api_key—api_key
For Authorization Code (oauth2_authorization_code), the
response carries a next link pointing to
POST /credentials/{id}/oauth/start — call that to obtain the
provider’s authorize URL and redirect the browser there.
Authorizations
Section titled “Authorizations ”Request Body required
Section titled “Request Body required ”object
Operator-chosen identifier referenced from caps.yaml transforms.
Example
googleoauth2_jwt_bearer_with_subject is Google domain-wide
delegation — same SA JSON key as the durable credential,
but mint requests carry a sub claim that impersonates the
email in provider_config.subject.
object
Kind=oauth2_jwt_bearer only.
Kind=oauth2_client_credentials | oauth2_authorization_code.
Kind=api_key | query_api_key.
Kind=basic_auth.
Kind=oauth2_authorization_code only — create a user-scoped override.
Kind=oauth2_authorization_code only — let members create personal overrides of an org-scoped row.
Responses
Section titled “ Responses ”Created
object
Non-null for personal (per-user) credentials
oauth2_jwt_bearer_with_subject is Google domain-wide
delegation — same SA JSON key as the durable credential,
but mint requests carry a sub claim that impersonates the
email in provider_config.subject.
Vault path to the durable secret. Reference only — the secret value is never returned.
Provider-specific structured config. Common shapes:
{client_id, tenant_id} for Microsoft client_credentials,
{subject} for Google domain-wide delegation,
{username} for basic_auth. Never carries the secret.
object
Timestamp of the most recent successful mint by the proxy’s broker.
Short status code from the most recent mint attempt — populated alongside status=needs_reauth to surface the broker’s terminal-error reason.
AC-kind only — lets members create personal overrides
Populated for kind=oauth2_jwt_bearer; grant this email access to whatever resources the agent should reach.
Example
{ "provider": "google", "kind": "oauth2_authorization_code", "status": "active"}Validation failure
object
object
Closed-enum slug (e.g. permission_denied, validation_error, workspace_not_found)
Human-readable summary
Server-generated request id for correlating logs
Optional structured context. Validation errors land at
details.fields as a per-field map.
object
Example
{ "error": { "code": "permission_denied", "message": "caller lacks required scope", "request_id": "7f3a9c2e" }}Tenant is past_due, decommissioning, or trial-expired
object
object
Closed-enum slug (e.g. permission_denied, validation_error, workspace_not_found)
Human-readable summary
Server-generated request id for correlating logs
Optional structured context. Validation errors land at
details.fields as a per-field map.
object
Example
{ "error": { "code": "permission_denied", "message": "caller lacks required scope", "request_id": "7f3a9c2e" }}auth_disabled — credentials subsystem isn’t configured
on this CP, or Vault was unreachable when the durable
secret was uploaded.
object
object
Closed-enum slug (e.g. permission_denied, validation_error, workspace_not_found)
Human-readable summary
Server-generated request id for correlating logs
Optional structured context. Validation errors land at
details.fields as a per-field map.
object
Example
{ "error": { "code": "permission_denied", "message": "caller lacks required scope", "request_id": "7f3a9c2e" }}