> ## Documentation Index
> Fetch the complete documentation index at: https://cadenya.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Store and use a secret

> A hands-on lesson. Store a credential as a workspace secret, reference it in a tool header, and let Cadenya inject it at call time.

Your tools need credentials, and those credentials should never sit in your tool configuration in plain text. A secret holds the value once. You reference it in a tool header as `${NAME}`, and Cadenya swaps in the real value when it calls the tool. The value never comes back out through the API.

In this lesson you store an API token as a workspace secret and wire it into a tool set.

## What you need

* A workspace, with your API key in `CADENYA_API_KEY` and your workspace ID in `WORKSPACE_ID`.
* A credential to store, such as a third-party API token.

## Step 1: Store the secret

In the sidebar, open **Secrets** and create one. Give it a **Name** and a **Value**. Cadenya uppercases the name and turns spaces and hyphens into underscores to form the reference, so `stripe_api_key` becomes `${STRIPE_API_KEY}` and `billing-key` becomes `${BILLING_KEY}`. Stick to letters, digits, and underscores so the reference reads exactly like the name you typed.

<Frame caption="The Create secret form with a name and a value">
  <img src="https://mintcdn.com/cadenya/uBVC-4MupBcJ2jhQ/images/docs/secrets/secret-form.svg?fit=max&auto=format&n=uBVC-4MupBcJ2jhQ&q=85&s=e4fc753365676e9e5a9c73edf998dd70" alt="The Create secret form with a Name field and a Value field" width="1200" height="675" data-path="images/docs/secrets/secret-form.svg" />
</Frame>

The same step from your terminal:

```bash theme={null}
curl https://api.cadenya.com/v1/workspaces/$WORKSPACE_ID/workspace_secrets \
  -H "Authorization: Bearer $CADENYA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "metadata": { "name": "stripe_api_key" },
        "spec": { "value": "sk_live_replace_me" }
      }'
```

See [Create a workspace secret](/docs/api-reference/workspacesecretservice/create-a-new-workspace-secret) for the full request.

<Warning>
  Cadenya stores the value encrypted and never returns it on a read. A response carries the name and labels, never the value. Lose track of a secret and you rotate it, you do not read it back.
</Warning>

## Step 2: Reference it in a tool header

A workspace secret is reachable by any [tool set](/docs/guides/tool-sets) in the workspace. Put the reference in the adapter's headers, where the provider expects the credential:

```bash theme={null}
curl https://api.cadenya.com/v1/workspaces/$WORKSPACE_ID/tool_sets \
  -H "Authorization: Bearer $CADENYA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "metadata": { "name": "Billing", "externalId": "billing" },
        "spec": { "adapter": { "type": "http", "http": {
          "baseUrl": "https://api.stripe.com",
          "headers": { "Authorization": "Bearer ${STRIPE_API_KEY}" }
        } } }
      }'
```

See [Create a tool set](/docs/api-reference/toolservice/create-a-new-tool-set) for the full request. Cadenya leaves the `${STRIPE_API_KEY}` text in the configuration. The substitution happens later, at the moment of the call. The same `${NAME}` reference works in MCP and OpenAPI adapter headers, not only HTTP.

## Step 3: Watch it resolve at call time

Assign the tool set to an agent and run an objective that calls one of its tools. When the agent fires the call, Cadenya resolves `${STRIPE_API_KEY}` against your secrets and sends the real token in the header. The objective's events show the tool call, but never the secret value.

Cadenya catches a missing secret when you connect the tool set, not in production. Sync an MCP or OpenAPI tool set whose header references a name that does not exist and the sync fails with an `unresolved_secrets` error that names the missing `${NAME}`, so a typo surfaces at setup.

## Rotate a secret

Rotate by updating the value and keeping the name. Every `${NAME}` reference picks up the new value on the next call, so nothing else changes. Pass the secret `id` from the create response.

```bash theme={null}
curl -X PATCH https://api.cadenya.com/v1/workspaces/$WORKSPACE_ID/workspace_secrets/$SECRET_ID \
  -H "Authorization: Bearer $CADENYA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "spec": { "value": "sk_live_rotated" }, "updateMask": "spec.value" }'
```

The old value stops working the moment the update lands, so cut over any caller that holds it. See [Update a workspace secret](/docs/api-reference/workspacesecretservice/update-a-workspace-secret) for the full request.

## Per-run secrets

A workspace secret is shared across the workspace, which suits a long-lived service token. For a credential scoped to one run, such as a single customer's short-lived token, pass an [objective secret](/docs/guides/run-an-objective) when you start the objective. An objective secret overrides a secret of the same name at any wider scope, so the same `${NAME}` reference resolves to the per-run value.

There are three scopes, and the narrowest wins: an objective secret, then a tool set secret, then a workspace secret. To see which one a tool call used, read the call by ID and check `resolvedSecrets`, which names the key and its source without ever revealing the value.

## What you built

You stored a credential once, referenced it by name in a tool header, and let Cadenya inject it at call time without ever exposing it. Add more secrets and reference each one the same way.

## Going further

<CardGroup cols={2}>
  <Card title="How secrets work" icon="key" href="/docs/guides/secrets">
    Encryption, interpolation, and how workspace and objective secrets layer.
  </Card>

  <Card title="Connect a tool set" icon="screwdriver-wrench" href="/docs/guides/tool-sets">
    The adapters whose headers carry your secret references.
  </Card>
</CardGroup>
