Your First API Call in Python
On this page
Your First Exchange with a Mistral Model
The SDK is installed and your API key is ready: it’s time to send a real request and, more importantly, understand what comes back. Many developers stop at the first line of the response and ignore the rest of the returned object. That’s a mistake, because cost tracking and diagnostics for truncated responses live precisely in that remaining data. We’ll start with minimal code and work our way up to the full structure.
Initialize the Client
The client is the entry point for all your interactions with the API:
import os
from mistralai.client import Mistral
client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])
It handles HTTP connections, retries on network errors, and request serialization. Instantiate it once at application startup. Recreating a client for every call forces you to pay for connection setup unnecessarily and is one of the most subtle causes of excessive latency.
Send a Request with chat.complete()
You’ll use the chat.complete() method most often. It sends your messages and waits for the model’s full response before returning control:
response = client.chat.complete(
model="mistral-small-latest",
messages=[
{
"role": "user",
"content": "Explain the concept of tokenization in three sentences."
}
]
)
print(response.choices[0].message.content)
Two parameters are enough here. model specifies the model ID: mistral-small-latest always points to the latest version of Mistral Small, making it the natural choice to get started since it’s fast and economical. messages expects a list of structured messages, each with a role—system, user, or assistant—and a content field holding the text. This structure may seem heavy for a single question, but it makes perfect sense once you reach the lesson on multi-turn conversations.
Read the Returned Object
The response object contains much more than just the generated text:
# Response text
text = response.choices[0].message.content
# Role (always "assistant" for a response)
role = response.choices[0].message.role
# Stop reason
finish = response.choices[0].finish_reason # "stop", "length", etc.
# Token statistics
input_tokens = response.usage.prompt_tokens
output_tokens = response.usage.completion_tokens
total_tokens = response.usage.total_tokens
print(f"Response ({output_tokens} tokens): {text}")
print(f"Total tokens consumed: {total_tokens}")
Pay close attention to the usage field from day one. Logging it on every call tells you exactly which feature of your application is burning through your budget, without having to reverse-engineer your bill at the end of the month.
As for finish_reason, it indicates why the model stopped and takes one of these values:
stop: the model finished its response naturallylength: the response was cut off because it hitmax_tokensmodel_length: the total context (input + output) reached the model’s limit
A response that ends mid-sentence isn’t a model bug: it’s a finish_reason of length that no one checked. Always verify this before concluding there’s a quality issue.
Adjust Model Behavior
Three additional parameters let you steer generation:
response = client.chat.complete(
model="mistral-large-latest",
messages=[
{
"role": "user",
"content": "Propose three names for an educational AI startup."
}
],
temperature=0.7,
max_tokens=500,
top_p=0.95,
)
Temperature controls the model’s degree of freedom. At 0.0, responses are deterministic: the same prompt always produces the same text, which is what you want for extraction or classification. Between 0.3 and 0.5, you get a good balance for factual tasks. Between 0.7 and 1.0, responses become more creative and varied—this is the range used in the example above, since we’re asking for name ideas and seeing the same idea three times would be pointless. Above 1.0, generation becomes highly random and rarely has practical utility.
max_tokens caps the response length, which helps control costs and keeps outputs manageable. Just remember that if the model gets cut off, finish_reason will be "length". top_p affects diversity through a different mechanism: it filters out the least probable tokens. A value of 0.95 means the model considers only tokens representing 95% of the cumulative probability.
A Production-Ready Call
In real-world conditions, the network drops, keys expire, and quotas fill up. Always wrap your calls in error handling:
import os
from mistralai.client import Mistral
client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])
try:
response = client.chat.complete(
model="mistral-small-latest",
messages=[
{"role": "user", "content": "What is the capital of France?"}
],
max_tokens=100,
)
text = response.choices[0].message.content
print(f"Response: {text}")
print(f"Tokens used: {response.usage.total_tokens}")
except Exception as e:
print(f"API call error: {e}")
Use this skeleton for your own experiments by simply replacing the message content. It’s the starting point for everything that follows in this course.
Key Takeaways
client.chat.complete()is the primary method for interacting with models- The response text is in
response.choices[0].message.content response.usagetells you how many tokens were consumed (useful for cost tracking)temperaturecontrols creativity;max_tokenslimits length- Start with
mistral-small-latest: it’s fast, economical, and performant