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

# Create a secret

> Store a credential with a provider shortcut or a custom auth scheme, then rotate or delete it without touching your sandboxes.

A secret needs a **name**, a **value** (the real credential), and a way to authenticate — either a [provider shortcut](#provider-shortcuts) or a [custom auth config](#custom-secrets). The value is encrypted on the platform and never returned by the API.

## Provider shortcuts

The fastest path. A shortcut sets the auth scheme and allowed hosts for a known service, so you supply only a name and value:

<CodeGroup>
  ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
  import { Secret } from "@superserve/sdk"

  const secret = await Secret.create({
    name: "openai-prod",
    value: process.env.OPENAI_API_KEY!,
    provider: "openai",
  })

  console.log(secret.hosts)  // ["api.openai.com"]
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
  import os

  from superserve import Secret

  secret = Secret.create(
      name="openai-prod",
      value=os.environ["OPENAI_API_KEY"],
      provider="openai",
  )

  print(secret.hosts)  # ["api.openai.com"]
  ```
</CodeGroup>

Built-in providers span LLM APIs, dev tools, and SaaS, and the list grows over time. `Provider.list()` returns the full current set — names, hosts, and token shape:

<CodeGroup>
  ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
  import { Provider } from "@superserve/sdk"

  const providers = await Provider.list()
  for (const p of providers) {
    console.log(p.name, p.hosts)  // "anthropic" ["api.anthropic.com"]
  }
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
  from superserve import Provider

  for p in Provider.list():
      print(p.name, p.hosts)  # "anthropic" ["api.anthropic.com"]
  ```
</CodeGroup>

## Custom secrets

When there's no shortcut, define the auth yourself with `auth` and `hosts`. `auth` and `provider` are mutually exclusive — pick one.

The `auth.type` controls how the credential is attached to outbound requests:

| `type`    | Attaches as                                          |
| --------- | ---------------------------------------------------- |
| `bearer`  | `Authorization: Bearer <value>`                      |
| `api-key` | a named header — `<header>: <prefix><value>`         |
| `basic`   | HTTP Basic, `<username>:<value>`                     |
| `custom`  | arbitrary header templates referencing `{{ value }}` |

<CodeGroup>
  ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
  // One host, key sent in the Authorization header.
  await Secret.create({
    name: "linear-key",
    value: "lin_api_...",
    hosts: ["api.linear.app"],
    auth: { type: "api-key", header: "Authorization" },
  })
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
  # One host, key sent in the Authorization header.
  Secret.create(
      name="linear-key",
      value="lin_api_...",
      hosts=["api.linear.app"],
      auth={"type": "api-key", "header": "Authorization"},
  )
  ```
</CodeGroup>

### Per-host auth

A single secret can authenticate differently per host — useful when one credential works across, say, a REST API and a git endpoint:

<CodeGroup>
  ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
  await Secret.create({
    name: "github-token",
    value: "ghp_...",
    hosts: ["api.github.com", "github.com"],
    auth: {
      perHost: [
        { hosts: ["api.github.com"], type: "bearer" },
        { hosts: ["github.com"], type: "basic", username: "x-access-token" },
      ],
    },
  })
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
  Secret.create(
      name="github-token",
      value="ghp_...",
      hosts=["api.github.com", "github.com"],
      auth={
          "per_host": [
              {"hosts": ["api.github.com"], "type": "bearer"},
              {"hosts": ["github.com"], "type": "basic", "username": "x-access-token"},
          ]
      },
  )
  ```
</CodeGroup>

<Note>
  `hosts` accepts wildcards (`*.example.com`), but not a whole top-level domain like `*.com`. A wildcard matches subdomains, not the domain itself — list both `example.com` and `*.example.com` if you need each.
</Note>

## Rotation

Replace a secret's value without recreating it. Bound sandboxes keep their environment variable; the new value is used on subsequent requests — no redeploy, no restart.

<CodeGroup>
  ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
  const secret = await Secret.get("openai-prod")
  await secret.rotate(newKey)
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
  secret = Secret.get("openai-prod")
  secret.rotate(new_key)
  ```
</CodeGroup>

## List and delete

<CodeGroup>
  ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
  const secrets = await Secret.list()

  await Secret.deleteByName("openai-prod")
  // or, from an instance:
  await secret.delete()
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
  secrets = Secret.list()

  Secret.delete_by_name("openai-prod")
  # or, from an instance:
  secret.delete()
  ```
</CodeGroup>

<Warning>
  Deleting a secret takes effect **immediately, everywhere it's bound** — any sandbox still using it starts failing at once. The environment variable stays, but its stand-in token no longer works. If you only want to change the value, [rotate](#rotation) instead.
</Warning>

## Next steps

<Card title="Bind to a sandbox" icon="link" href="/secrets/binding">
  Attach the secret to an environment variable so code in the sandbox can use it.
</Card>
