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

# Personal access tokens

> Authenticate CLI and SDK access for automation and CI/CD.

Personal access tokens (PATs) authenticate programmatic access to Ona via the [CLI](/ona/integrations/cli) or [SDK](/ona/integrations/sdk).

## Create a token

1. Go to [Personal access tokens](https://app.ona.com/settings/personal-access-tokens)
2. Click "New Token"
3. Enter a description and select expiration (30, 60, or 90 days)
4. Choose an access level:
   * **Read-only** - the token can only read data. All write operations are denied.
   * **Read & Write** - the token can both read and modify data.
5. Click "Create" and copy the token immediately - you won't see it again

## Use a token

```bash theme={null}
ona login --token <your-token>
```

Or set the environment variable:

```bash theme={null}
export ONA_TOKEN=<your-token>
ona login
```

## Permissions

Tokens inherit your user account's permissions and can be scoped to one of two access levels:

| Access level     | Description                                                                  |
| ---------------- | ---------------------------------------------------------------------------- |
| **Read-only**    | Can list and retrieve resources but cannot create, update, or delete them.   |
| **Read & Write** | Full access. Can perform any action your user account is allowed to perform. |

The access level is set at creation time and cannot be changed afterward. To switch access levels, revoke the existing token and create a new one.

## Security

* Treat tokens like passwords - don't share or store insecurely
* Use the shortest expiration that meets your needs
* Revoke unused tokens
* Actions are logged in audit logs with the token ID

## Examples

### CI/CD integration

Authenticate your CI/CD pipeline to create and manage environments.

```yaml theme={null}
name: Ona Integration
on: [push]
jobs:
  create-environment:
    runs-on: ubuntu-latest
    steps:
      - name: Create Environment
        env:
          ONA_TOKEN: ${{ secrets.ONA_PAT }}
          ONA_CLASS: some-class-id
        run: |
          ona login --token $ONA_TOKEN
          ona environment create --class-id $ONA_CLASS https://github.com/your-repo
```

### Scripted environment management

Manage environments programmatically for bulk operations.

```python theme={null}
import subprocess
import json

ONA_PAT = "your_personal_access_token"

def run_ona_command(*args):
    result = subprocess.run(
        ["ona"] + list(args),
        capture_output=True,
        text=True,
        check=True
    )
    return result.stdout.strip()

# Login using PAT
run_ona_command("login", "--token", ONA_PAT)

# List all environments
environments_json = run_ona_command("environment", "list", "-o", "json")
environments = json.loads(environments_json)

# Stop all running environments
for env in environments:
    if env['status']['phase'] == 'ENVIRONMENT_PHASE_RUNNING':
        print(f"Stopping environment {env['id']}")
        run_ona_command("environment", "stop", env['id'])

print("All running environments have been stopped.")
```

### Third-party tool integration

Create environments from external tools.

```python theme={null}
import subprocess
import json

ONA_PAT = "your_personal_access_token"

def create_environment_for_review(repo_url):
    # Login using PAT
    subprocess.run(["ona", "login", "--token", ONA_PAT], check=True)

    # Create an environment
    result = subprocess.run(
        ["ona", "environment", "create", repo_url, "--dont-wait"],
        capture_output=True,
        text=True,
        check=True
    )
    env_id = result.stdout.strip()

    # Get the environment details
    result = subprocess.run(
        ["ona", "environment", "get", env_id, "-o", "json"],
        capture_output=True,
        text=True,
        check=True
    )
    return json.loads(result.stdout)
```
