Authentication
Daytona authenticates SDK, CLI, and API requests with an API key. The key identifies the organization that owns the resources a request touches and carries the permissions the request may use. Every request sends the key as a bearer token.
A JWT token from the CLI login is the alternative for account-level operations. A JWT token identifies a user instead of an organization, so every JWT-authenticated request also names the organization it acts on.
| Term | Description |
|---|---|
| API key | A long-lived credential scoped to one organization and a set of permissions. Created in the dashboard. |
| JWT token | A short-lived access token issued when you log in to the CLI. Identifies a user, not an organization. |
| Organization ID | The organization a JWT-authenticated request acts on. Sent in the organization header. |
| Target | The default region for sandboxes and snapshots a client creates. A per-call target overrides it. |
| Profile | The CLI’s saved login: API URL plus an API key or a JWT token. The active profile serves CLI commands. |
Get an API key
Section titled “Get an API key”Create an API key in the dashboard and store it where the SDKs and CLI can read it. See API keys for permissions, expiration, and key management.
- Go to Daytona Dashboard ↗
- Click
- Enter the name of the API key, set the expiration date, and select permissions
- Click
- Copy the API key and save it as an environment variable
Environment variables
Section titled “Environment variables”The SDKs and the CLI read their configuration from environment variables. The SDKs resolve each value in order of precedence:
- Configuration in code
- Environment variables of the process
.env.localand.envfiles in the working directory (Python, TypeScript, and Ruby)- Default values
The API URL is the exception: the SDKs read it from code or from the process environment only. A DAYTONA_API_URL value in a .env file is ignored and reported, so a file in the working directory cannot redirect your API key to another endpoint.
| Variable | Description |
|---|---|
DAYTONA_API_KEY | Your Daytona API key. Required unless a JWT token is set. |
DAYTONA_API_URL | URL of the Daytona API. Default: https://app.daytona.io/api |
DAYTONA_TARGET | Default region for sandboxes and snapshots. Optional. |
DAYTONA_JWT_TOKEN | JWT token from daytona login. Alternative to the API key. |
DAYTONA_ORGANIZATION_ID | Your organization ID. Required when authenticating with a JWT token. |
.env file
Section titled “.env file”DAYTONA_API_KEY=YOUR_API_KEYDAYTONA_API_URL=https://app.daytona.io/apiDAYTONA_TARGET=usexport DAYTONA_API_KEY=YOUR_API_KEYexport DAYTONA_API_URL=https://app.daytona.io/apiexport DAYTONA_TARGET=us$env:DAYTONA_API_KEY="YOUR_API_KEY"$env:DAYTONA_API_URL="https://app.daytona.io/api"$env:DAYTONA_TARGET="us"Authenticate the SDK
Section titled “Authenticate the SDK”Construct the client without arguments to read the environment variables, or pass the configuration in code. Each configuration field falls back to its environment variable on its own, so you can set the API key in code and the target in the environment. When no API key and no JWT token is found, the constructor raises an authentication error.
from daytona import Daytona, DaytonaConfig
# Using environment variablesdaytona = Daytona()
# Using explicit configurationconfig = DaytonaConfig( api_key="YOUR_API_KEY", api_url="https://app.daytona.io/api", target="us",)
daytona = Daytona(config)import { Daytona } from '@daytona/sdk'
// Using environment variablesconst daytona = new Daytona()
// Using explicit configurationconst daytonaWithConfig = new Daytona({ apiKey: 'YOUR_API_KEY', apiUrl: 'https://app.daytona.io/api', target: 'us',})require 'daytona'
# Using environment variablesdaytona = Daytona::Daytona.new
# Using explicit configurationconfig = Daytona::Config.new( api_key: 'YOUR_API_KEY', api_url: 'https://app.daytona.io/api', target: 'us')
daytona = Daytona::Daytona.new(config)import ( "github.com/daytona/clients/sdk-go/pkg/daytona" "github.com/daytona/clients/sdk-go/pkg/types")
// Using environment variablesclient, _ := daytona.NewClient()
// Using explicit configurationclient, _ = daytona.NewClientWithConfig(&types.DaytonaConfig{ APIKey: "YOUR_API_KEY", APIUrl: "https://app.daytona.io/api", Target: "us",})import io.daytona.sdk.Daytona;import io.daytona.sdk.DaytonaConfig;
// Using environment variablesDaytona daytona = new Daytona();
// Using explicit configurationDaytonaConfig config = new DaytonaConfig.Builder() .apiKey("YOUR_API_KEY") .apiUrl("https://app.daytona.io/api") .target("us") .build();
Daytona daytonaWithConfig = new Daytona(config);Authenticate the CLI
Section titled “Authenticate the CLI”Log in once and the CLI saves the result in its active profile, so later commands need no key or flags. The login prompt offers two methods: a browser login, which stores a JWT token, or an API key, which stores the key. Pass the key as a flag to skip the prompt.
When both DAYTONA_API_KEY and DAYTONA_API_URL are set in the environment, the CLI uses them instead of the active profile for that command.
# Interactive login: choose browser login or enter an API keydaytona login
# Store an API key in the active profile without the promptdaytona login --api-key YOUR_API_KEY
# Use the saved profiledaytona sandbox list
# Remove the saved profile from this machinedaytona logoutAuthenticate API requests
Section titled “Authenticate API requests”Send the API key as a bearer token in the authorization header of every request.
curl 'https://app.daytona.io/api/sandbox' \ --request GET \ --header 'Authorization: Bearer YOUR_API_KEY'JWT tokens
Section titled “JWT tokens”JWT tokens authenticate account-level operations with the Daytona API. A JWT token identifies a user, so every JWT-authenticated request must include the X-Daytona-Organization-ID header set to the organization it acts on. JWT tokens expire after a short period. The Python, TypeScript, Ruby, and Go SDKs accept a JWT token and an organization ID in place of an API key. The Java SDK accepts API keys only.
- Run
daytona login - Select
- Complete the sign-in in your browser
- The CLI saves the access token to
config.jsonin the Daytona config directory
Daytona resolves the config directory from the $DAYTONA_CONFIG_DIR environment variable. If the variable is not set, Daytona uses the daytona folder inside your OS user config directory: ~/.config/daytona on Linux and ~/Library/Application Support/daytona on macOS. The active profile stores the token in the api.token.accessToken field.
from daytona import Daytona, DaytonaConfig
# Using environment variables: DAYTONA_JWT_TOKEN and DAYTONA_ORGANIZATION_IDdaytona = Daytona()
# Using explicit configurationconfig = DaytonaConfig( jwt_token="YOUR_JWT_TOKEN", organization_id="YOUR_ORGANIZATION_ID",)
daytona = Daytona(config)import { Daytona } from '@daytona/sdk'
// Using environment variables: DAYTONA_JWT_TOKEN and DAYTONA_ORGANIZATION_IDconst daytona = new Daytona()
// Using explicit configurationconst daytonaWithConfig = new Daytona({ jwtToken: 'YOUR_JWT_TOKEN', organizationId: 'YOUR_ORGANIZATION_ID',})require 'daytona'
# Using environment variables: DAYTONA_JWT_TOKEN and DAYTONA_ORGANIZATION_IDdaytona = Daytona::Daytona.new
# Using explicit configurationconfig = Daytona::Config.new( jwt_token: 'YOUR_JWT_TOKEN', organization_id: 'YOUR_ORGANIZATION_ID')
daytona = Daytona::Daytona.new(config)import ( "github.com/daytona/clients/sdk-go/pkg/daytona" "github.com/daytona/clients/sdk-go/pkg/types")
// Using environment variables: DAYTONA_JWT_TOKEN and DAYTONA_ORGANIZATION_IDclient, _ := daytona.NewClient()
// Using explicit configurationclient, _ = daytona.NewClientWithConfig(&types.DaytonaConfig{ JWTToken: "YOUR_JWT_TOKEN", OrganizationID: "YOUR_ORGANIZATION_ID",})curl 'https://app.daytona.io/api/sandbox' \ --request GET \ --header 'Authorization: Bearer YOUR_JWT_TOKEN' \ --header 'X-Daytona-Organization-ID: YOUR_ORGANIZATION_ID'