What you will build and need#
You will create a small local program that sends a short text to the API and prints a summary. An API connects your own software; ordinary Grok chat use does not require one. You need Python 3, internet access, an API console account, an available model and active billing.
This procedure was checked against the documentation. We did not make a paid request, so we do not claim a tested output or cost for a particular run.
Prepare the account and key#
- Select the correct team in the console and check billing. Start with a small budget and automatic top-ups disabled until you understand usage.
- Create a project-specific key on the API Keys page. Keep it in a secrets manager or an environment variable.
- Set
XAI_API_KEYto your key andXAI_MODELto the identifier below. The commands differ between shells; in production, use your host’s secret settings. - Keep the key out of visitors’ browsers, public repositories and prompts. A
.envfile must also stay out of a public project.
Model identifier for this example:
Before using it, confirm that it appears in your team’s console. If a key leaks, revoke it, create a new one and review usage.
Your first request#
Save the code as first_request.py and run python3 first_request.py in an environment with the variables configured. It uses only Python’s standard library and the documented Responses API.
import json
import os
import urllib.request
payload = {
"model": os.environ["XAI_MODEL"],
"input": "Summarise only this text in one sentence: The meeting is on Tuesday at 10:00. We will discuss the training plan.",
"store": False,
}
request = urllib.request.Request(
"https://api.x.ai/v1/responses",
data=json.dumps(payload).encode("utf-8"),
headers={
"Authorization": "Bearer " + os.environ["XAI_API_KEY"],
"Content-Type": "application/json",
},
method="POST",
)
with urllib.request.urlopen(request, timeout=120) as response:
result = json.load(response)
for item in result.get("output", []):
for part in item.get("content", []):
if part.get("type") == "output_text":
print(part["text"])
print("Usage:", result.get("usage", {}))Expect one sentence containing Tuesday, the time and the training topic. For example: Illustrative output: The training-planning meeting is on Tuesday at 10:00. Compare the answer with the input and inspect usage. An empty output is not success: check the response status and structure.
store: false disables storing conversation state for continuation through the Responses API. It does not replace the team’s zero data retention (ZDR) setting or promise zero audit retention.
Keep costs under control#
Send one small sample before running a batch. Measure actual usage on typical inputs, allow for retries and only then estimate a daily budget. Limit both request counts and input size in your application. A short answer does not by itself guarantee low reasoning usage.
If you add search or another tool, check its separate rate. Do not infer image, video or voice costs from text-token pricing. A foreign-currency rate here is not an official euro price for Slovakia.
Current information and tools#
The short example above uses only the supplied text. For current research, enable the appropriate API tool. The documentation lists web_search for the web and x_search for X in the tools field. Writing “search” in a prompt does not replace tool configuration in your program.
"tools": [{"type": "web_search"}]After adding a tool, inspect the returned links and tool calls as well as the answer. Preserve citations when displaying results. For functions that write to other systems, validate arguments on the server and obtain specific user approval before an irreversible step.
Output your application can process#
Before sending an answer to a database or another service, define fields, types and the missing-value rule. An order number stored as text preserves leading zeroes; an unknown deadline should remain empty or null, rather than becoming an invented date.
For a supported model, use the documented structured outputs. Then validate both schema and meaning on your server: valid JSON does not establish a correct total, an authorized recipient or support in the source.
Extract only the order number, currency, amount and deadline from the supplied material. Use null for missing values. Do not estimate them. Preserve a reference to the source line or section for each value so it can be checked.
This is an extraction brief, not a complete API configuration. Before a batch, test a valid input, a missing field, an invalid format and an ambiguous value. A failure must not silently overwrite an existing record.
When a request fails#
- 401: check the key variable and Authorization header. Never print the key in shared logs.
- 403: check team or key permissions.
- 404: compare the address and model identifier with the documentation.
- 400 or 422: check JSON formatting and supported parameters.
- 429: reduce concurrency and wait. Use a limited number of retries with increasing delays; an endless loop makes matters worse.
After a timeout, first check whether the service already processed the request. Retrying can create another billable request. For a broader outage, check service status. Send support the request identifier and a sanitised description, never the secret key.
Data and your next step#
For business deployment, record the processing purpose, transmitted fields, permissions, storage and deletion process. Do not treat consumer-chat training settings as API rules. Then prepare a small test set: a valid input, empty text, long text and an unexpected format. Automate only after checking results and costs.