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

# REST API Reference

> Complete REST API reference for Shannon Gateway

## Base URL

```
http://localhost:8080/api/v1
```

## Endpoints Summary

Shannon provides **40+ REST endpoints** across 8 categories:

### Task Operations (10 endpoints)

| Endpoint                        | Description                                                  |
| ------------------------------- | ------------------------------------------------------------ |
| `POST /tasks`                   | Submit a new task                                            |
| `POST /tasks/stream`            | Submit task and receive stream URL                           |
| `GET /tasks`                    | List tasks with filters (limit, offset, status, session\_id) |
| `GET /tasks/{id}`               | Get task status and result                                   |
| `GET /tasks/{id}/events`        | Get persistent event history                                 |
| `GET /tasks/{id}/timeline`      | Get deterministic Temporal timeline                          |
| `POST /tasks/{id}/pause`        | Pause a running task at workflow checkpoints                 |
| `POST /tasks/{id}/resume`       | Resume a previously paused task                              |
| `GET /tasks/{id}/control-state` | Get pause/cancel control state for a task                    |
| `POST /tasks/{id}/cancel`       | Cancel a queued or running task                              |

### Streaming (2 endpoints)

| Endpoint                           | Description                  |
| ---------------------------------- | ---------------------------- |
| `GET /stream/sse?workflow_id={id}` | Server-Sent Events streaming |
| `GET /stream/ws?workflow_id={id}`  | WebSocket streaming          |

### Session Management (6 endpoints)

| Endpoint                            | Description                                  |
| ----------------------------------- | -------------------------------------------- |
| `GET /sessions`                     | List sessions with pagination                |
| `GET /sessions/{sessionId}`         | Get session details                          |
| `GET /sessions/{sessionId}/history` | Get session conversation history             |
| `GET /sessions/{sessionId}/events`  | Get session events (grouped by turn)         |
| `PATCH /sessions/{sessionId}`       | Update session title (UUID or external\_id)  |
| `DELETE /sessions/{sessionId}`      | Delete session (soft delete; 204 idempotent) |

### Schedules (8 endpoints)

| Endpoint                      | Description                   |
| ----------------------------- | ----------------------------- |
| `POST /schedules`             | Create a new schedule         |
| `GET /schedules`              | List schedules                |
| `GET /schedules/{id}`         | Get schedule details          |
| `GET /schedules/{id}/runs`    | Get schedule run history      |
| `PUT /schedules/{id}`         | Update schedule configuration |
| `POST /schedules/{id}/pause`  | Pause a schedule              |
| `POST /schedules/{id}/resume` | Resume a schedule             |
| `DELETE /schedules/{id}`      | Delete a schedule             |

### Authentication (8 endpoints)

| Endpoint                      | Description             |
| ----------------------------- | ----------------------- |
| `POST /auth/register`         | Register a new user     |
| `POST /auth/login`            | Login and obtain tokens |
| `POST /auth/refresh`          | Refresh access token    |
| `GET /auth/me`                | Get current user info   |
| `POST /auth/api-keys/refresh` | Refresh an API key      |
| `GET /auth/api-keys`          | List API keys           |
| `POST /auth/api-keys`         | Create a new API key    |
| `DELETE /auth/api-keys/{id}`  | Revoke an API key       |

### Approvals & HITL Review (3 endpoints)

| Endpoint                   | Description                      |
| -------------------------- | -------------------------------- |
| `POST /approvals/decision` | Submit a human approval decision |
| `GET /tasks/{id}/review`   | Get HITL review details          |
| `POST /tasks/{id}/review`  | Submit HITL review decision      |

### OpenAI Compatible (3 endpoints)

| Endpoint                    | Description                            |
| --------------------------- | -------------------------------------- |
| `POST /v1/chat/completions` | Chat completions (streaming supported) |
| `GET /v1/models`            | List available models                  |
| `GET /v1/models/{model}`    | Get model details                      |

### Health & Observability (3 endpoints)

| Endpoint            | Auth Required | Description                           |
| ------------------- | ------------- | ------------------------------------- |
| `GET /health`       | No            | Health check probe                    |
| `GET /readiness`    | No            | Readiness probe (checks orchestrator) |
| `GET /openapi.json` | No            | OpenAPI 3.0 specification             |

## Authentication

<Note>
  **Development**: Authentication is **disabled by default** (`GATEWAY_SKIP_AUTH=1`).

  **Production**: Set `GATEWAY_SKIP_AUTH=0` and use API keys.
</Note>

### API Key Header

```bash theme={null}
curl -H "X-API-Key: sk_test_123456" \
  http://localhost:8080/api/v1/tasks
```

### SSE Streaming Authentication

<Warning>
  Browser `EventSource` cannot send custom headers. In production, proxy SSE via your backend and inject `X-API-Key` or Bearer headers. For SSE endpoints, the `api_key` query parameter is supported as a fallback (e.g., `?api_key=sk_...`).
</Warning>

```javascript theme={null}
const eventSource = new EventSource(
  `/api/v1/stream/sse?workflow_id=${id}`
);
```

## Common Headers

### Request Headers

| Header            | Required   | Description                                |
| ----------------- | ---------- | ------------------------------------------ |
| `X-API-Key`       | Yes\*      | API authentication key                     |
| `Content-Type`    | Yes (POST) | `application/json`                         |
| `Idempotency-Key` | No         | Prevents duplicate submissions (24h cache) |
| `traceparent`     | No         | W3C trace context for distributed tracing  |

