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

# Streaming responses

> Learn how to consume streaming API responses using Server-Sent Events

Perplexica's Search API supports streaming responses, allowing you to receive results incrementally as they're generated. This provides a better user experience by displaying partial results immediately rather than waiting for the complete response.

## Enable streaming

To enable streaming, set the `stream` parameter to `true` in your search request:

```json theme={null}
{
  "chatModel": {
    "providerId": "550e8400-e29b-41d4-a716-446655440000",
    "key": "gpt-4o-mini"
  },
  "embeddingModel": {
    "providerId": "550e8400-e29b-41d4-a716-446655440000",
    "key": "text-embedding-3-large"
  },
  "sources": ["web"],
  "query": "What is Perplexica",
  "stream": true
}
```

## Response format

When streaming is enabled, the API returns a stream using Server-Sent Events (SSE) with `Content-Type: text/event-stream`. Each line in the stream contains a complete, valid JSON object.

### Stream headers

The streaming response includes these headers:

* `Content-Type: text/event-stream`
* `Cache-Control: no-cache, no-transform`
* `Connection: keep-alive`

### Message types

The stream sends different message types during the search process:

#### init

Sent when the stream connection is established:

```json theme={null}
{"type":"init","data":"Stream connected"}
```

#### sources

Sent once with all sources used to generate the response:

```json theme={null}
{
  "type": "sources",
  "data": [
    {
      "content": "Perplexica is an innovative, open-source AI-powered search engine...",
      "metadata": {
        "title": "What is Perplexica",
        "url": "https://example.com/perplexica"
      }
    }
  ]
}
```

#### response

Sent multiple times with chunks of the generated answer:

```json theme={null}
{"type":"response","data":"Perplexica is an "}
{"type":"response","data":"innovative, open-source "}
{"type":"response","data":"AI-powered search engine..."}
```

#### done

Sent when the stream is complete:

```json theme={null}
{"type":"done"}
```

## Complete example

Here's what a complete streaming response looks like:

```
{"type":"init","data":"Stream connected"}
{"type":"sources","data":[{"content":"...","metadata":{"title":"...","url":"..."}}]}
{"type":"response","data":"Perplexica is an "}
{"type":"response","data":"innovative, open-source "}
{"type":"response","data":"AI-powered search engine..."}
{"type":"done"}
```

## Consuming the stream

Here are examples of how to consume the streaming API in different languages:

<CodeGroup>
  ```javascript JavaScript (Fetch API) theme={null}
  const response = await fetch('http://localhost:3000/api/search', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      chatModel: {
        providerId: '550e8400-e29b-41d4-a716-446655440000',
        key: 'gpt-4o-mini'
      },
      embeddingModel: {
        providerId: '550e8400-e29b-41d4-a716-446655440000',
        key: 'text-embedding-3-large'
      },
      sources: ['web'],
      query: 'What is Perplexica',
      stream: true
    })
  });

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

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    
    const chunk = decoder.decode(value);
    const lines = chunk.split('\n').filter(line => line.trim());
    
    for (const line of lines) {
      const message = JSON.parse(line);
      
      switch (message.type) {
        case 'init':
          console.log('Stream connected');
          break;
        case 'sources':
          console.log('Sources:', message.data);
          break;
        case 'response':
          process.stdout.write(message.data);
          break;
        case 'done':
          console.log('\nStream complete');
          break;
      }
    }
  }
  ```

  ```python Python theme={null}
  import requests
  import json

  url = 'http://localhost:3000/api/search'
  data = {
      'chatModel': {
          'providerId': '550e8400-e29b-41d4-a716-446655440000',
          'key': 'gpt-4o-mini'
      },
      'embeddingModel': {
          'providerId': '550e8400-e29b-41d4-a716-446655440000',
          'key': 'text-embedding-3-large'
      },
      'sources': ['web'],
      'query': 'What is Perplexica',
      'stream': True
  }

  with requests.post(url, json=data, stream=True) as response:
      for line in response.iter_lines():
          if line:
              message = json.loads(line)
              
              if message['type'] == 'init':
                  print('Stream connected')
              elif message['type'] == 'sources':
                  print('Sources:', message['data'])
              elif message['type'] == 'response':
                  print(message['data'], end='', flush=True)
              elif message['type'] == 'done':
                  print('\nStream complete')
  ```

  ```go Go theme={null}
  package main

  import (
  	"bufio"
  	"bytes"
  	"encoding/json"
  	"fmt"
  	"net/http"
  )

  type StreamMessage struct {
  	Type string          `json:"type"`
  	Data json.RawMessage `json:"data"`
  }

  func main() {
  	payload := map[string]interface{}{
  		"chatModel": map[string]string{
  			"providerId": "550e8400-e29b-41d4-a716-446655440000",
  			"key":        "gpt-4o-mini",
  		},
  		"embeddingModel": map[string]string{
  			"providerId": "550e8400-e29b-41d4-a716-446655440000",
  			"key":        "text-embedding-3-large",
  		},
  		"sources": []string{"web"},
  		"query":   "What is Perplexica",
  		"stream":  true,
  	}

  	data, _ := json.Marshal(payload)
  	resp, err := http.Post(
  		"http://localhost:3000/api/search",
  		"application/json",
  		bytes.NewBuffer(data),
  	)
  	if err != nil {
  		panic(err)
  	}
  	defer resp.Body.Close()

  	scanner := bufio.NewScanner(resp.Body)
  	for scanner.Scan() {
  		line := scanner.Text()
  		if line == "" {
  			continue
  		}

  		var message StreamMessage
  		if err := json.Unmarshal([]byte(line), &message); err != nil {
  			continue
  		}

  		switch message.Type {
  		case "init":
  			fmt.Println("Stream connected")
  		case "sources":
  			fmt.Printf("Sources: %s\n", message.Data)
  		case "response":
  			var text string
  			json.Unmarshal(message.Data, &text)
  			fmt.Print(text)
  		case "done":
  			fmt.Println("\nStream complete")
  		}
  	}
  }
  ```
</CodeGroup>

<Note>
  Each line in the stream is a complete JSON object. Make sure to parse each line separately rather than treating the entire stream as a single JSON document.
</Note>

## Stream lifecycle

1. **Connection** - The stream begins with an `init` message
2. **Sources** - A `sources` message contains all references used
3. **Content** - Multiple `response` messages deliver the answer incrementally
4. **Completion** - A `done` message signals the end of the stream

<Warning>
  If the client disconnects before the stream completes, the server will automatically clean up resources and stop processing the request.
</Warning>

## Non-streaming mode

If you prefer to receive the complete response at once, set `stream` to `false` or omit the parameter (defaults to `false`):

```json theme={null}
{
  "chatModel": { ... },
  "embeddingModel": { ... },
  "sources": ["web"],
  "query": "What is Perplexica",
  "stream": false
}
```

The response will be a standard JSON object:

```json theme={null}
{
  "message": "Perplexica is an innovative, open-source AI-powered search engine...",
  "sources": [
    {
      "content": "...",
      "metadata": {
        "title": "...",
        "url": "..."
      }
    }
  ]
}
```
