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

# Authentication

> How to obtain and use tokens to authenticate Hyperspeed API requests.

## Login

Exchange email and password for a JWT access token and a refresh token.

```
POST /api/v1/auth/login
```

**Request body**

<ParamField body="email" type="string" required>
  The user's email address.
</ParamField>

<ParamField body="password" type="string" required>
  The user's password.
</ParamField>

**Example**

```bash theme={null}
curl -X POST https://your-hostname/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email": "alice@example.com", "password": "s3cr3tpassword"}'
```

**Response** `200 OK`

```json theme={null}
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5...",
  "refresh_token": "dGhpcyBpcyBhIHJlZnJlc2...",
  "token_type": "Bearer",
  "expires_in": 900
}
```

<ResponseField name="access_token" type="string">
  JWT access token. Valid for 900 seconds (15 minutes).
</ResponseField>

<ResponseField name="refresh_token" type="string">
  Opaque token used to obtain a new access token without re-entering credentials.
</ResponseField>

<ResponseField name="token_type" type="string">
  Always `"Bearer"`.
</ResponseField>

<ResponseField name="expires_in" type="integer">
  Access token lifetime in seconds (900).
</ResponseField>

<ResponseField name="signup_pending" type="boolean">
  Present and `true` when the account is awaiting admin approval (open-signup flow only).
</ResponseField>

## Using the token

Pass the access token in the `Authorization` header on every subsequent request:

```bash theme={null}
curl https://your-hostname/api/v1/organizations \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5..."
```

## Refreshing the token

When the access token expires, use the refresh token to get a new pair without re-entering credentials.

```
POST /api/v1/auth/refresh
```

<ParamField body="refresh_token" type="string" required>
  The refresh token received at login.
</ParamField>

```bash theme={null}
curl -X POST https://your-hostname/api/v1/auth/refresh \
  -H "Content-Type: application/json" \
  -d '{"refresh_token": "dGhpcyBpcyBhIHJlZnJlc2..."}'
```

The response is the same shape as `/auth/login`. The old refresh token is invalidated immediately.

## Logout

Invalidate a refresh token server-side.

```
POST /api/v1/auth/logout
```

<ParamField body="refresh_token" type="string" required>
  The refresh token to revoke.
</ParamField>

Returns `204 No Content` on success.

## Service account tokens

Service accounts are used for programmatic or AI staff access. Their tokens are prefixed with `sa_` and are not JWTs — they authenticate via the same `Authorization: Bearer` header. A service account token is returned once when the service account is created and is not recoverable afterward. See [Service Accounts](/api-reference/service-accounts) for creation details.

Use a service account token exactly like a user JWT:

```bash theme={null}
curl https://your-hostname/api/v1/organizations/YOUR_ORG_ID/spaces \
  -H "Authorization: Bearer sa_4a7f3c..."
```

Service account tokens do not expire unless explicitly revoked. Store them securely.

## Common errors

| Status | Error message | Cause |
| - | - | - |
| `401 Unauthorized` | `"invalid credentials"` | Wrong email or password |
| `401 Unauthorized` | `"unauthorized"` | Missing or expired token on a protected route |
| `403 Forbidden` | `"signups_disabled"` | Registration is disabled on this instance |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.