# HTTP API

> AppPlugin provides the HTTP runtime, and HttpPlugin exposes session and turn endpoints.

`AppPlugin` is the shared axum runtime for Polaris HTTP products. It binds a listener, merges route fragments, and applies middleware such as CORS, request IDs, and tracing.

Import the HTTP runtime through `polaris_ai::app` and enable the `sessions-http` feature. There is no separate app-crate dependency needed.

Session endpoints come from `polaris_ai::sessions::HttpPlugin`. In practice:

* `AppPlugin` starts the server and owns the shared `HttpRouter`
* `HttpPlugin` adds `/v1/sessions/...` routes backed by `SessionsAPI`
* your own plugins can add extra routes such as `/healthz` or `/v1/info`

## How it fits together

Add `AppPlugin` to provide the HTTP runtime, then layer `SessionsPlugin` and `HttpPlugin` on top.

```toml
[dependencies]
polaris-ai = { git = "https://github.com/RadiantAILabs/polaris", rev = "5ff84646db63589d58bf87956976d749b8c754de", features = ["sessions-http", "anthropic"] }
```

```rust
use polaris_ai::app::{AppConfig, AppPlugin};
use polaris_ai::plugins::PersistencePlugin;
use polaris_ai::models::AnthropicPlugin;
use polaris_ai::models::ModelsPlugin;
use polaris_ai::sessions::HttpPlugin;
use polaris_ai::sessions::{InMemoryStore, SessionsPlugin};
use polaris_ai::system::server::Server;
use polaris_ai::tools::ToolsPlugin;
use std::sync::Arc;


let mut server = Server::new();
server
    .add_plugins(ModelsPlugin)
    .add_plugins(AnthropicPlugin::from_env("ANTHROPIC_API_KEY"))
    .add_plugins(ToolsPlugin)
    .add_plugins(PersistencePlugin)
    .add_plugins(SessionsPlugin::new(Arc::new(InMemoryStore::new())))
    .add_plugins(
        AppPlugin::new(
            AppConfig::new()
                .with_host("0.0.0.0")
                .with_port(3000),
        ),
    )
    .add_plugins(HttpPlugin::new());
```

