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

# Create a Secret

`Novita.secret``.create()` creates a team-scoped Secret and its first immutable version. It returns `SecretBinding` metadata and does not include the real value. The `hosts` allow list controls which hosts the real value may be substituted for on outbound HTTPS requests.

## Prerequisites

```bash CLI icon="terminal" theme={"system"}
export OPENAI_API_KEY="your-openai-api-key"
```

## Example

The example creates a Secret, launches a sandbox that references it via `secret_envs`, uses the placeholder from inside the sandbox to call an allow-listed host, and kills the sandbox when done.

<CodeGroup>
  ```python Python icon="python" theme={"system"}
  import os
  import uuid

  from novita_sandbox import Novita

  secret_name = f"openai-example-{uuid.uuid4().hex[:12]}"
  openai_api_key = os.environ["OPENAI_API_KEY"]
  novita = Novita()

  # Handle secret: create a team-scoped Secret. The real value is stored
  # encrypted; substitution is only allowed for hosts in the allow list.
  novita.secret.create(
      name=secret_name,
      value=openai_api_key,
      hosts=["api.openai.com"],
      description="Sandbox Secrets example",
  )

  # Create sandbox: map an env var to the Secret name.
  # The env var holds a placeholder, not the real value.
  sandbox = novita.sandbox.create(
      secret_envs={"OPENAI_API_KEY": secret_name},
  )

  try:
      # Use the secret: the proxy substitutes the real value in flight
      # because api.openai.com is on the allow list.
      result = sandbox.commands.run(
          'curl -s https://api.openai.com/v1/models '
          '-H "Authorization: Bearer $OPENAI_API_KEY"'
      )
      print(result.stdout)
  finally:
      # Kill sandbox when done.
      sandbox.kill()
  ```

  ```js JavaScript & TypeScript icon="js" theme={"system"}
  import 'dotenv/config'
  import { randomUUID } from 'crypto'
  import { Novita } from 'novita-sandbox'

  const secretName = `openai-example-${randomUUID().slice(0, 12)}`
  const openaiApiKey = process.env.OPENAI_API_KEY
  const novita = new Novita()

  // Handle secret: create a team-scoped Secret. The real value is stored
  // encrypted; substitution is only allowed for hosts in the allow list.
  await novita.secret.create({
    name: secretName,
    value: openaiApiKey,
    hosts: ['api.openai.com'],
    description: 'Sandbox Secrets example',
  })

  // Create sandbox: map an env var to the Secret name.
  // The env var holds a placeholder, not the real value.
  const sandbox = await novita.sandbox.create({
    secretEnvs: { OPENAI_API_KEY: secretName },
  })

  try {
    // Use the secret: the proxy substitutes the real value in flight
    // because api.openai.com is on the allow list.
    const result = await sandbox.commands.run(
      'curl -s https://api.openai.com/v1/models -H "Authorization: Bearer $OPENAI_API_KEY"'
    )
    console.log(result.stdout)
  } finally {
    // Kill sandbox when done.
    await sandbox.kill()
  }
  ```
</CodeGroup>

## Parameters

| Parameter     | Description                                                                                                                                                         |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`        | Secret name, unique among active Secrets in the current team.                                                                                                       |
| `value`       | The real credential to store. It is encrypted and never returned by the API.                                                                                        |
| `hosts`       | Allow list of hosts the value may be substituted for. At least one host; hostname only (no protocol, path, port, or query). Wildcards support the `*.` prefix only. |
| `description` | Optional human-readable description.                                                                                                                                |

<Note>
  If an active Secret with the same name already exists in the current team, the call returns `409 Conflict`. `novita.secret.create()` returns `SecretBinding` metadata only — it never returns the real value.
</Note>
