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

> Learn how to handle streaming responses from the V3 LLM endpoint using Server-Sent Events (SSE).

# Streaming

export const TechArticleSchema = ({title, description, path, articleSection, about, proficiencyLevel = "Beginner", dependencies, keywords = [], datePublished, dateModified, image, inLanguage = "en"}) => {
  const baseUrl = "https://www.edenai.co/docs";
  const canonicalUrl = `${baseUrl}/${path}`.replace(/\/+$/, "");
  const ogParams = new URLSearchParams({
    division: articleSection || "",
    title: title || "",
    description: description || ""
  });
  const resolvedImage = image || `https://edenai.mintlify.app/_mintlify/api/og?${ogParams.toString()}`;
  const data = {
    "@context": "https://schema.org",
    "@type": "TechArticle",
    "@id": `${canonicalUrl}#techarticle`,
    mainEntityOfPage: {
      "@type": "WebPage",
      "@id": canonicalUrl
    },
    headline: title,
    name: title,
    description: description,
    url: canonicalUrl,
    inLanguage: inLanguage,
    isPartOf: {
      "@type": "WebSite",
      name: "Eden AI Documentation",
      url: baseUrl
    },
    author: [{
      "@type": "Organization",
      name: "Eden AI",
      url: "https://www.edenai.co/"
    }],
    publisher: {
      "@type": "Organization",
      name: "Eden AI",
      url: "https://www.edenai.co/",
      logo: {
        "@type": "ImageObject",
        url: "https://www.edenai.co/assets/logo.png"
      }
    }
  };
  if (articleSection) data.articleSection = articleSection;
  if (about) data.about = {
    "@type": "Thing",
    name: about
  };
  if (proficiencyLevel) data.proficiencyLevel = proficiencyLevel;
  if (dependencies) data.dependencies = dependencies;
  if (keywords && keywords.length) data.keywords = keywords;
  if (datePublished) data.datePublished = datePublished;
  if (dateModified) data.dateModified = dateModified;
  data.image = Array.isArray(resolvedImage) ? resolvedImage : [resolvedImage];
  const json = JSON.stringify(data);
  const schemaId = `techarticle-${canonicalUrl}`;
  React.useEffect(() => {
    if (typeof document === "undefined") return;
    document.querySelectorAll(`script[data-schema-id="${schemaId}"]`).forEach(n => n.remove());
    const script = document.createElement("script");
    script.type = "application/ld+json";
    script.dataset.schemaId = schemaId;
    script.textContent = json;
    document.head.appendChild(script);
    return () => script.remove();
  }, [json, schemaId]);
  return null;
};

<TechArticleSchema title={"Streaming"} description={"Learn how to handle streaming responses from the V3 LLM endpoint using Server-Sent Events (SSE)."} path="v3/llms/streaming" articleSection="LLMs" about={"LLM API"} proficiencyLevel="Intermediate" keywords={["Eden AI", "AI API", "LLM API", "chat completion", "OpenAI compatible"]} datePublished="2026-05-06T00:00:00Z" dateModified="2026-05-07T00:00:00Z" />

Learn how to handle streaming responses from the V3 LLM endpoint using Server-Sent Events (SSE).

## Overview

When streaming is enabled in V3, LLM responses are delivered via Server-Sent Events (SSE), providing real-time token-by-token output.

**Benefits:**

* Immediate response feedback
* Better user experience with progressive display
* Lower perceived latency

## Server-Sent Events Format

SSE responses follow this pattern:

```
data: {JSON_CHUNK}

data: {JSON_CHUNK}

data: [DONE]
```

Each line starts with `data: ` followed by JSON or the `[DONE]` marker.

## Python with OpenAI SDK

<CodeGroup>
  ```python Python theme={null}
  from openai import OpenAI

  client = OpenAI(
      api_key="YOUR_EDEN_AI_API_KEY",
      base_url="https://api.edenai.run/v3"
  )

  stream = client.chat.completions.create(
      model="anthropic/claude-sonnet-4-5",
      messages=[{"role": "user", "content": "Tell me a short story"}],
      stream=True
  )

  full_content = ""

  for chunk in stream:
      if chunk.choices[0].delta.content:
          content = chunk.choices[0].delta.content
          full_content += content
          print(content, end='', flush=True)

  print(f"\n\nComplete response: {full_content}")
  ```
</CodeGroup>

## JavaScript with Fetch API

<CodeGroup>
  ```javascript JavaScript theme={null}
  const url = 'https://api.edenai.run/v3/chat/completions';
  const headers = {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  };

  const payload = {
    model: 'openai/gpt-4',
    messages: [{role: 'user', content: 'Tell me a short story'}],
    stream: true
  };

  const response = await fetch(url, {
    method: 'POST',
    headers: headers,
    body: JSON.stringify(payload)
  });

  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(); // Keep incomplete line in buffer

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

        if (data === '[DONE]') {
          console.log('\nStream finished');
          break;
        }

        try {
          const chunk = JSON.parse(data);
          const content = chunk.choices[0]?.delta?.content;
          if (content) {
            process.stdout.write(content);
          }
        } catch (e) {
          // Ignore parse errors
        }
      }
    }
  }
  ```
</CodeGroup>

## Chunk Structure

Each JSON chunk follows OpenAI's format:

```json theme={null}
{
  "id": "chatcmpl-abc123",
  "object": "chat.completion.chunk",
  "created": 1677652288,
  "model": "gpt-4",
  "choices": [
    {
      "index": 0,
      "delta": {
        "content": "Hello"
      },
      "finish_reason": null
    }
  ]
}
```

### Key Fields

| Field                     | Description                |
| ------------------------- | -------------------------- |
| `id`                      | Unique completion ID       |
| `created`                 | Unix timestamp             |
| `model`                   | Model used                 |
| `choices[].delta.role`    | Role (only in first chunk) |
| `choices[].delta.content` | Token content              |
| `choices[].finish_reason` | Stop reason in final chunk |

## Finish Reasons

| Value            | Meaning                       |
| ---------------- | ----------------------------- |
| `stop`           | Completed normally            |
| `length`         | Stopped at `max_tokens` limit |
| `content_filter` | Stopped by content policy     |
| `tool_calls`     | Stopped to invoke a tool      |

## Next Steps

<CardGroup cols={2}>
  <Card title="Plans & Pricing" icon="book-open" href="/v3/overview/plans-prices">
    Understand how streaming usage is billed
  </Card>
</CardGroup>
