# API Reference

Base URL: `https://valiron-edge-proxy.onrender.com`

Endpoints are organized into two groups:

- **Trust evaluation** (`/operator/agent/*`, `/operator/gate/*`, etc.) — No authentication required. Used by the SDK to evaluate agents.
- **Dashboard** (`/operator/register`, `/operator/login`, `/operator/endpoints`, etc.) — JWT-authenticated. Used by the Operator Dashboard. See [DASHBOARD.md](./DASHBOARD.md) for the UI guide.

---

## Trust Evaluation Endpoints

### GET /operator/agent/:agentId

Retrieve the complete trust profile for an agent.

### Parameters

| Parameter | Location | Type | Required | Description |
|-----------|----------|------|----------|-------------|
| `agentId` | path | string | yes | ERC-8004 token ID |
| `chain` | query | string | no | Network override (default: ethereum) |

### Response — 200 OK

```json
{
  "agentId": "25459",
  "identity": {
    "agentId": "25459",
    "wallet": "0x52ce...",
    "tokenUri": "data:application/json;base64,...",
    "name": "Agent Name",
    "image": "https://...",
    "description": "Agent description",
    "endpoints": {
      "agentWallet": "eip155:1:0x...",
      "api": "https://api.example.com"
    },
    "trustModels": ["reputation_on_chain", "behavioral_sandbox"]
  },
  "onchainReputation": {
    "feedbackCount": 12,
    "averageScore": 92.5
  },
  "routing": {
    "finalRoute": "prod",
    "meetsThreshold": true
  },
  "chain": {
    "name": "ethereum",
    "chainId": 1
  },
  "timestamp": "2026-03-23T12:00:00.000Z"
}
```

### Error Responses

| Status | Meaning |
|--------|---------|
| 404 | Agent not found in ERC-8004 registry |
| 500 | Internal server error |

---

## GET /operator/wallet/:wallet

Reverse-lookup a wallet address to get its trust profile.

### Parameters

| Parameter | Location | Type | Required | Description |
|-----------|----------|------|----------|-------------|
| `wallet` | path | string | yes | Ethereum address (0x...) or Solana pubkey (base-58, with `chain=solana`) |
| `chain` | query | string | no | Network override |

### Response — 200 OK

Same structure as `GET /operator/agent/:agentId`.

---

## GET /operator/resolve-wallet/:wallet

Lightweight wallet → agentId resolution. Returns just the agent ID and how it was resolved, without the full trust profile.

Resolution chain: Redis → Agent0 subgraph → null. For Solana (`chain=solana`): QuantuLabs `getAgentsByOwner()`.

### Parameters

| Parameter | Location | Type | Required | Description |
|-----------|----------|------|----------|-------------|
| `wallet` | path | string | yes | Ethereum address (0x...) or Solana pubkey (base-58, with `chain=solana`) |
| `chain` | query | string | no | Network override (default: ethereum) |

### Response — 200 OK

```json
{
  "wallet": "0x52ce...",
  "agentId": "25459",
  "source": "subgraph",
  "chainId": 1,
  "agentName": "MyAgent",
  "timestamp": "2024-01-01T00:00:00.000Z"
}
```

---

## POST /operator/trigger-sandbox/:agentId

Execute real-time sandbox tests against an agent and compute a trust evaluation.

### Parameters

| Parameter | Location | Type | Required | Description |
|-----------|----------|------|----------|-------------|
| `agentId` | path | string | yes | ERC-8004 token ID |
| `chain` | query | string | no | Network override |

### Response — 200 OK

```json
{
  "ok": true,
  "agentId": "25459",
  "wallet": "0x52ce...",
  "tier": "AAA",
  "riskLevel": "GREEN",
  "meetsThreshold": true,
  "testSummary": {},
  "chain": {
    "name": "ethereum",
    "chainId": 1
  },
  "message": "Sandbox evaluation complete"
}
```

> **Note:** The `testSummary` object contains opaque test metrics. Its internal structure is proprietary and may change without notice.

---

## POST /operator/gate/:agentId

Trust gate — combined on-chain reputation + sandbox check. Returns an allow/deny decision. Designed for protecting payment endpoints (x402, etc.).

### Parameters

