# Create Credential

- **Method:** `POST`
- **Path:** `/api/v1/credentials`
- **Operation ID:** `create_credential`
- **Tags:** credentials

This tenant's own provider key, test-account login, webhook key or GitHub token, written to Secrets
Manager and named by an `awssm://` ref.

The ref that comes back is what goes into a run spec's `providers.entries[].credential_ref` - or, for
kind `account`, into `target.seed.accounts`, for `webhook` into `connectors.webhook.secret_ref`, and for
`github` into `connectors.github.token_ref` - and only this tenant's specs may name it: another
tenant's spec naming it is refused at `POST /runs` with a 422. The value is never returned, logged,
put on a span, or stored anywhere but the secret.

What is refused: a name that is not one readable segment, a kind no worker resolves, an empty or
oversized value, and a value of the wrong shape for its kind - JSON on a kind whose credential is one
string, a non-object on `google-cloud`, or an `account` that is not a valid secret-store entry (422
each); a name this tenant already has, or whose secret
already exists (409). There is no replace: rotation is `DELETE` then `POST`, so a mistyped name cannot
retire a working key.

## Effective servers

- `https://api.saram.sh`

  Saram

## Authentication

- **HTTPBearer**: HTTP bearer

  a Saram API key (`sk_saram_<env>_...`) or a person's AuthKit access token, as `Authorization: Bearer <credential>`. Both are told apart by shape and produce the same principal.

## Request body

**Required:** `true`

**Content type:** `application/json`

schema: `CredentialWrite`, no additional properties

`POST /api/v1/credentials`: the one request body in this API that carries a secret.

The API stores `value` once and never answers it back: no response anywhere has a `value` field. To change a
credential, delete it and write it again.

- **`kind` (required)**: `string`

  Which provider this key is for, as the model string's prefix names it: anthropic, bedrock, openai, openrouter, azure, google, google-cloud, litellm. A run spec entry naming this credential must be on the same kind. Or account: a test-account login for a persona, named in a run spec's target.seed.accounts (or target.auth.secret\_ref) instead. Or webhook: the key a run spec's connectors.webhook is signed with, named there as secret\_ref. Or github: a token that may write issues on one repository, named as connectors.github.token\_ref and used only where the Saram GitHub App is not installed on that repository.
- **`name` (required)**: `string`

  What to call this credential: lowercase letters, digits, underscore and dash, up to 64 characters. The last segment of the secret's name and part of the ref you will paste into a run spec, so pick something a person can read - anthropic, openai-judge.
- **`value` (required)**: `string`, format: `password`, writeOnly

  The provider key itself. Written to Secrets Manager and never returned, logged or echoed; for google-cloud it is the service-account JSON document, and for account it is one secret-store entry as a JSON object (email, password, inbox, notes, cookies, basic, headers).

**Example:**

```json
{
  "name": "",
  "kind": "",
  "value": ""
}
```

## Responses

### 201 Successful Response

**Content type:** `application/json`

schema: `CredentialRecord`, no additional properties

One of this tenant's credentials, a provider key or a test account, as all three routes answer it.
Metadata only.

- **`created_at` (required)**: `string`, format: `date-time`
- **`id` (required)**: `string`
- **`kind` (required)**: `string`
- **`name` (required)**: `string`
- **`secret_ref` (required)**: `string`

  The awssm:// ref to paste into a run spec as providers.entries\[].credential\_ref, for an account into target.seed.accounts, as connectors.webhook.secret\_ref for a webhook key, or as connectors.github.token\_ref for a github token. Only this tenant's specs may name it.
- **`deleted_at`**: `string | null`, format: `date-time`

  Set on the record `DELETE` answers with, absent on a live one: the secret is gone and the name is free.

**Example:**

```json
{
  "id": "",
  "name": "",
  "kind": "",
  "secret_ref": "",
  "created_at": "",
  "deleted_at": ""
}
```

### 403 the API key lacks the credentials:write scope, or the request carries no tenant

### 409 this tenant already has a credential by that name

### 422 bad name, a kind no worker resolves, or a value of the wrong shape for its kind

## Schemas

- `CredentialRecord` — shown above.
- `CredentialWrite` — shown above.