This assembles the runtime; it does not register an agent. Register your `Agent` implementation through `SessionsAPI` from a plugin during startup, then await `server.run()`. For a runnable server, start from the [public HTTP example](https://github.com/RadiantAILabs/polaris/tree/main/examples) rather than sending requests to an empty agent registry.

## Configuration

`AppPlugin` accepts an `AppConfig`.

```rust
use polaris_ai::app::AppConfig;


let config = AppConfig::new()
    .with_host("0.0.0.0")
    .with_port(3000)
    .with_cors_origin("http://localhost:5173");
```

The server starts during `ready()`, after all plugins have registered their routes.

## Session endpoints

`HttpPlugin` exposes these routes:

| Method   | Path                               | Description                                   |
| -------- | ---------------------------------- | --------------------------------------------- |
| `POST`   | `/v1/sessions`                     | Create a live session                         |
| `GET`    | `/v1/sessions`                     | List live sessions                            |
| `GET`    | `/v1/sessions/stored`              | List persisted sessions                       |
| `GET`    | `/v1/sessions/agent-types`         | List registered agent names                   |
| `GET`    | `/v1/sessions/agent-types/details` | Auth-protected graph signatures and contracts |
| `POST`   | `/v1/sessions/{id}/turns/stream`   | Process a turn with SSE                       |
| `GET`    | `/v1/sessions/{id}/turns`          | List recorded turn summaries                  |
| `GET`    | `/v1/sessions/{id}/turns/{n}`      | Inspect one turn                              |
| `GET`    | `/v1/sessions/{id}/uptime`         | Read bucketed lifecycle history               |
| `GET`    | `/v1/sessions/{id}`                | Get session metadata                          |
| `DELETE` | `/v1/sessions/{id}`                | Delete a session                              |
| `POST`   | `/v1/sessions/{id}/turns`          | Process one turn                              |
| `POST`   | `/v1/sessions/{id}/checkpoints`    | Create a checkpoint                           |
| `GET`    | `/v1/sessions/{id}/checkpoints`    | List checkpoints                              |
| `POST`   | `/v1/sessions/{id}/rollback`       | Roll back to a checkpoint                     |
| `POST`   | `/v1/sessions/{id}/save`           | Persist a session                             |
| `POST`   | `/v1/sessions/{id}/resume`         | Resume a persisted session                    |

### Create a session

```text
POST /v1/sessions
```

Creates a new session for a registered agent type.

**Request body:**

```json
{
  "agent_type": "react_agent"
}
```

**Response (201 Created):**

```json
{
  "session_id": "user-123-conversation-1",
  "agent_type": "react_agent",
  "turn_number": 0,
  "created_at": "2026-04-08T10:12:34Z",
  "status": "active"
}
```

`session_id` is optional. If you omit it, Polaris generates one for you.

The `agent_type` must match an agent already registered with `SessionsAPI`.

### Process a turn

```text
POST /v1/sessions/{session_id}/turns
```

Sends one user message to the agent and returns the result of one turn.

**Request body:**

```json
{
  "message": "What files are in the current directory?"
}
```

**Response (200 OK):**

```json
{
  "messages": [
    {
      "type": "assistant_text",
      "text": "Here are the files in the current directory: ..."
    }
  ],
  "execution": {
    "nodes_executed": 5,
    "duration_ms": 1230,
    "turn_number": 1
  }
}
```

The handler bridges the HTTP request into agent IO with `HttpIOProvider`, executes one turn, then returns the emitted messages plus execution metadata.

### List sessions

```text
GET /v1/sessions
```

Returns metadata for live in-memory sessions.

**Response (200 OK):**

```json
{
  "sessions": [
    {
      "session_id": "user-123-conversation-1",
      "agent_type": "react_agent",
      "turn_number": 1,
      "created_at": "2026-04-08T10:12:34Z",
      "status": "active"
    }
  ]
}
```

### Get session info

```text
GET /v1/sessions/{session_id}
```

Returns metadata about a specific session.

### Delete a session

```text
DELETE /v1/sessions/{session_id}
```

Removes the session from memory and deletes it from the backing store if one is configured.

**Response (204 No Content)**

### Checkpoints, rollback, save, and resume

```text
POST /v1/sessions/{session_id}/checkpoints
GET  /v1/sessions/{session_id}/checkpoints
POST /v1/sessions/{session_id}/rollback
POST /v1/sessions/{session_id}/save
POST /v1/sessions/{session_id}/resume
```

These routes map directly to the checkpointing and persistence methods on `SessionsAPI`.

### Rollback a session

```text
POST /v1/sessions/{session_id}/rollback
```

**Request body:**

```json
{
  "turn_number": 2
}
```

**Response (200 OK):**

```json
{
  "session_id": "user-123-conversation-1",
  "agent_type": "react_agent",
  "turn_number": 2
}
```

The target turn must correspond to an existing checkpoint.

## Custom routes

If you want to add routes beyond the session API, register them through `HttpRouter` in another plugin:

```rust
use axum::{Router, routing::get};
use polaris_ai::app::{AppPlugin, HttpRouter};
use polaris_ai::system::plugin::{Plugin, PluginId, Version};
use polaris_ai::system::server::Server;


struct HealthPlugin;


impl Plugin for HealthPlugin {
    const ID: &'static str = "example::health";
    const VERSION: Version = Version::new(0, 0, 1);


    fn build(&self, server: &mut Server) {
        server
            .api::<HttpRouter>()
            .expect("AppPlugin must be added first")
            .add_routes(Router::new().route("/healthz", get(|| async { "ok" })));
    }


    fn dependencies(&self) -> Vec<PluginId> {
        vec![PluginId::of::<AppPlugin>()]
    }
}
```

## Error responses

When a request fails, the response uses a standard error format.

```json
{
  "error": "session_not_found",
  "message": "no session with ID 'nonexistent'"
}
```

HTTP status codes map to error types: 404 for missing sessions or agents, 400 for invalid request bodies, and 500 for execution failures.

## Authentication and embedding

Configure an `AuthProvider` when your deployment requires authenticated requests. Protected agent-signature metadata is mounted only when authentication is configured. The standalone `sessions_router` helper carries no authentication or shared app middleware; an embedding application must apply those itself.