| Parameter | Location | Type | Required | Description |
|-----------|----------|------|----------|-------------|
| `agentId` | path | string | yes | ERC-8004 token ID |

### Request Body

```json
{
  "ttlMs": 86400000
}
```

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `ttlMs` | number | 86400000 | Cache TTL in milliseconds (default 24 hours) |

### Response — 200 OK

```json
{
  "allow": true,
  "tier": "AAA",
  "riskLevel": "GREEN",
  "meetsThreshold": true,
  "route": "prod",
  "agentId": "25459",
  "wallet": "0x52ce...",
  "chain": {
    "name": "ethereum",
    "chainId": 1
  },
  "sandboxRan": false,
  "cached": true
}
```

### Decision Logic

1. If the agent meets the trust threshold → `allow: true`
2. If the agent does not meet the threshold → `allow: false`
3. Cached sandbox results are reused within the `ttlMs` window
4. If no cached result exists, sandbox tests run automatically

---

## GET /operator/agent/:agentId/snapshot

Get the latest behavioral snapshot hash for an agent. Returns an opaque hash suitable for on-chain commitment systems.

### Parameters

| Parameter | Location | Type | Required | Description |
|-----------|----------|------|----------|-------------|
| `agentId` | path | string | yes | ERC-8004 token ID |
| `chain` | query | string | no | Network override |

### Response — 200 OK

```json
{
  "agentId": "25459",
  "snapshotHash": "0x3a7f2b...",
  "previousHash": "0x0",
  "encryptedDataUri": null,
  "timestamp": "2026-04-01T12:00:00.000Z",
  "interactionCount": 15
}
```

### Error Responses

| Status | Meaning |
|--------|---------|
| 400 | Invalid agentId |
| 404 | Agent not found or no snapshot available (trigger a sandbox evaluation first) |
| 500 | Internal server error |

---

## POST /operator/webhooks/register

Register a webhook URL to receive `evaluation_complete` events whenever Valiron evaluates an agent.

### Request Body

```json
{
  "event": "evaluation_complete",
  "url": "https://your-endpoint.com/hooks/valiron",
  "agentIds": [42, 43]
}
```

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `event` | string | yes | Must be `"evaluation_complete"` |
| `url` | string | yes | HTTPS endpoint to receive webhook POST requests |
| `agentIds` | number[] | no | Filter to specific agent IDs. Omit for all agents. |

### Response — 201 Created

```json
{
  "id": "a1b2c3d4-...",
  "event": "evaluation_complete",
  "url": "https://your-endpoint.com/hooks/valiron",
  "agentIds": [42, 43],
  "createdAt": "2026-04-01T12:00:00.000Z"
}
```

### Webhook Payload

When an evaluation completes, Valiron POSTs the following to your registered URL:

```json
{
  "event": "evaluation_complete",
  "agentId": "25459",
  "tier": "AAA",
  "riskLevel": "GREEN",
  "route": "prod",
  "meetsThreshold": true,
  "snapshotHash": "0x3a7f2b...",
  "previousHash": "0x8b2c1a...",
  "encryptedDataUri": null,
  "timestamp": "2026-04-01T12:05:00.000Z",
  "interactionCount": 16
}
```

#### Webhook Payload Fields

| Field | Type | Description |
|-------|------|-------------|
| `event` | string | Always `"evaluation_complete"` |
| `agentId` | string | The evaluated agent ID |
| `tier` | string | Moody's-style trust tier (AAA–C) |
| `riskLevel` | string | GREEN / YELLOW / RED |
| `route` | string | Route decision (`prod`, `prod_throttled`, `sandbox`, `sandbox_only`) |
| `meetsThreshold` | boolean | Whether the agent passed the trust gate |
| `snapshotHash` | string | Deterministic hash of the behavioral evaluation |
| `previousHash` | string | Hash from the prior evaluation |
| `encryptedDataUri` | string\|null | IPFS CID of encrypted snapshot data |
| `timestamp` | string | ISO 8601 timestamp |
| `interactionCount` | number | Total interactions in the evaluation window |

#### Webhook Limitations

- **Maximum registrations:** 1,000 per operator
- **Delivery:** Fire-and-forget — no retries on failure
- **Timeout:** 10 seconds — your endpoint must respond within 10s
- **Signatures:** Webhooks are not signed — verify via IP allowlisting or shared secrets if needed
- **Events:** Only `evaluation_complete` is currently supported

