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

# Streaming (SSE)

> Server-Sent Events format, section-by-section notebook streaming, progress tracking, and client integration examples.

## Overview

The High IQ API uses **Server-Sent Events (SSE)** for real-time streaming of AI-generated notebook sections. Notebooks are generated section-by-section, with each section streamed as a series of events: `start`, `partial`, `complete`, or `error`. This allows the client to render content progressively as it is generated.

The streaming service is built on [Hono SSE](https://hono.dev/helpers/streaming#sse-streaming) with [AI SDK 7](https://sdk.vercel.ai/) `streamText()` and `Output.object()` for structured output with partial updates.

## Endpoints

| Endpoint                               | Method | Description                          |
| -------------------------------------- | ------ | ------------------------------------ |
| `/api/v1/notebooks/stream/health`      | `GET`  | Health check for streaming service   |
| `/api/v1/notebooks/stream/sections`    | `GET`  | List available section keys          |
| `/api/v1/notebooks/stream/:sectionKey` | `POST` | Stream a single notebook section     |
| `/api/v1/notebooks/stream/batch`       | `POST` | Stream multiple sections in sequence |

## Single Section Streaming

Stream a single notebook section by its key. Returns an SSE stream with progressive updates.

### Request

```bash theme={null}
curl -X POST "https://api.thisiswhyimhigh.com/api/v1/notebooks/stream/terpene_analysis" \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{
    "orderItems": [
      {
        "strainName": "Blue Dream",
        "grams": 3.5,
        "type": "hybrid",
        "thcPct": 21,
        "terpenes": [
          { "name": "Myrcene", "percentage": 0.45 },
          { "name": "Caryophyllene", "percentage": 0.32 }
        ]
      }
    ],
    "orderMetadata": {
      "dispensaryName": "Green Leaf",
      "orderDate": "2026-02-15",
      "totalSpent": 45.00
    }
  }'
```

### Request Body Schema

```typescript theme={null}
{
  orderItems?: {
    strainName: string;
    grams: number;
    price?: number;
    thcPct?: number;
    cbdPct?: number;
    type?: 'sativa' | 'indica' | 'hybrid';
    terpenes?: { name: string; percentage: number }[];
    effects?: string[];
    aromas?: string[];
  }[];
  orderMetadata?: {
    dispensaryName?: string;
    orderDate?: string;
    totalSpent?: number;
  };
  previousSections?: Record<string, unknown>;
}
```

### SSE Event Stream

The server sends events in the standard SSE format. Each event has a `type`, `sectionKey`, and optional data:

```
event: start
id: a1b2c3d4-uuid
data: {"type":"start","sectionKey":"terpene_analysis","estimatedTokens":500}

event: partial
id: a1b2c3d4-uuid
data: {"type":"partial","sectionKey":"terpene_analysis","data":{"title":"Terpene Profile"},"progress":25}

event: partial
id: a1b2c3d4-uuid
data: {"type":"partial","sectionKey":"terpene_analysis","data":{"title":"Terpene Profile","summary":"Your order features..."},"progress":60}

event: complete
id: a1b2c3d4-uuid
data: {"type":"complete","sectionKey":"terpene_analysis","data":{"title":"Terpene Profile","summary":"Your order features a myrcene-dominant profile...","insights":["..."]},"progress":100}
```

## Batch Section Streaming

Stream multiple sections in sequence. Each section is generated one after another, with overall progress tracking. Previously generated sections are passed as context to dependent sections.

### Request

```bash theme={null}
curl -X POST "https://api.thisiswhyimhigh.com/api/v1/notebooks/stream/batch" \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{
    "sectionKeys": ["overview", "terpene_analysis", "effects_breakdown"],
    "orderItems": [
      {
        "strainName": "OG Kush",
        "grams": 7,
        "type": "indica",
        "thcPct": 24
      }
    ]
  }'
```

### Batch Request Schema

```typescript theme={null}
{
  sectionKeys: string[];  // At least one section key required
  orderItems?: OrderItem[];
  orderMetadata?: OrderMetadata;
}
```

### Batch Event Stream

Batch streaming adds `batch_start` and `batch_complete` events, plus overall progress tracking on each section event:

```
event: batch_start
id: req-uuid
data: {"type":"batch_start","totalSections":3,"sectionKeys":["overview","terpene_analysis","effects_breakdown"]}

event: start
id: req-uuid-overview
data: {"type":"start","sectionKey":"overview","overallProgress":0,"completedSections":0,"totalSections":3}

event: partial
id: req-uuid-overview
data: {"type":"partial","sectionKey":"overview","progress":50,"overallProgress":16,"completedSections":0,"totalSections":3}

event: complete
id: req-uuid-overview
data: {"type":"complete","sectionKey":"overview","data":{...},"progress":100,"overallProgress":33,"completedSections":1,"totalSections":3}

event: start
id: req-uuid-terpene_analysis
data: {"type":"start","sectionKey":"terpene_analysis","overallProgress":33,"completedSections":1,"totalSections":3}

...

event: batch_complete
id: req-uuid
data: {"type":"batch_complete","totalSections":3,"completedSections":3,"results":{"overview":{...},"terpene_analysis":{...},"effects_breakdown":{...}}}
```

## Event Types

| Event            | Description                           | Fields                                             |
| ---------------- | ------------------------------------- | -------------------------------------------------- |
| `batch_start`    | Batch streaming has begun             | `totalSections`, `sectionKeys`                     |
| `start`          | Individual section generation started | `sectionKey`, `estimatedTokens`                    |
| `partial`        | Partial structured data available     | `sectionKey`, `data` (partial), `progress` (0-100) |
| `complete`       | Section fully generated               | `sectionKey`, `data` (complete), `progress` (100)  |
| `error`          | Section generation failed             | `sectionKey`, `error` (message)                    |
| `batch_complete` | All sections finished                 | `totalSections`, `completedSections`, `results`    |

### Batch-Enriched Fields

In batch mode, every section event includes additional fields for overall progress:

| Field               | Type     | Description                          |
| ------------------- | -------- | ------------------------------------ |
| `overallProgress`   | `number` | 0-100 percentage across all sections |
| `completedSections` | `number` | Count of finished sections           |
| `totalSections`     | `number` | Total sections in the batch          |

## StreamEvent Interface

```typescript theme={null}
interface StreamEvent {
  type: 'start' | 'partial' | 'complete' | 'error';
  sectionKey: string;
  data?: unknown;        // Partial or complete structured data
  progress?: number;     // 0-100 section progress
  text?: string;         // Raw text output
  error?: string;        // Error message (type: 'error' only)
  estimatedTokens?: number; // Estimated token count (type: 'start' only)
}
```

## Available Sections

Fetch the list of available section keys and their metadata:

```bash theme={null}
curl "https://api.thisiswhyimhigh.com/api/v1/notebooks/stream/sections"
```

```json theme={null}
{
  "sections": [
    {
      "key": "overview",
      "label": "Overview",
      "tab": "summary",
      "order": 1,
      "strategy": "ai",
      "estimatedTokens": 500
    },
    {
      "key": "terpene_analysis",
      "label": "Terpene Analysis",
      "tab": "science",
      "order": 2,
      "strategy": "ai",
      "estimatedTokens": 800
    }
  ],
  "totalSections": 12
}
```

<Note>
  Sections with `strategy: "computed"` are handled client-side and cannot be streamed. The API returns a message indicating the section should be computed locally.
</Note>

## Client Integration

### JavaScript / TypeScript (EventSource)

```typescript theme={null}
const response = await fetch(
  'https://api.thisiswhyimhigh.com/api/v1/notebooks/stream/batch',
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Accept': 'text/event-stream',
    },
    body: JSON.stringify({
      sectionKeys: ['overview', 'terpene_analysis'],
      orderItems: [{ strainName: 'Blue Dream', grams: 3.5 }],
    }),
  }
);

const reader = response.body!.getReader();
const decoder = new TextDecoder();

let buffer = '';
while (true) {
  const { done, value } = await reader.read();
  if (done) break;

  buffer += decoder.decode(value, { stream: true });
  const lines = buffer.split('\n');
  buffer = lines.pop() || '';

  for (const line of lines) {
    if (line.startsWith('data: ')) {
      const event = JSON.parse(line.slice(6));

      switch (event.type) {
        case 'start':
          console.log(`Starting ${event.sectionKey}...`);
          break;
        case 'partial':
          // Update UI with partial data
          updateSection(event.sectionKey, event.data, event.progress);
          break;
        case 'complete':
          // Section finished
          finalizeSection(event.sectionKey, event.data);
          break;
        case 'error':
          console.error(`Error in ${event.sectionKey}: ${event.error}`);
          break;
      }
    }
  }
}
```

### React Native (High IQ Mobile)

The mobile app uses custom hooks for SSE consumption:

```typescript theme={null}
import { useStreamingNotebookGeneration } from '@/_hooks/useStreamingNotebookGeneration';

function NotebookScreen({ orderItems }) {
  const {
    sections,
    overallProgress,
    isStreaming,
    error,
    startGeneration,
  } = useStreamingNotebookGeneration();

  const handleGenerate = () => {
    startGeneration({
      sectionKeys: ['overview', 'terpene_analysis', 'effects_breakdown'],
      orderItems,
    });
  };

  return (
    <View>
      <ProgressBar progress={overallProgress} />
      {Object.entries(sections).map(([key, section]) => (
        <StreamingSectionCard
          key={key}
          sectionKey={key}
          data={section.data}
          progress={section.progress}
          status={section.status}
        />
      ))}
    </View>
  );
}
```

## Error Handling

If a section fails during streaming, an `error` event is sent for that section and the batch continues to the next section. The `batch_complete` event includes the count of successfully completed sections.

```
event: error
id: req-uuid-failing_section
data: {"type":"error","sectionKey":"failing_section","error":"AI model timeout","overallProgress":66,"completedSections":2,"totalSections":3}
```

If the streaming service itself is unavailable, the API returns a `503` response before streaming begins:

```json theme={null}
{
  "error": "Streaming service is not available",
  "code": "SERVICE_UNAVAILABLE"
}
```

## Health Check

Verify the streaming service is available before initiating a stream:

```bash theme={null}
curl "https://api.thisiswhyimhigh.com/api/v1/notebooks/stream/health"
```

```json theme={null}
{
  "available": true,
  "service": "section-streaming",
  "timestamp": "2026-02-16T12:00:00.000Z",
  "aiSectionsCount": 12
}
```

Check `available: true` before starting a notebook generation flow. If `false`, AI models may not be configured or the service is temporarily unavailable.
