# Authentication

Amigo uses a two-tiered authentication system for secure API access. This guide covers the authentication workflow and best practices.

{% hint style="warning" %}
**Classic API authentication.** This page covers the Classic API's two-tier authentication (API key to JWT). The Platform API uses workspace-scoped API keys as Bearer tokens instead. See [Platform API Authentication](/developer-guide/platform-api/platform-api/authentication.md).
{% endhint %}

## Authentication

### Bearer Tokens

By default, the platform issues Bearer tokens. Include the token in the `Authorization` header:

```
Authorization: Bearer <access_token>
```

### DPoP (Sender-Constrained Tokens)

The platform supports DPoP (Demonstration of Proof-of-Possession) sender-constrained tokens per RFC 9449. DPoP binds tokens to a cryptographic key held by the client, so even if a token is intercepted, it cannot be used without the corresponding private key.

To use DPoP:

1. **Generate an EC key pair** on the client (P-256, P-384, or P-521).
2. **Create a DPoP proof JWT** for each request with the following header and claims:
   * Header: `typ` set to `dpop+jwt`, `alg` set to `ES256`/`ES384`/`ES512`, and `jwk` containing the public key.
   * Claims: `htm` (HTTP method), `htu` (HTTP URL without query parameters), `iat` (issued at), and `jti` (unique identifier). Do not include an `exp` claim.
3. **Send the proof** in the `DPoP` header on the token request.
4. **Receive a DPoP-bound token** - the response will have `token_type` set to `DPoP` and the access token will contain a confirmation claim binding it to your key.
5. **Include a DPoP proof on every request** that uses the access token, including refresh token grants.

When refreshing a DPoP-bound token, you must include a valid DPoP proof signed by the same key. The refresh token is not rotated on each use - because the token is sender-constrained, replay by a different client is not possible, eliminating the need for rotation and the race conditions it can cause.

#### Token Response

The token response includes a `token_type` field that indicates whether the token is a standard `Bearer` token or a sender-constrained `DPoP` token:

| Field           | Type      | Description                            |
| --------------- | --------- | -------------------------------------- |
| `access_token`  | `string`  | The access token                       |
| `token_type`    | `string`  | `Bearer` or `DPoP`                     |
| `expires_in`    | `integer` | Token lifetime in seconds              |
| `scope`         | `string`  | Space-separated list of granted scopes |
| `refresh_token` | `string`  | Refresh token (if applicable)          |
| `session_id`    | `string`  | Session identifier (if applicable)     |

