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

# Agent Authentication Contract

> ASG Agent Cloud v5.2.x API Key authentication specification

# Agent Authentication Contract

This document defines the authentication contract for programmatic (agent/bot) access to ASG Agent Cloud.

## Authentication Hierarchy

ASG Gateway supports two authentication methods, evaluated in order:

1. **SIWS Session Cookie** (`asg_session`) — For console UI users
2. **Bearer Token API Key** — For agents and programmatic access

```
Authorization: Bearer asc_sk_...
```

## API Key Format

| Prefix         | Environment | Example                 |
| -------------- | ----------- | ----------------------- |
| `asc_sk_live_` | Production  | `asc_sk_live_abc123...` |
| `asc_sk_test_` | Staging/Dev | `asc_sk_test_xyz789...` |

Keys are 64-character random strings prefixed with environment indicator.

## Security Model

### Key Storage

* **Plain-text key**: Shown ONCE at creation time — user must save it
* **Server stores**: BCrypt hash only (cost=10)
* **No recovery**: Lost keys cannot be retrieved; user must rotate

### Scopes

| Scope  | Description                                         |
| ------ | --------------------------------------------------- |
| `read` | Query balance, history, usage stats (default)       |
| `fund` | Initiate deposits, manage billing (requires opt-in) |

### Rate Limits

| Tier | RPM Limit | Default |
| ---- | --------- | ------- |
| Free | 60        | ✓       |
| Plus | 300       |         |
| Pro  | 1000      |         |

Limits are per-key, not per-wallet. 429 responses include `Retry-After` header.

## Endpoints (Billing Plane)

### Create Key

```http theme={null}
POST /keys
Content-Type: application/json
Cookie: asg_session=...

{
  "name": "My Agent Bot",
  "scopes": ["read"],
  "rate_limit_rpm": 60
}
```

**Response (201):**

```json theme={null}
{
  "key_id": "key_abc123",
  "api_key": "asc_sk_live_...",  // ⚠️ SHOW ONCE
  "name": "My Agent Bot",
  "scopes": ["read"],
  "rate_limit_rpm": 60,
  "created_at": "2026-02-03T12:00:00Z"
}
```

### List Keys

```http theme={null}
GET /keys
Cookie: asg_session=...
```

**Response:**

```json theme={null}
{
  "keys": [
    {
      "key_id": "key_abc123",
      "name": "My Agent Bot",
      "prefix": "asc_sk_live_abc...",  // First 16 chars only
      "scopes": ["read"],
      "rate_limit_rpm": 60,
      "last_used_at": "2026-02-03T11:30:00Z",
      "created_at": "2026-02-03T10:00:00Z"
    }
  ]
}
```

### Revoke Key

```http theme={null}
DELETE /keys/:key_id
Cookie: asg_session=...
```

### Rotate Key

```http theme={null}
POST /keys/:key_id/rotate
Cookie: asg_session=...
```

**Response:** New key object (same as Create)

### Validate Key (Internal)

```http theme={null}
POST /keys/validate
Content-Type: application/json

{ "api_key": "asc_sk_live_..." }
```

**Response:**

```json theme={null}
{
  "valid": true,
  "key_id": "key_abc123",
  "owner_wallet": "ABC...xyz",
  "scopes": ["read"],
  "rate_limit_rpm": 60
}
```

## Gateway Auth Middleware

The gateway validates keys via billing-plane `/keys/validate` with 5-minute caching.

```typescript theme={null}
// Request gets decorated with:
interface AuthenticatedRequest extends Request {
  apiKeyId?: string;       // e.g., "key_abc123"
  ownerWallet?: string;    // Wallet that created the key
  scopes?: string[];       // ["read"] or ["read", "fund"]
  rateLimitRpm?: number;   // Per-key rate limit
}
```

## Error Responses

| Status | Code           | Description                |
| ------ | -------------- | -------------------------- |
| 401    | `UNAUTHORIZED` | Missing or invalid API key |
| 403    | `FORBIDDEN`    | Missing required scope     |
| 429    | `RATE_LIMITED` | Rate limit exceeded        |

## Usage Example (Agent)

```typescript theme={null}
const response = await fetch('https://agent.asgcompute.com/v1/account/balance', {
  headers: {
    'Authorization': 'Bearer asc_sk_live_your_key_here',
    'Content-Type': 'application/json'
  }
});

if (response.status === 401) {
  // Re-authenticate or refresh key
}

const balance = await response.json();
```

## Related Documents

* [Quickstart for Agents](/docs/guide/agent-quickstart)
* [Rate Limiting](/docs/security/rate-limits)
* [Error Codes](/docs/api/errors)