---

## POST /operator/proxy/:agentId (Pro)

Forward a request through Valiron's edge proxy with automatic trust gating, logging, and SSRF protection.

### Parameters

| Parameter | Location | Type | Required | Description |
|-----------|----------|------|----------|-------------|
| `agentId` | path | string | yes | Agent to gate |

### Request Body

```json
{
  "targetUrl": "https://your-api.com/data",
  "method": "POST",
  "headers": { "Content-Type": "application/json" },
  "body": "{\"query\": \"example\"}"
}
```

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `targetUrl` | string | yes | Your origin URL to forward to |
| `method` | string | no | HTTP method (default: `GET`) |
| `headers` | object | no | Headers to forward |
| `body` | string | no | Request body |

### Response — 200 OK

```json
{
  "statusCode": 200,
  "responseHeaders": {},
  "responseBody": "...",
  "responseMs": 145,
  "costCharged": "0.0500",
  "route": "prod",
  "tierResolved": "AA"
}
```

> **SSRF Protection:** The proxy blocks requests to private IPs (10.x, 172.16-31.x, 192.168.x), localhost, link-local addresses, and cloud metadata endpoints (169.254.169.254).

---

## Key-Based Agent Endpoints

For Web2 agents that don't have on-chain identities, Valiron supports key-based authentication using EIP-191 challenge-response.

### GET /operator/key/:agentAddress/challenge

Get a challenge nonce for key-based authentication.

| Parameter | Location | Type | Required | Description |
|-----------|----------|------|----------|-------------|
| `agentAddress` | path | string | yes | Ethereum address (0x...) |

#### Response — 200 OK

```json
{
  "challenge": "valiron-challenge-abc123...",
  "expiresAt": "2026-04-01T12:05:00.000Z"
}
```

### POST /operator/key/verify

Verify a signed challenge to authenticate a key-based agent.

#### Request Body

```json
{
  "address": "0x...",
  "signature": "0x..."
}
```

#### Response — 200 OK

```json
{
  "verified": true,
  "address": "0x...",
  "isKeyAgent": true,
  "tier": "C",
  "riskLevel": "YELLOW",
  "route": "sandbox"
}
```

### GET /operator/key/:agentAddress

Get the profile of a key-based agent.

#### Response — 200 OK

```json
{
  "address": "0x...",
  "isKeyAgent": true,
  "tier": "C",
  "riskLevel": "YELLOW",
  "route": "sandbox",
  "firstSeen": "2026-04-01T12:00:00.000Z",
  "totalRequests": 42
}
```

---

## World ID Endpoints

Verify agent-human linkage via Worldcoin's zero-knowledge proof system.

### POST /operator/world-id/verify/:agentId

Submit a World ID proof for verification.

| Parameter | Location | Type | Required | Description |
|-----------|----------|------|----------|-------------|
| `agentId` | path | string | yes | ERC-8004 token ID |

#### Request Body

```json
{
  "merkle_root": "0x...",
  "nullifier_hash": "0x...",
  "proof": "0x...",
  "signal": "0x..."
}
```

#### Response — 200 OK

```json
{
  "verified": true,
  "agentId": "25459",
  "level": "orb",
  "verifiedAt": "2026-04-01T12:00:00.000Z"
}
```

### GET /operator/world-id/status/:agentId

Check if an agent has a verified World ID.

#### Response — 200 OK

```json
{
  "verified": true,
  "verifiedAt": "2026-04-01T12:00:00.000Z",
  "level": "orb"
}
```

### GET /operator/world-id/profile/:agentId

Get full World ID profile including verification details.

#### Response — 200 OK

```json
{
  "agentId": "25459",
  "worldId": {
    "verified": true,
    "level": "orb",
    "verifiedAt": "2026-04-01T12:00:00.000Z"
  }
}
```

---

## GET /operator/health

Health check endpoint.

### Response — 200 OK

```json
{
  "status": "ok",
  "supportedChains": ["ethereum", "monad", "arbitrum", "base", ...],
  "defaultChain": "ethereum"
}
```

---

## Solana Support

All `/operator/*` endpoints support Solana agents when `chain=solana` is passed as a query parameter or `x-chain: solana` header.