\*Not required if `GATEWAY_SKIP_AUTH=1`

### Response Headers

| Header                  | Description                               |
| ----------------------- | ----------------------------------------- |
| `X-Workflow-ID`         | Temporal workflow identifier for tracking |
| `X-Session-ID`          | Session identifier                        |
| `X-RateLimit-Limit`     | Requests allowed per minute               |
| `X-RateLimit-Remaining` | Requests remaining in current window      |
| `X-RateLimit-Reset`     | Unix timestamp when limit resets          |

## Rate Limiting

* **Default**: 60 requests/minute per API key
* **Status**: `429 Too Many Requests` when exceeded
* **Header**: `Retry-After` indicates seconds to wait

```json theme={null}
{
  "error": "Rate limit exceeded",
  "retry_after": 60
}
```

## Idempotency

Prevent duplicate task submissions using `Idempotency-Key` header:

```bash theme={null}
curl -X POST http://localhost:8080/api/v1/tasks \
  -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
  -H "Content-Type: application/json" \
  -d '{"query": "Analyze data"}'
```

**Behavior**:

* Same key within 24 hours returns **cached response**
* Request body is **ignored** for duplicate keys
* Uses Redis for distributed cache

## Error Handling

### HTTP Status Codes

| Code  | Meaning               | Common Causes                         |
| ----- | --------------------- | ------------------------------------- |
| `200` | Success               | Request completed                     |
| `200` | OK                    | Task submitted successfully           |
| `400` | Bad Request           | Invalid JSON, missing required fields |
| `401` | Unauthorized          | Missing or invalid API key            |
| `404` | Not Found             | Task/session not found                |
| `429` | Too Many Requests     | Rate limit exceeded                   |
| `500` | Internal Server Error | Server error                          |
| `502` | Bad Gateway           | Orchestrator unavailable              |
| `503` | Service Unavailable   | System overloaded                     |

### Error Response Format

```json theme={null}
{
  "error": "Task not found"
}
```

## CORS

CORS is enabled for development:

```
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, X-API-Key, Idempotency-Key, traceparent
```

<Warning>
  **Production**: Configure `Access-Control-Allow-Origin` to specific domains.
</Warning>

## Timeouts

| Operation       | Timeout                                               |
| --------------- | ----------------------------------------------------- |
| HTTP Read       | 30 seconds                                            |
| HTTP Write      | 30 seconds                                            |
| HTTP Idle       | 60 seconds                                            |
| Agent Execution | 10 minutes (configurable via `AGENT_TIMEOUT_SECONDS`) |

## Best Practices

### 1. Always Use Idempotency Keys

```python theme={null}
import uuid
import requests

response = requests.post(
    "http://localhost:8080/api/v1/tasks",
    headers={
        "X-API-Key": "sk_test_123456",
        "Idempotency-Key": str(uuid.uuid4())
    },
    json={"query": "Analyze data"}
)
```

### 2. Implement Exponential Backoff

```python theme={null}
import time

def submit_with_retry(query, max_retries=3):
    for attempt in range(max_retries):
        response = requests.post(url, json={"query": query})

        if response.status_code == 429:
            retry_after = int(response.headers.get("Retry-After", 60))
            time.sleep(retry_after)
            continue

        return response
```

### 3. Stream Events for Long Tasks

```python theme={null}
import httpx

with httpx.stream(
    "GET",
    f"http://localhost:8080/api/v1/stream/sse?workflow_id={task_id}",
    headers={"X-API-Key": "sk_test_123456"}
) as response:
    for line in response.iter_lines():
        if line.startswith("data:"):
            event = json.loads(line[5:])
            print(event["type"])
```

### 4. Extract Workflow ID from Response

```python theme={null}
response = requests.post(
    "http://localhost:8080/api/v1/tasks",
    headers={"X-API-Key": "sk_test_123456"},
    json={"query": "Analyze data"}
)

workflow_id = response.headers.get("X-Workflow-ID")
# Use workflow_id for streaming or Temporal UI
```

## Quick Example

```bash theme={null}
#!/bin/bash
API_KEY="sk_test_123456"
BASE="http://localhost:8080/api/v1"

# Submit task
RESPONSE=$(curl -s -X POST "$BASE/tasks" \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query": "What is 2+2?"}')

TASK_ID=$(echo $RESPONSE | jq -r '.task_id')
echo "Task: $TASK_ID"

# Get status
curl -s "$BASE/tasks/$TASK_ID" -H "X-API-Key: $API_KEY" | jq

# Stream events
curl -N "$BASE/stream/sse?workflow_id=$TASK_ID" -H "X-API-Key: $API_KEY"
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Submit Tasks" icon="paper-plane" href="/en/api/rest/submit-task">
    Task submission endpoint
  </Card>

  <Card title="Streaming" icon="stream" href="/en/api/rest/streaming">
    SSE and WebSocket streaming
  </Card>

  <Card title="Sessions" icon="messages" href="/en/api/rest/sessions">
    Session management
  </Card>

  <Card title="Python SDK" icon="python" href="/en/sdk/python/quickstart">
    Use the Python SDK
  </Card>
</CardGroup>
