Chat API
Read this page as MarkdownIn this section: Requests 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.
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
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].
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]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.