# Authentication (/docs/authentication)

Daytona authenticates SDK, CLI, and API requests with a project [API key](/docs/api-keys). The key identifies the [project](/docs/projects) that owns the sandboxes you create and carries the [permissions](/docs/api-keys#scopes) a request may use.

<AuthenticationVisual />

## Get an API key [#get-an-api-key]

1. Go to [Daytona Dashboard ↗](https://app.daytona.com/dashboard/keys)
2. Select the project in the header switcher
3. Click <Button>Create API Key</Button>
4. Enter <Button>Key Name</Button>
5. Select <Button>write:sandboxes</Button> permission
6. Click <Button>Create API Key</Button>
7. Copy and save the API key as an environment variable

## Environment variables [#environment-variables]

Daytona resolves configuration in order of precedence:

1. Configuration in code
2. Environment variables

| **Variable**              | **Description**                                                                                |
| ------------------------- | ---------------------------------------------------------------------------------------------- |
| **`DAYTONA_API_KEY`**     | Your Daytona API key. <br /> Required unless `DAYTONA_JWT_TOKEN` is set                     |
| **`DAYTONA_JWT_TOKEN`**   | A JWT instead of an API key. <br /> Optional; needs `DAYTONA_PROJECT_ID`                     |
| **`DAYTONA_PROJECT_ID`**  | The project a JWT is scoped to. <br /> Required with `DAYTONA_JWT_TOKEN`                   |

### .env file [#env-file]

```bash
DAYTONA_API_KEY=YOUR_API_KEY
```

### Shell [#shell]

<Tabs syncKey="shell">
<TabItem label="Bash/Zsh" icon="seti:shell">

```bash
export DAYTONA_API_KEY=YOUR_API_KEY
```

</TabItem>
<TabItem label="Windows PowerShell" icon="seti:powershell">

```powershell
$env:DAYTONA_API_KEY="YOUR_API_KEY"
```

</TabItem>
</Tabs>

## Authenticate the SDK [#authenticate-the-sdk]

Construct the client without arguments to read the environment variables, or pass the configuration in code. Every call made through the client sends the API key or, with a JWT, a short-lived project token the client exchanges the JWT for.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
from daytona import Daytona, DaytonaConfig

# Using environment variables
daytona = Daytona()

# Using explicit configuration
config = DaytonaConfig(api_key="YOUR_API_KEY")

daytona = Daytona(config)

# Pick the region per create
sandbox = daytona.v2.create(region="earth")
```

| **Parameter**     | **Type** | **Description**                                                                                                                                   |
| ----------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `api_key`         | str    | Falls back to `DAYTONA_API_KEY`. When neither this nor `jwt_token` is set, the first access to `daytona.v2` raises `UnauthorizedError`.           |
| `jwt_token`       | str    | A JWT instead of an API key. Falls back to `DAYTONA_JWT_TOKEN`. Needs `project_id`; setting both `api_key` and `jwt_token` raises `BadRequestError`. |
| `project_id`      | str    | The project a JWT is scoped to. Falls back to `DAYTONA_PROJECT_ID`.                                                                               |
| `request_timeout` | float  | Per-request HTTP timeout in seconds. `0` disables the timeout.                                                                                    |

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
import { Daytona } from '@daytona/sdk'

// Using environment variables
const daytona = new Daytona()

// Using explicit configuration
const daytonaWithConfig = new Daytona({ apiKey: 'YOUR_API_KEY' })

// Pick the region per create
const sandbox = await daytonaWithConfig.v2.create({ region: 'earth' })
```

| **Parameter**    | **Type** | **Description**                                                                                                                                   |
| ---------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `apiKey`         | string | Falls back to `DAYTONA_API_KEY`. When neither this nor `jwtToken` is set, the first access to `daytona.v2` throws `DaytonaAuthenticationError`.  |
| `jwtToken`       | string | A JWT instead of an API key. Falls back to `DAYTONA_JWT_TOKEN`. Needs `projectId`; setting both `apiKey` and `jwtToken` throws `DaytonaValidationError`. |
| `projectId`      | string | The project a JWT is scoped to. Falls back to `DAYTONA_PROJECT_ID`.                                                                               |
| `requestTimeout` | number | Per-request HTTP timeout in milliseconds. `0` disables the timeout.                                                                               |

</TabItem>
</Tabs>

### Close the client [#close-the-client]

Close the client when your program no longer needs it. The client holds network resources between calls, such as the connection that reports sandbox state changes, and closing it releases them. Closing does not stop or delete any sandbox. Closing an already closed client does nothing.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
from daytona import Daytona

# Close the client when the block exits
with Daytona() as daytona:
    sandbox = daytona.v2.create()

# Close the client explicitly
daytona = Daytona()
sandbox = daytona.v2.create()
daytona.close()
```

<Callout type="note" title="Notes">
- Use `AsyncDaytona` with `async with` or `await daytona.close()` in asynchronous code.
</Callout>

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
import { Daytona } from '@daytona/sdk'

const daytona = new Daytona()
const sandbox = await daytona.v2.create()

// Close the client explicitly
await daytona.close()
```

<Callout type="note" title="Notes">
- Declare the client with `await using` to close it when the scope exits.
</Callout>

</TabItem>
</Tabs>

## Authenticate the CLI [#authenticate-the-cli]

Sign in once and the CLI saves the session in its active profile, so following commands need no key or flags. After a browser or device login, the CLI selects your personal organization and its default project the first time and remembers your last selection afterwards. Sandbox commands use a short-lived platform token where the deployment issues one. Toolbox access, and sandbox commands on other deployments, use a project API key the CLI mints on your behalf with a 24-hour expiry; logging out attempts to revoke these keys.

<Tabs syncKey="language">
<TabItem label="CLI" icon="seti:shell">

```bash
# Browser login
daytona login --api-url https://api.daytona.com

# Device-code login on a host without a browser
daytona login --device --api-url https://api.daytona.com

# Store an API key in the active profile
daytona login --token YOUR_API_KEY --api-url https://api.daytona.com

# Confirm who you are and what is selected
daytona whoami

# Create a sandbox with the saved session
daytona sandbox create

# Remove the saved session from this machine
daytona logout
```

```bash
# Using environment variables (DAYTONA_API_KEY, DAYTONA_API_URL)
daytona sandbox create

# Using explicit flags
daytona sandbox create --api-key YOUR_API_KEY --api-url https://api.daytona.com
```

| **Flag**    | **Type** | **Description**                                                                                  |
| ----------- | -------- | ------------------------------------------------------------------------------------------------ |
| `--api-key` | string | Takes precedence over `DAYTONA_API_KEY`. Either one replaces the saved login for that command.   |
| `--api-url` | string | Takes precedence over `DAYTONA_API_URL`, and either one overrides the URL stored in the profile. |
| `--profile` | string | Selects a profile other than the active one. `DAYTONA_PROFILE` does the same.                    |

</TabItem>
</Tabs>

### Profiles [#profiles]

A profile is a named connection: an API URL, a credential, and the selected organization and project. One machine can keep several profiles, for example one per organization or deployment, and switch between them without signing in again. A command uses the profile it names, then the profile in the environment, then the active profile, then the profile named `default`. Signing in to a new profile creates it, and makes it active only when no profile is active yet. Deleting the active profile makes `default` active when it exists, otherwise no profile is active.

<Tabs syncKey="language">
<TabItem label="CLI" icon="seti:shell">

```bash
# Sign in to a second profile
daytona login --profile work --api-url https://api.daytona.com

# List profiles
daytona profile list

# Run one command with another profile
daytona sandbox list --profile work

# Make a profile active for following commands
daytona profile use work

# Delete a profile and its saved credentials
daytona profile delete work
```

| **Argument** | **Type** | **Description** |
| ------------ | -------- | --------------- |
| `name` | string | Sets the profile name: from `1` to `64` ASCII letters, digits, `.`, `_`, or `-`, excluding `.` and `..`. This argument is required. |

The output of the list has the following columns:

| **Column**   | **Description**                                                         |
| ------------ | ----------------------------------------------------------------------- |
| (unnamed)    | `*` for the active profile.                                             |
| `NAME`       | Profile name.                                                           |
| `API URL`    | The API URL the profile connects to.                                    |
| `CREDENTIAL` | How the profile authenticates: `oidc` for a browser or device login, `token` for a static credential stored with `--token`, such as a project or organization API key. |
| `ORG`        | ID of the selected organization.                                        |
| `PROJECT`    | ID of the selected project.                                             |

<Callout type="note" title="Notes">
- A profile named by `--profile` or `DAYTONA_PROFILE` must exist, except in `daytona login`, which creates it.
- Deleting a profile attempts to revoke its CLI-minted project keys. The profile is deleted from the machine even when the revocation fails, and the keys expire after 24 hours.
</Callout>

</TabItem>
</Tabs>

### Confirmation prompts [#confirmation-prompts]

At a terminal, the CLI asks for confirmation before destructive and billable commands. The setting applies to every profile on the machine. Turning it off removes the prompt only: when the CLI is not attached to a terminal, prints JSON or YAML, or runs with the `CI` environment variable set, those commands still require an explicit confirmation.

<Tabs syncKey="language">
<TabItem label="CLI" icon="seti:shell">

```bash
# Turn off confirmation prompts
daytona config set confirm false

# Print the current value
daytona config get confirm

# Print the directory that holds profiles, credentials, and settings
daytona config path
```

| **Setting** | **Type** | **Description** |
| ----------- | -------- | --------------- |
| `confirm`   | bool     | Sets whether destructive and billable commands ask for confirmation at a terminal: `true` or `false`. The default is `true`. |

<Callout type="note" title="Notes">
- Pass `--yes` or set `DAYTONA_YES=1` to confirm a command without a prompt, for example in scripts and CI.
- The config directory is `DAYTONA_CONFIG_DIR` when set, else `$XDG_CONFIG_HOME/daytona`, else `~/.config/daytona`.
</Callout>

</TabItem>
</Tabs>

## Authenticate API requests [#authenticate-api-requests]

Send the API key as a bearer token in the authorization header of every request.

<Tabs syncKey="language">
<TabItem label="API" icon="seti:json">

```bash
curl 'https://api.daytona.com/sandboxes' \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{}'
```

</TabItem>
</Tabs>
