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

# Creating a secret

> Naming, the recovery window a secret carries from birth, and what the create call does not take.

## Creating a secret

<Tabs>
  <Tab title="Console">
    Go to **Secrets** and choose **Create Secret**. Under **Secret details**
    give it a **Name** and an optional **Description**, paste the first
    **Value**, and leave **Encryption key** on **Platform-managed key
    (default)** unless you want one of your own keys.

    The console takes the value as text and base64-encodes it for you; over
    the API you encode it yourself.
  </Tab>

  <Tab title="API">
    ```bash theme={null}
    POST https://secrets.sa-saopaulo-1.basaltic.sh/v1/secrets
    {
      "name": "prod/api/stripe-key",
      "value": "c3VwZXItc2VjcmV0LXZhbHVl",
      "description": "Stripe live secret key for the payments service"
    }
    ```
  </Tab>

  <Tab title="CLI">
    ```bash theme={null}
    basaltic secrets create \
      --name prod/api/stripe-key \
      --value "$(base64 -w0 <<< 'super-secret-value')" \
      --description "Stripe live secret key for the payments service"
    ```
  </Tab>

  <Tab title="Go">
    ```go theme={null}
    cfg, err := basaltic.NewConfig(ctx,
        basaltic.WithClientCredentials(os.Getenv("BASALTIC_ACCESS_KEY_ID"), os.Getenv("BASALTIC_SECRET_ACCESS_KEY")),
        basaltic.WithRegion("sa-saopaulo-1"),
    )
    if err != nil {
        log.Fatal(err)
    }

    sec, err := secrets.New(cfg).CreateSecret(ctx, &secrets.CreateSecretRequest{
        Name:        "prod/api/stripe-key",
        Value:       []byte("super-secret-value"),
        Description: basaltic.String("Stripe live secret key for the payments service"),
    })
    ```

    `Value` is raw bytes — the SDK base64-encodes it, so do not encode it
    yourself.
  </Tab>
</Tabs>

A secret is created **with** its first value — there is no such thing as an
empty secret. The response is `201` and the secret is at version 1.

<ResponseField name="value" type="base64, 1 byte – 64 KiB">
  Values travel base64-encoded so arbitrary binary payloads survive JSON
  intact. Anything larger than 64 KiB belongs in a [bucket](/storage), with
  the secret holding the reference and the credentials to fetch it — not
  crammed inline.
</ResponseField>

<ResponseField name="name" type="unique per account">
  Matches `^[a-zA-Z0-9][a-zA-Z0-9._/-]{0,255}$`. Slashes are allowed, which is
  why `prod/api/stripe-key` works — and because the CRN is built from the name,
  a path convention becomes directly policy-able:
  `crn:secrets:sa-saopaulo-1:my-account:secret/prod/*`.
</ResponseField>
