## Credentials

A credential is the client ID and client secret that your integration exchanges for an access token, as [API Basics](/docs/get-started/api-basics#authentication) describes. Your Talli representative provides your organization's first credential. With the endpoints on this page you can create a second one, rename a credential, rotate its secret and delete it. In the routes below, `…` stands for `/v3/distribution-manager`.

| Endpoint | What it does |
|  --- | --- |
| `GET …/credentials` | Lists your organization's credentials, without their secrets. |
| `GET …/credentials/{clientId}` | Reads one credential, without its secret. |
| `POST …/credentials` | Creates a credential and returns its client secret. |
| `PATCH …/credentials/{clientId}` | Renames a credential. |
| `POST …/credentials/{clientId}/:rotate-secret` | Replaces the client secret and returns the new one. |
| `DELETE …/credentials/{clientId}` | Deletes a credential. |


The two `GET` endpoints need the `credentials:view` scope, the four others `credentials:manage`. Your organization can hold at most 2 credentials. The sandbox and production each have their own credentials: call these endpoints on the base URL of the environment whose credentials you manage. A call that returns `502` failed or could not be confirmed; retry it. The API reference documents every request and response.

Only a Full access credential's token holds `credentials:manage`. With Read-only credentials only, ask a console user.

## Create a credential

```bash
curl --request POST \
  --url 'https://api.talli.ai/v3/distribution-manager/credentials' \
  --header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{ "name": "Reporting", "scopesPreset": "ReadOnly" }'
```

`name` is 1 to 128 characters, not only spaces, with no control characters. It must be unique in your organization, and names that differ only in case count as different names. `scopesPreset` sets what the credential can do:

| `scopesPreset` | Access |
|  --- | --- |
| `FullAccess` | Every scope of an administrator of your organization, `credentials:manage` included. |
| `ReadOnly` | Every `:view` scope. The credential can read your data and cannot change anything. |


Its preset is set when you create it and cannot be changed.

The `201` response holds the credential with its `clientSecret`, `tokenUrl` and `audience`. Talli returns the client secret only in this response and keeps no copy, so store it in your secret manager at once. If you lose it, rotate it.

The call returns `409` with `CREDENTIAL_LIMIT_REACHED` when your organization already has 2 credentials, and `409` with `CREDENTIAL_NAME_TAKEN` when another credential has the name.

## Rename a credential

`PATCH …/credentials/{clientId}` takes `name` and renames the credential. Any token that holds `credentials:manage` can call it, the credential's own included. The name rules of the create apply, and a name that another credential has returns `409` with `CREDENTIAL_NAME_TAKEN`.

The name is the only thing that changes. To give an integration other access, create a credential with the access you need, move your integration to it, then delete the old one, as in [Rotate with two credentials](#rotate-with-two-credentials).

## Rotate a secret in place

```bash
curl --request POST \
  --url 'https://api.talli.ai/v3/distribution-manager/credentials/YOUR_CLIENT_ID/:rotate-secret' \
  --header 'Authorization: Bearer YOUR_ACCESS_TOKEN'
```

The `200` response holds the new `clientSecret`, returned only this once. The old secret stops working within 30 seconds, and your integration cannot request access tokens until it uses the new secret. Access tokens issued before the rotation keep working until they expire. A Full access credential can rotate its own secret. If the call returns `502` or another `5xx`, the old secret may already have stopped working: rotate again.

## Rotate with two credentials

To replace a secret with no gap in access, use a second credential:

1. Create a new credential with the access your integration needs.
2. Move your integration to the new client ID and secret, and check that it gets access tokens.
3. Delete the old credential, with the new credential's token if it is Full access, or from the console.


A credential cannot delete itself: a delete called with the old credential's own token returns `409` with `CANNOT_DELETE_OWN_CREDENTIAL`. This rotation needs a free slot, so with 2 credentials, rotate in place instead.

## Delete a credential

```bash
curl --request DELETE \
  --url 'https://api.talli.ai/v3/distribution-manager/credentials/YOUR_CLIENT_ID' \
  --header 'Authorization: Bearer YOUR_ACCESS_TOKEN'
```

The call returns `204`, and the credential can no longer request access tokens. Access tokens it already holds keep working until they expire, but a call with them that creates, changes, rotates or deletes a credential returns `403` with `CALLER_CREDENTIAL_NOT_FOUND`.

A credential's token never deletes your organization's last credential: the last credential is the one that calls, so the call returns `409` with `CANNOT_DELETE_OWN_CREDENTIAL`. A console user can delete it, and your organization then has no credential until a console user creates one.

## Access tokens

An access token lasts 24 hours: the token response holds `"expires_in": 86400`. Cache the token and send it with every call until it is close to expiring, then request a new one.

> Request a new access token only when the current one expires. Talli limits token requests, and can suspend a credential that requests a token on every call.