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

# Store credentials

> Put a provider credential somewhere your apps can use it without ever seeing it.

A bucket is the credential container an SDK, MCP server, or workspace service points at. Services declare what is *enabled*; buckets hold what a running app actually *uses*.

Secrets are resolved server-side by the Engine at dispatch time. They never appear in a config file, a plan receipt, or a generated package.

## Pick a bucket before you write to one

```bash theme={null}
fused-cli bucket list
fused-cli bucket show default
fused-cli bucket services default
```

A listed bucket is one you can *see*, not necessarily one you may use. Choose a visible candidate, run the action you intended, and let the permission check decide. If it is denied, stop and report it — do not create a fallback bucket.

Create one only when you actually need isolation:

```bash theme={null}
fused-cli bucket create prod-credentials
```

<Warning>
  A `buckets:` block in `workspace.yaml` configures an *existing* bucket. It cannot create one. If no bucket of that name exists, apply fails with "bucket not found" rather than creating it. `bucket create` is the only way.
</Warning>

## Store a secret

Values are rejected in argv so they cannot survive in shell history or a process listing. Pipe them instead.

```bash theme={null}
printf '%s' "$TOKEN" | fused-cli secret set stripe --value-stdin
```

Multi-field schemes are still **one** value, joined with `;`:

```bash theme={null}
printf '%s' 'username=x;password=y' | fused-cli secret set jira --type basic --value-stdin
printf '%s' 'cert=...;key=...'       | fused-cli secret set acme --type mtls  --value-stdin
```

There is no `--username`, `--password`, `--cert`, or `--key` flag, and these are not two separate secrets set in two calls.

Or prompt for each field:

```bash theme={null}
fused-cli secret set jira --interactive
```

<Note>
  `secret set` is an upsert with no apply step. It takes effect on the next request. Re-running it with a new value *is* how you rotate a credential — there is no versioning and no grace period, so the old value is simply gone.
</Note>

## Flags

### `secret set`

| Flag            | What it does                                                | Example                                                                                             |
| --------------- | ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| `--value-stdin` | Reads the credential from stdin                             | `printf '%s' "$T" \| fused-cli secret set stripe --value-stdin`                                     |
| `--interactive` | Prompts per field and selects the scheme directly           | `fused-cli secret set jira --interactive`                                                           |
| `--type`        | Auth family: `api_key`, `bearer`, `basic`, `oauth`, `mtls`… | `printf '%s' "$T" \| fused-cli secret set jira --type bearer --value-stdin`                         |
| `--auth-name`   | Exact Registry scheme, when one family has several          | `printf '%s' "$T" \| fused-cli secret set jira --type api_key --auth-name legacy-key --value-stdin` |
| `--bucket`      | Targets a bucket other than the default                     | `printf '%s' "$T" \| fused-cli secret set stripe --bucket prod-credentials --value-stdin`           |
| `--expires-at`  | Advisory expiry metadata, RFC3339                           | `printf '%s' "$T" \| fused-cli secret set stripe --expires-at 2026-12-31T23:59:59Z --value-stdin`   |

`--expires-at` is advisory only. Listings flag an expired secret; nothing auto-rotates and nothing blocks requests when it passes.

If a service declares more than one scheme, a bare `set` only auto-picks when there is exactly one. When two schemes share a type, `--auth-name` is required — the CLI fails an ambiguous selection rather than taking the first.

### `secret list`

| Flag       | What it does                 | Example                                             |
| ---------- | ---------------------------- | --------------------------------------------------- |
| `--bucket` | Bucket to inspect (required) | `fused-cli secret list --bucket prod-credentials`   |
| `--limit`  | Rows to read                 | `fused-cli secret list --bucket default --limit 50` |

Secret values are never read back — metadata only.

## Store a non-secret value

Some providers need a non-secret piece of configuration, like a tenant ID that appears in the host name.

`value set` takes five positional arguments, and only the third comes from a fixed set:

```text theme={null}
fused-cli value set <bucket-name-or-id> <service-slug> <location> <key-name> <value>
fused-cli value delete <bucket-name-or-id> <service-slug> <key-name>
fused-cli value list <bucket-name-or-id>
```

| Position              | Is                                              | Example           |
| --------------------- | ----------------------------------------------- | ----------------- |
| `<bucket-name-or-id>` | Yours                                           | `sendbird-bucket` |
| `<service-slug>`      | The service this value belongs to               | `sendbird`        |
| `<location>`          | One of `env`, `body`, `query`, `header`, `path` | `env`             |
| `<key-name>`          | Yours                                           | `SENDBIRD_APP_ID` |
| `<value>`             | The value itself                                | `your-app-id`     |

```bash theme={null}
fused-cli value set sendbird-bucket sendbird env SENDBIRD_APP_ID your-app-id
fused-cli value list sendbird-bucket
fused-cli value delete sendbird-bucket sendbird SENDBIRD_APP_ID
```

The `env` namespace here is the bucket's own value store — it does not read an operating-system environment variable.

## Inject a bucket value into a request

An SDK or MCP service can pull those values into the outgoing request at dispatch time, so a tenant ID or account prefix never has to be hardcoded per environment.

Usually you will not write these by hand — [`sdk init` and `mcp init` generate them](/app/build-an-sdk#init-fills-in-the-routing-you-would-otherwise-miss) for whichever server-template variables your selected operations declare, leaving you to supply the value.

```yaml theme={null}
services:
  sendbird:
    version: "v3"
    operations: [listChannels]
    injections:
      - location: server_variable
        name: app_id
        value: ${bucket.env.SENDBIRD_APP_ID}
        mode: force
```

References always resolve against **that app's own `bucket:`** — there is no way to name a different bucket here, unlike a `kind: webhook` secret. An ordinary injection value may also mix a tag with surrounding text, such as `"Bearer ${bucket.secrets.API_KEY}"`.

`location: server_variable` is stricter than the rest. Its value must be a complete `${bucket.env.KEY}` or `${bucket.values.KEY}` reference — never a literal, never interpolated, never a secret — because host routing has to stay non-secret and reviewable. Plan checks `name` against the service and operation server templates and rejects an undeclared one.

### Which value wins

| Source                                        | Precedence                                          |
| --------------------------------------------- | --------------------------------------------------- |
| Workspace `execution_policy.server_variables` | Final authority                                     |
| Injection with `mode: force`                  | Overrides connection-resource input                 |
| Connection-resource input                     | Overrides a `default` injection                     |
| Injection with `mode: default`                | Supplies the app value ahead of a provider fallback |
| Provider-declared fallback                    | Last resort                                         |

An omitted `mode` canonicalizes to `force`.

<Warning>
  A host template must keep a fixed registrable anchor such as `.sendbird.com`. Whole-host or public-suffix-only forms like `https://{host}` or `https://{tenant}.com` fail closed — the Engine validates the resolved value and the final HTTPS URL before dispatch.
</Warning>

## Inspect a bucket

```bash theme={null}
fused-cli bucket secrets prod-credentials
fused-cli bucket values prod-credentials
fused-cli bucket sdks prod-credentials
```

## Permissions

| Action                         | Needs                       |
| ------------------------------ | --------------------------- |
| List or show a bucket          | `bucket.read`               |
| Read values                    | `bucket.values.read`        |
| List secret metadata           | `credentials.metadata.read` |
| Create a bucket, change values | `bucket.manage`             |
| Change secrets                 | `credentials.manage`        |

<Card title="Connect a user's account" icon="user-check" href="/bucket/connect-user-accounts">
  Static credentials cover one identity. OAuth covers one per end user.
</Card>
