# Get an access token

> Get a short-lived access token by exchanging a private key's signed assertion.

> Nevia is in beta and open to selected teams. Public launch in Dec 2026. The CLI installs with `curl -fsSL https://get.nevia.cloud | sh`, and the MCP server is at https://api.nevia.cloud/mcp. A person signs in once in the browser.
> Setup, sign-in and requesting access: [SKILL.md](https://nevia.cloud/SKILL.md). When Nevia fits and when it doesn't: [why.md](https://nevia.cloud/why.md).

> For the complete documentation index, see [llms.txt](https://nevia.cloud/llms.txt). This page's HTML version: https://nevia.cloud/docs/reference/api/access/createAccessToken

`POST https://api.nevia.cloud/v1/auth/token`

## Request body

Content type: `application/json`, required

Schema: `AccessTokenRequest`

| Field | Type | Required | Description |
|---|---|---|---|
| `assertion` | string | yes | Signed JWT: `iss` and `sub` = subject, `aud` = audience, `kid` = key_id. Length `20 <= length <= 4096`. |

## Behavior

Tokens last 15 minutes and carry no refresh. Sign a new assertion when one expires.

## Example request

### cURL

```bash
curl -X POST "https://api.nevia.cloud/v1/auth/token" \
  -H "Content-Type: application/json" \
  -d '{
    "assertion": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjM5Mzg5MDg0NjM4NDA4NTQwNCIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIzOTM4OTA4NDYyNDk4Njk5MDUiLCJzdWIiOiIzOTM4OTA4NDYyNDk4Njk5MDUiLCJhdWQiOiJodHRwczovL2F1dGguZXhhbXBsZS5jb20iLCJleHAiOjE3ODkwMDAwMDB9.c2lnbmF0dXJl"
  }'
```

### JavaScript

```js
const body = JSON.stringify({
  "assertion": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjM5Mzg5MDg0NjM4NDA4NTQwNCIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIzOTM4OTA4NDYyNDk4Njk5MDUiLCJzdWIiOiIzOTM4OTA4NDYyNDk4Njk5MDUiLCJhdWQiOiJodHRwczovL2F1dGguZXhhbXBsZS5jb20iLCJleHAiOjE3ODkwMDAwMDB9.c2lnbmF0dXJl"
})

fetch("https://api.nevia.cloud/v1/auth/token", {
  method: "POST",
  headers: {
    "Content-Type": "application/json"
  },
  body
})
```

### Python

```python
import requests

url = "https://api.nevia.cloud/v1/auth/token"
body = """{
  "assertion": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjM5Mzg5MDg0NjM4NDA4NTQwNCIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIzOTM4OTA4NDYyNDk4Njk5MDUiLCJzdWIiOiIzOTM4OTA4NDYyNDk4Njk5MDUiLCJhdWQiOiJodHRwczovL2F1dGguZXhhbXBsZS5jb20iLCJleHAiOjE3ODkwMDAwMDB9.c2lnbmF0dXJl"
}"""
response = requests.request("POST", url, data = body, headers = {
  "Content-Type": "application/json"
})

print(response.text)
```

## Responses

### 200

The access token, as the identity provider returns it.

Content type: `application/json`

Schema: `AccessTokenResponse`

| Field | Type | Required | Description |
|---|---|---|---|
| `access_token` | string | yes | Token for `Authorization: Bearer` headers. |
| `token_type` | "Bearer" | yes |  |
| `expires_in` | integer | yes | Token lifetime in seconds. |

Example:

```json
{
  "access_token": "mKq2vT9xRz4LwB8pNcYd3Hs6JfU1eGa0",
  "token_type": "Bearer",
  "expires_in": 900
}
```

### 400

`validation_failed`: malformed body, unknown field, or invalid id or name. Fix `details.field` and retry. `validation_failed`: the assertion is not a signed JWT with `iss`, `sub` and `kid`.

Content type: `application/json`

Schema: `ErrorEnvelope`

Body of every error response

| Field | Type | Required | Description |
|---|---|---|---|
| `error` | Error | yes |  |

Example `validation_failed: malformed body, unknown field, or invalid id or name. Fix \`details.field\` and retry`:

```json
{
  "error": {
    "code": "validation_failed",
    "message": "Unknown field `colour` in the request body. Remove it; request bodies are strict.",
    "details": {
      "field": "colour",
      "in": "body"
    },
    "request_id": "req_01j9k3m2p7q4r8s1"
  }
}
```

Example `validation_failed: the assertion is not a signed JWT with \`iss\`, \`sub\` and \`kid\``:

```json
{
  "error": {
    "code": "validation_failed",
    "message": "The assertion is not a signed JWT with iss, sub and kid (JWSInvalid).",
    "details": {
      "field": "assertion",
      "in": "body"
    },
    "request_id": "req_01j9k3m2p7q4r8s1"
  }
}
```

### 401

`unauthorized`: the assertion was refused. Every refusal gets this same response with no details: an unknown or deleted principal, an unknown, revoked or expired key, or a signature or audience the provider rejects.

Content type: `application/json`

Schema: `ErrorEnvelope`

Body of every error response

| Field | Type | Required | Description |
|---|---|---|---|
| `error` | Error | yes |  |

Example `unauthorized`:

```json
{
  "error": {
    "code": "unauthorized",
    "message": "The assertion was refused. Check the key file, or issue a new key.",
    "details": {},
    "request_id": "req_01j9k3m2p7q4r8s1"
  }
}
```

### 429

`rate_limited`: too many requests from this client address. Retry after `Retry-After`.

Content type: `application/json`

Schema: `ErrorEnvelope`

Body of every error response

| Field | Type | Required | Description |
|---|---|---|---|
| `error` | Error | yes |  |

Example `rate_limited`:

```json
{
  "error": {
    "code": "rate_limited",
    "message": "Too many requests. Retry after 2 seconds.",
    "details": {
      "retry_after_seconds": 2
    },
    "request_id": "req_01j9k3m2p7q4r8s1"
  }
}
```

### 500

`request_failed`, or the failed action's own code, such as `creation_failed`, `authorization_failed` or `command_execution_failed`. Quote `request_id` when reporting. The diagnostic stays in server logs.

Content type: `application/json`

Schema: `ErrorEnvelope`

Body of every error response

| Field | Type | Required | Description |
|---|---|---|---|
| `error` | Error | yes |  |

Example `request_failed`:

```json
{
  "error": {
    "code": "request_failed",
    "message": "request failed",
    "details": {},
    "request_id": "req_01j9k3m2p7q4r8s1"
  }
}
```

### 503

`creation_failed`: The action is temporarily unavailable, named by its code (`creation_failed`, `wake_failed`, ...). Wait at least `Retry-After` seconds (60 by default). `details.retryable` says whether repeating the request is safe. Keep the original `Idempotency-Key`. Signing in again does not help. `authentication_failed`: the deployment has no identity provider configured, so no token is issued. `authentication_failed`: the identity provider is unreachable, or refused the grant. Try again later.

Content type: `application/json`

Schema: `ErrorEnvelope`

Body of every error response

| Field | Type | Required | Description |
|---|---|---|---|
| `error` | Error | yes |  |

Example `creation_failed`:

```json
{
  "error": {
    "code": "creation_failed",
    "message": "The computer could not be created. Try again later, and quote request_id if it persists.",
    "details": {
      "retryable": true
    },
    "request_id": "req_01j9k3m2p7q4r8s1"
  }
}
```

Example `authentication_failed: the deployment has no identity provider configured, so no token is issued`:

```json
{
  "error": {
    "code": "authentication_failed",
    "message": "Private-key access is not configured on this deployment. Quote request_id when reporting.",
    "details": {
      "reason": "not configured",
      "retryable": false
    },
    "request_id": "req_01j9k3m2p7q4r8s1"
  }
}
```

Example `authentication_failed: the identity provider is unreachable, or refused the grant. Try again later`:

```json
{
  "error": {
    "code": "authentication_failed",
    "message": "the access token could not be issued",
    "details": {
      "retryable": true
    },
    "request_id": "req_01j9k3m2p7q4r8s1"
  }
}
```