Solana agent identity and reputation data is provided by [QuantuLabs 8004-solana](https://8004.qnt.sh/), while EVM chains use the 8004 team's registry contracts. The two registries have different schemas — this is by design.

### Key Differences from EVM

| Area | EVM | Solana |
|------|-----|--------|
| **Agent ID format** | Numeric token ID (e.g. `25459`) | Base-58 Metaplex Core asset pubkey (e.g. `GL4k...`) or sequential ID (e.g. `1`, `42`) |
| **Wallet format** | `0x`-prefixed hex address | Base-58 public key |
| **Identity source** | ERC-8004 `ownerOf()` on-chain call | QuantuLabs `loadAgent()` SDK call |
| **Reputation source** | ERC-8004 `getSummary()` | QuantuLabs ATOM engine (`getEnrichedSummary()`) |
| **Extra reputation fields** | — | `solana.trustTier`, `solana.qualityScore`, `solana.confidence`, `solana.riskScore`, `solana.uniqueCallers` |
| **Wallet → Agent resolution** | Redis → Agent0 subgraph | QuantuLabs `getAgentsByOwner()` |
| **Liveness check** | — | `isItAlive()` endpoint-by-endpoint health probe |
| **Feedback write-back** | — | Valiron scores written on-chain via `giveFeedback()` (requires `SOLANA_FEEDBACK_KEYPAIR`) |

### Sequential Agent IDs

Solana agents are primarily identified by their base-58 asset pubkey, but the QuantuLabs indexer also assigns sequential integer IDs (1, 2, 3, …). You can use either format:

```bash
# By asset pubkey (primary)
curl "https://valiron-edge-proxy.onrender.com/operator/agent/GL4k...?chain=solana"

# By sequential ID (convenience)
curl "https://valiron-edge-proxy.onrender.com/operator/agent/42?chain=solana"
```

When a sequential ID is used, the response includes a `sequentialId` field mapping back to the numeric ID.

### Liveness Check

`GET /operator/agent/:agentId/liveness?chain=solana`

Pings each service endpoint from the agent's on-chain metadata and returns a health report. Only available for Solana agents.

**Response:**
```json
{
  "agentId": "GL4k...",
  "chain": { "network": "solana", "cluster": "mainnet-beta" },
  "liveness": {
    "status": "live",
    "okCount": 3,
    "totalPinged": 3,
    "skippedCount": 0,
    "results": [
      { "type": "rest", "endpoint": "https://...", "ok": true, "latencyMs": 120 }
    ]
  }
}
```

The `trigger-sandbox` endpoint also includes a `liveness` summary in its response for Solana agents.

### Feedback Write-Back

When `SOLANA_FEEDBACK_KEYPAIR` is configured, Valiron automatically writes evaluation scores back to the Solana reputation registry after sandbox testing and gate evaluations. This closes the trust loop — other consumers of the 8004-solana registry can see Valiron's scores.

Feedback is submitted as fire-and-forget using the `starred` tag with `tag2: "valiron"` for attribution.

### Solana-Specific Response Fields

When querying a Solana agent, the `onchainReputation` object may include an additional `solana` block with ATOM engine metrics:

```json
{
  "onchainReputation": {
    "count": "42",
    "averageScore": 88.5,
    "feedbackEntries": [],
    "totalFeedback": 42,
    "solana": {
      "trustTier": "trusted",
      "qualityScore": 92.1,
      "confidence": 0.87,
      "riskScore": 0.08,
      "uniqueCallers": 15
    }
  }
}
```

### Example Requests

```bash
# Get Solana agent profile
curl "https://valiron-edge-proxy.onrender.com/operator/agent/GL4k...?chain=solana"

# Get Solana agent by sequential ID
curl "https://valiron-edge-proxy.onrender.com/operator/agent/42?chain=solana"

# Gate a Solana agent
curl -X POST "https://valiron-edge-proxy.onrender.com/operator/gate/GL4k...?chain=solana"

# Check liveness
curl "https://valiron-edge-proxy.onrender.com/operator/agent/GL4k.../liveness?chain=solana"

# Look up by Solana wallet
curl "https://valiron-edge-proxy.onrender.com/operator/wallet/7xKX...?chain=solana"

# Trigger sandbox for Solana agent
curl -X POST "https://valiron-edge-proxy.onrender.com/operator/trigger-sandbox/GL4k...?chain=solana"
```

### Environment Variables

| Variable | Default | Description |
|----------|---------|-------------|
| `SOLANA_CLUSTER` | `mainnet-beta` | Solana cluster (`mainnet-beta` or `devnet`) |
| `SOLANA_RPC_URL` | Public RPC | Custom Solana RPC endpoint |
| `SOLANA_FEEDBACK_KEYPAIR` | — | JSON array secret key (e.g. `[1,2,...,64]`) for feedback write-back. When set, Valiron scores are written on-chain after evaluation. |

---

## Dashboard Endpoints (JWT-Authenticated)

All dashboard endpoints require a `Authorization: Bearer <jwt>` header. Get a JWT by calling `POST /operator/login`.

---

### POST /operator/register

Create a new operator account.

#### Request Body

```json
{
  "email": "you@example.com",
  "password": "SecurePass123!",
  "name": "Your Name"
}
```

#### Response — 200 OK

```json
{
  "operator": { "id": "uuid", "email": "you@example.com", "name": "Your Name", "role": "operator" },
  "apiKey": "val_op_xxxx..."
}
```

> **Important:** The `apiKey` is shown once. Copy it immediately.

---

### POST /operator/login

Authenticate and receive a JWT token.

#### Request Body

```json
{
  "email": "you@example.com",
  "password": "SecurePass123!"
}
```

#### Response — 200 OK

```json
{
  "operator": { "id": "uuid", "email": "you@example.com", "name": "Your Name", "role": "operator" },
  "token": "eyJhbGciOi..."
}
```

---

### GET /operator/me

Get the current operator's profile. Requires JWT.

#### Response — 200 OK

```json
{
  "ok": true,
  "operator": {
    "id": "uuid",
    "email": "you@example.com",
    "name": "Your Name",
    "role": "operator",
    "plan": "standard",
    "fee_rate": "0.03",
    "created_at": "2026-01-01T00:00:00.000Z",
    "updated_at": "2026-01-01T00:00:00.000Z"
  }
}
```

---

### PATCH /operator/me

Update operator name. Requires JWT.

#### Request Body

```json
{
  "name": "New Name"
}
```

---

### GET /operator/keys

List all API keys for the current operator. Requires JWT.

#### Response — 200 OK

```json
[
  {
    "id": "uuid",
    "keyPrefix": "val_op_c010...",
    "label": null,
    "revoked": false,
    "lastUsed": "2026-04-01T00:00:00.000Z",
    "createdAt": "2026-01-01T00:00:00.000Z"
  }
]
```

---

### POST /operator/keys/rotate

Generate a new API key. Requires JWT.

#### Request Body (optional)

```json
{
  "label": "production-key"
}
```

#### Response — 200 OK

```json
{
  "key": "val_op_xxxx...",
  "id": "uuid",
  "label": "production-key"
}
```

> **Important:** The full key is shown once. Copy it immediately.

---

### DELETE /operator/keys/:keyId

Revoke an API key. Requires JWT.

---

### GET /operator/endpoints

List all registered endpoints for the current operator. Requires JWT.

#### Response — 200 OK

```json
[
  {
    "id": "uuid",
    "path": "/api/v1/weather",
    "method": "GET",
    "pricePerCall": "0.050000",
    "description": "Returns weather data",
    "rateLimit": 60,
    "active": true,
    "createdAt": "2026-01-01T00:00:00.000Z"
  }
]
```

---

### POST /operator/endpoints

Register a new priced endpoint. Requires JWT.

#### Request Body

```json
{
  "path": "/api/v1/weather",
  "method": "GET",
  "pricePerCall": 0.05,
  "description": "Returns weather data",
  "rateLimit": 60,
  "targetUrl": "https://myapi.com"
}
```

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `path` | string | yes | API path (e.g. `/api/v1/weather`) |
| `method` | string | no | HTTP method (default: `GET`) |
| `pricePerCall` | number | yes | Price in USD per call (must be ≥ 0) |
| `description` | string | no | Endpoint description |
| `rateLimit` | number | no | Max requests/min per agent (null = unlimited) |
| `targetUrl` | string | no | Backend base URL (e.g. `https://myapi.com`). Must be HTTPS. Private/internal addresses are blocked. When set, the playground forwards requests to this URL + path. |

---

### DELETE /operator/endpoints/:endpointId

Deactivate an endpoint (soft delete). Requires JWT.

---

### GET /operator/analytics/stats

Aggregate stats for the current operator. Requires JWT.

#### Response — 200 OK

```json
{
  "totalCalls": 1250,
  "totalRevenue": "62.50",
  "uniqueAgents": 18,
  "avgResponseMs": 145,
  "errorRate": "0.024",
  "callsToday": 42,
  "revenueToday": "2.10"
}
```

---

### GET /operator/analytics/revenue?days=30

Daily revenue time series. Requires JWT.

#### Response — 200 OK

```json
[
  { "date": "2026-04-01", "revenue": "3.50", "calls": 70 },
  { "date": "2026-04-02", "revenue": "4.25", "calls": 85 }
]
```

---

### GET /operator/analytics/top-endpoints?limit=10

Top endpoints ranked by call volume. Requires JWT.

---

### GET /operator/analytics/agents?sortBy=lastSeen&limit=50&offset=0

Paginated agent summaries. Requires JWT.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `sortBy` | string | `lastSeen` | Sort by: `lastSeen`, `calls`, `spent`, `errors` |
| `limit` | number | 50 | Page size |
| `offset` | number | 0 | Offset |

---

### GET /operator/analytics/agents/:agentId

Detailed view of a single agent. Requires JWT. Returns summary stats, endpoint breakdown, and recent call log.

---

### GET /operator/analytics/logs

Paginated call logs. Requires JWT.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `limit` | number | 50 | Page size |
| `offset` | number | 0 | Offset |
| `days` | number | — | Filter to last N days |
| `agentId` | string | — | Filter by agent |
| `endpointId` | string | — | Filter by endpoint |

---

### POST /operator/playground

Execute a test request through the edge proxy as a simulated agent. Requires JWT. See [DASHBOARD.md — API Playground](./DASHBOARD.md#api-playground).

#### Request Body

```json
{
  "method": "GET",
  "path": "/api/v1/weather?city=NYC",
  "headers": { "Content-Type": "application/json" },
  "body": null,
  "agentId": "25459",
  "chain": "ethereum",
  "dryRun": false
}
```

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `path` | string | yes | Target path or absolute URL |
| `agentId` | string | yes | ERC-8004 agent ID to simulate |
| `method` | string | no | HTTP method (default: `GET`) |
| `headers` | object | no | Custom request headers |
| `body` | string | no | Request body (for POST/PUT/PATCH) |
| `chain` | string | no | Chain (default: `ethereum`) |
| `dryRun` | boolean | no | If `true`, returns trust evaluation without logging the call |

#### Response — 200 OK (standard mode)

```json
{
  "ok": true,
  "statusCode": 200,
  "statusText": "OK",
  "responseHeaders": {},
  "responseBody": "<downstream response body or trust evaluation JSON>",
  "responseMs": 145,
  "costCharged": "0.0500",
  "route": "prod",
  "tierResolved": "AA"
}
```

#### Response — 200 OK (dry-run mode)

```json
{
  "ok": true,
  "statusCode": null,
  "statusText": null,
  "responseHeaders": {},
  "responseBody": "{\"dryRun\":true,\"message\":\"Routing and pricing validated — request was not forwarded to your backend\",\"agentId\":\"25459\",\"chain\":\"ethereum\",\"tier\":\"AA\",\"route\":\"prod\",\"pricePerCall\":\"0.0500\",\"endpointRegistered\":true,\"trustProfile\":{\"onchainScore\":92.5,\"feedbackCount\":\"12\",\"routingDecision\":null}}",
  "responseMs": null,
  "costCharged": "0.0500",
  "route": "prod",
  "tierResolved": "AA"
}
```

---

### Admin Endpoints (require `role: "admin"`)

| Endpoint | Method | Description |
|----------|--------|-------------|
| `/operator/admin/stats` | GET | Platform-wide stats |
| `/operator/admin/operators` | GET | List all operators with aggregate stats |
| `/operator/admin/operators/:id` | GET | Full operator detail (keys, endpoints, agents, revenue) |
| `/operator/admin/operators/:id/logs` | GET | Call logs for a specific operator |
