> Fetch https://askmiles.ai/llms.txt first: it indexes every public Miles capability. This file is the markdown twin of https://askmiles.ai/docs/chat-api/request-and-streaming.

# Requests and streaming

The request body, a complete non-streaming call, and a streaming call with what each server-sent chunk looks like.

## The request

A JSON object with `model` and `messages`. `stream: true` switches to server-sent events; `stream_options: {"include_usage": true}` is accepted. Other OpenAI fields (`temperature`, `tools`, `response_format`) are ignored: Miles decides how it answers.

```bash
curl https://askmiles.ai/v1/chat/completions \
  -H "Authorization: Bearer $MILES_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "miles", "messages": [{"role": "user", "content": "Which card should I use at Costco?"}]}'
```

## With the SDK

```python
from openai import OpenAI

client = OpenAI(base_url="https://askmiles.ai/v1", api_key=MILES_API_KEY)
response = client.chat.completions.create(
    model="miles",
    messages=[{"role": "user", "content": "Which card should I use at Costco?"}],
)
print(response.choices[0].message.content)
```

Set the key from your environment rather than the source file; a key is shown once at mint and never again.

## Streaming

The body is the same with `stream: true`. The response is `text/event-stream`: a sequence of `data:` lines, each an OpenAI chat completion chunk, ending with `data: [DONE]`.

```text
data: {"id":"chatcmpl-…","object":"chat.completion.chunk","model":"miles","choices":[{"index":0,"delta":{"role":"assistant","content":"At a Costco warehouse"},"finish_reason":null}]}

data: {"id":"chatcmpl-…","object":"chat.completion.chunk","model":"miles","choices":[{"index":0,"delta":{"content":", use your"},"finish_reason":null}]}

data: {"id":"chatcmpl-…","object":"chat.completion.chunk","model":"miles","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}

data: [DONE]
```

```python
from openai import OpenAI

client = OpenAI(base_url="https://askmiles.ai/v1", api_key=MILES_API_KEY)
with client.chat.completions.create(
    model="miles",
    messages=[{"role": "user", "content": "Is the Sapphire Reserve worth keeping?"}],
    stream=True,
) as stream:
    for chunk in stream:
        delta = chunk.choices[0].delta.content
        if delta:
            print(delta, end="", flush=True)
```

Nothing arrives until Miles starts writing the answer, which is after classification, tool calls and reasoning: expect 15 to 23 seconds of silence on a simple question. An error after the stream has opened arrives as one final `data:` event carrying the same `error` envelope a non-streaming call would return, then `[DONE]`.

## Follow-ups

Miles holds no state. To ask a follow-up, resend the earlier turns as `assistant` and `user` messages ahead of the new question. Only the last 26 messages are read.

## Rate limits

Every response carries the rate-limit headers, streams included; see [Rate limits](https://askmiles.ai/docs/chat-api/rate-limits).
