> For the complete documentation index, see [llms.txt](https://docs.acecloud.ai/knowledge-base/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.acecloud.ai/knowledge-base/cli/authentication.md).

# Authentication

The CLI supports three login methods. **For automation and CI use API keys** — they don't expire on the JWT 3-hour cycle.

| Method                | Use case                         | Lifetime  |
| --------------------- | -------------------------------- | --------- |
| API key (recommended) | Automation, CI/CD, scripts       | 90 days   |
| Developer token (JWT) | Interactive use, short sessions  | \~3 hours |
| Email + password      | First-time login from a new host | \~3 hours |

***

## Login with an API Key (Recommended for Automation)

API keys are long-lived `keyId.secret` credentials. They authenticate via the `X-Ace-Api-Key` HTTP header instead of `Authorization: Bearer`, eliminating the 3-hour token-refresh dance for unattended automation.

### Step 1 — Create an API key

You must be logged in (via `auth login` or `auth login-token`) to create one.

```bash
ace api-key create --name terraform-prod --description "IaC for production"
```

Output:

```
API key created. Save the secret below now — it will NEVER be shown again.

  Service name: terraform-prod
  API key:      00000000-0000-0000-0000-000000000000.EXAMPLE-secret-do-not-use

To use this key as your CLI auth method, run:

  ace auth login-api-key --key "00000000-0000-0000-0000-000000000000.EXAMPLE-secret-do-not-use" --service-name "terraform-prod"
```

The secret is shown **only once**. Save it to your secrets manager immediately. If you lose it, run `ace api-key revive <keyID>` to regenerate.

### Step 2 — Log in with the key

```bash
# Combined form (paste the full id.secret blob)
ace auth login-api-key --key "00000000-0000-0000-0000-000000000000.EXAMPLE-secret-do-not-use" \
                       --service-name "terraform-prod"

# Or separate id + secret
ace auth login-api-key --key-id "00000000-0000-0000-0000-000000000000" \
                       --secret  "EXAMPLE-secret-do-not-use" \
                       --service-name "terraform-prod"
```

The CLI verifies the key via `auth me`, stores it in `~/.ace/config.json`, and clears any existing JWT (single-source-of-truth — only one auth method active at a time).

### Step 3 — Use it

Every subsequent command sends the `X-Ace-Api-Key` header. No further action needed:

```bash
ace instance list
ace flavor list -o json
```

### Env var alternative (preferred for CI)

Skip the config file entirely — set environment variables instead. The CLI checks `ACE_API_KEY_ID` + `ACE_API_KEY_SECRET` + `ACE_API_KEY_SERVICE_NAME` on every invocation:

```bash
export ACE_API_KEY_ID=00000000-0000-0000-0000-000000000000
export ACE_API_KEY_SECRET=EXAMPLE-secret-replace-with-your-own-do-not-use-this-value
export ACE_API_KEY_SERVICE_NAME=terraform-prod

ace instance list
```

This is the recommended setup for GitHub Actions, GitLab CI, Jenkins, etc.

### Managing API keys

```bash
ace api-key list                              # see all your keys
ace api-key get <keyID>                       # single key details
ace api-key disable <keyID>                   # turn off without deleting
ace api-key enable <keyID>                    # re-enable
ace api-key update <keyID> --description "x"  # rename / re-describe
ace api-key revive <keyID>                    # regenerate secret (old one stops working)
ace api-key delete <keyID> --yes              # permanent delete
```

Keys auto-expire after \~90 days. To rotate before expiry, run `ace api-key revive <keyID>` and update wherever the secret is stored.

***

## Login with Developer Token (JWT)

Get your token from the AceCloud portal: **Settings > Developer Tokens**.

```bash
ace auth login-token --token <your-token>
```

Tokens expire after \~3 hours. Re-authenticate when expired.

## Login with Email/Password

```bash
ace auth login --email user@example.com --password "secret"

# Or interactive (prompts for credentials)
ace auth login
```

If 2FA/MFA is enabled, use `login-token` or `login-api-key` instead.

***

## Account Commands

```bash
# Current user info
ace auth me

# Detailed account status
ace auth status

# List projects and regions
ace auth projects

# Logout
ace auth logout
```

### `ace auth me` output

The default table view (and `-o json` / `-o yaml`) returns a slim profile — name, email, country, and account currency — not the full account dump.

```bash
$ ace auth me
Name:     Jane Doe
Email:    jane.doe@example.com
Country:  India
Currency: INR

$ ace auth me -o json
{
  "name": "Jane Doe",
  "email": "jane.doe@example.com",
  "country": "India",
  "currency": "INR"
}
```

***

## Token Expiry

JWTs are valid for \~3 hours. When expired:

```bash
ace auth login-token --token <new-token>
```

For CI/CD, **prefer API keys** over JWT — they last 90 days and don't need mid-pipeline refreshes. See *Login with an API Key* above. If you must use JWT in CI, the `ACE_TOKEN` environment variable still works:

```bash
export ACE_TOKEN="fresh-token"
ace instance list -o json
```