{% @mermaid/diagram content="%%{init: {"theme": "base", "themeVariables": {"actorBkg": "#083241", "actorTextColor": "#FFFFFF", "actorBorder": "#083241", "signalColor": "#575452", "signalTextColor": "#100F0F", "labelBoxBkgColor": "#F1EAE7", "labelBoxBorderColor": "#D7D2D0", "labelTextColor": "#100F0F", "loopTextColor": "#100F0F", "noteBkgColor": "#F1EAE7", "noteBorderColor": "#D7D2D0", "noteTextColor": "#100F0F", "activationBkgColor": "#E8E2EB", "activationBorderColor": "#083241", "altSectionBkgColor": "#F1EAE7", "altSectionColor": "#100F0F"}}}%%
sequenceDiagram
autonumber
participant Dev as Developer/Admin
participant API as Amigo API
participant App as Your App / SDK

Note over Dev,API: Create API key (one-time or rotate periodically)
Dev->>API: POST /v1/{org}/organization/api\_key/
API-->>Dev: 201 Created { api\_key\_id, api\_key }

Note over App,API: Exchange API key for JWT (machine-to-machine)
App->>API: POST /v1/{org}/user/signin\_with\_api\_key
API-->>App: 200 OK { jwt }

Note over App,API: Use JWT for HTTP requests
App->>API: Authorization: Bearer {jwt}
API-->>App: 200 OK

Note over App,API: For WebSocket realtime
App->>API: Sec-WebSocket-Protocol:<br/>bearer.authorization.amigo.ai.{jwt}
API-->>App: Connected" %}

### Understanding the two-step process

Amigo uses a two-credential system for secure API access.

1. **Generate an API key** (one-time or rotate periodically)
   * Create via the Admin Dashboard or the API endpoint
   * Produces `api_key_id` and `api_key`
   * Long-lived credential for machine-to-machine authentication
2. **Exchange the API key for a JWT token** (per session or application startup)
   * Call `POST /v1/{org}/user/signin_with_api_key` with the API key credentials
   * Returns a `jwt` (JSON Web Token)
   * Short-lived token representing an authenticated user session
3. **Use the JWT in all API calls**
   * Include it in the header: `Authorization: Bearer {jwt}`
   * The JWT grants access to conversations, users, and other endpoints

{% hint style="danger" %}
**Critical: API Key is not a JWT Token**

Wrong: `Authorization: Bearer {api_key}` Correct: `Authorization: Bearer {jwt}`

Never use the API key directly in Bearer headers. Always exchange it for a JWT first via the signin endpoint.
{% endhint %}

#### Step 1: User and workspace creation

This part of the process is handled for you by an Amigo representative.

1. **Create a user.** A user profile within the desired workspace represents an individual or entity with specific privileges and access rights within Amigo.
2. **Set up a workspace.** The workspace is a collaborative environment for you and others, providing a curated space for data and user activities.

#### Step 2: API key generation

Once the user and workspace are set up, create an API key. This key is a unique identifier that lets applications access the workspace securely and perform operations based on the permissions granted to it. Keep the key secret to prevent unauthorized access.

#### Step 3: Authentication token creation

Use the generated API key to create an authentication token. The token acts as a pass, granting access to perform actions on behalf of the users it impersonates within Amigo. Tokens are essential for validation, allowing the system to authenticate requests and verify that they come from known entities.

#### Final notes

* **Security best practices.** Always safeguard API keys and authentication tokens. Limit their distribution and rotate them periodically.
* **User impersonation.** Use the authentication token to carry out tasks on behalf of other users, as permitted by their roles and permissions.

### Regional endpoints and dedicated clusters

* Use the regional base URL that matches your organization's residency (US, EU, or AU). See [Regions & Endpoints](/developer-guide/getting-started/regions-and-endpoints.md) for the full list.
* For tenants on dedicated clusters, include the `x-mongo-cluster-name` header when instructed (mandatory for Create Organization).

A service account makes API keys for use with other services. When your organization is set up in Amigo, an `Admin` user is created for adding more users.

To confirm you are logged in as the `Admin` role, check that the tag appears in the top right corner of the admin dashboard.

## Generating API Keys

You have two options for generating API keys.

{% tabs %}
{% tab title="Admin Dashboard" %}

1. Log in to your service account.
2. Navigate to `https://<your-org-id>.amigo.ai/admin/settings`.
3. Click **Create API Key** and select the duration.
4. Store the API key and key ID securely (they cannot be retrieved later).
   {% endtab %}

{% tab title="Programmatic (Recommended)" %}

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
**Permission boundaries** API keys cannot impersonate users with higher privileges than the key creator.
{% endhint %}

## Authentication Token Generation

Exchange your API key for a JWT token to authenticate API calls.

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/user/signin\_with\_api\_key" method="post" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

## Testing with Postman or Scalar

When testing with API clients like Postman, Scalar, or Insomnia, follow the quick start flow below.

### Quick start flow

1. **Generate an API key** using one of the methods above. You will have `api_key`, `api_key_id`, and your `user_id`.
2. **Call the signin endpoint** to exchange for a JWT (see the embedded reference above).
3. **Use the JWT as a Bearer token** for all other API calls.

{% hint style="warning" %}
**Critical: the signin endpoint uses headers**

When calling `/user/signin_with_api_key`, pass credentials as **HTTP headers** rather than in the request body:

* `x-api-key: {your-api-key}`
* `x-api-key-id: {your-api-key-id}`
* `x-user-id: {your-user-id}`

The response contains `{ "jwt": "..." }`.
{% endhint %}

{% hint style="info" %}
**Where to find credentials**

* `api_key`, `api_key_id`, and `user_id`: all available at `https://<your-org-id>.amigo.ai/admin/settings/api-keys`
* `user_id`: also available in user details at `https://<your-org-id>.amigo.ai/admin/users/{user_id}`
  {% endhint %}

Once you have the JWT, use it for all subsequent requests.

```http
Authorization: Bearer {jwt-from-signin-response}
```

## CLI Authentication (Agent Forge)

When using the Agent Forge CLI, authentication is configured via environment variables in your `.env.{env}` file. Two methods are supported.

### Method 1: API key authentication

Set all three API key variables to use API key auth. This method also supports user impersonation via the `--user` flag.

```env
API_KEY=your-api-key
API_KEY_ID=your-api-key-id
API_KEY_USER_ID=your-user-id
```

### Method 2: Firebase authentication (recommended)

Set `GOOGLE_TENANT_ID` (and omit the API key fields) to use Firebase-based Google Sign-In with device code flow. When using the device code flow, the CLI displays a user code and directs you to the Developer Console's device authorization page. After signing in, you verify the code matches what your terminal shows and approve or deny the request. Tokens are cached in the system keyring and refresh automatically.

```env
GOOGLE_TENANT_ID=your-tenant-id
```

```bash
# One-time login per environment
forge auth login -e myorg

# Output:
# Visit: https://www.google.com/device
# Enter code: ABCD-EFGH
# Waiting for authentication...
# Authenticated as you@example.com
```

{% hint style="info" %}
**Auth method selection.** The CLI picks the auth method based on which environment variables are set. If all three API key fields are present, API key auth is used. Otherwise, Firebase auth is used. Subsequent commands reuse cached tokens and refresh them silently.
{% endhint %}

{% hint style="warning" %}
**Impersonation limitation.** The `--user` flag on conversation commands (smoke-test, simulate, simulate-step) requires API key authentication. Firebase auth does not support user impersonation.
{% endhint %}

## HTTP Basic Authentication (Experimental)

{% hint style="warning" %}
**Experimental feature.** HTTP Basic Auth is experimental and subject to change. Use the API key to JWT exchange for production integrations.
{% endhint %}

An alternative authentication method is available using HTTP Basic Auth, which supports cross-organization authorization.

**Format:**

```
Authorization: Basic base64({org_id}_{user_id}:{firebase_token})
```

**Key features:**

* Combines organization, user, and Firebase token into a single header
* Supports cross-organization authentication (a user in org A authenticating against org B)
* Useful for scenarios where the standard two-step API key to JWT flow is impractical

**Example:**

```bash
# Encode credentials
CREDENTIALS=$(echo -n "${ORG_ID}_${USER_ID}:${FIREBASE_TOKEN}" | base64)

curl --request GET \
     --url 'https://api.amigo.ai/v1/<YOUR-ORG-ID>/service/' \
     --header "Authorization: Basic ${CREDENTIALS}"
```

## Security Best Practices

### API key rotation

1. **Create new keys** before current keys expire.
2. **Transition applications** to use the new credentials.
3. **Revoke old keys** after a successful transition.
4. **Automate rotation** to prevent authentication failures.

### Additional security measures

* **Environment variables.** Never hardcode credentials.
* **Access control.** Apply the principle of least privilege.
* **Audit logs.** Monitor API key usage.
* **Secure storage.** Use a secret management solution.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.amigo.ai/developer-guide/getting-started/authentication.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
