AI Inference is in preview. Contact support to request access. Models, prices, and limits may change. See Availability during preview for what to expect.
Features
- API keys: Generate and manage keys to authenticate your API requests
- Endpoints: Browse available models with pricing, context length, and capabilities
- Playground: Test models interactively before integrating them
Managing API keys
1
Access API keys
Log in to the dashboard, select a project, and navigate to AI Inference > API keys.
2
Create a key
Click Create key and provide a name for your key.
3
Copy your key
Copy the generated API key immediately. For security, the full key is only shown once.
aitok_ and can be deleted at any time from the API keys page.
Browsing models
1
Access the endpoints page
Log in to the dashboard, select a project, and navigate to AI Inference > Endpoints.
2
Filter models
Click Create endpoint to search models by name and filter by provider or capability (text, vision, code, reasoning).
3
View model details
Select a model, then click Create endpoint to see its endpoint URL, model ID, provider, context length, and input/output pricing per million tokens.
Using the playground
1
Access the playground
Log in to the dashboard, select a project, and navigate to AI Inference > Playground.
2
Configure your request
Pick a model and an API key with the Ready status. If the Key value field appears, paste the full key. Click Try out, then use the settings button to adjust the system prompt, temperature, and max tokens.
3
Send a message
Type your prompt and send it to see the model’s response in real-time.
Making API requests
The AI Inference API is available athttps://api.lsh.ai and is fully compatible with the OpenAI SDK. You can also make direct HTTP requests.
YOUR_API_KEY with your API key. You can find available model IDs on the Endpoints page or with GET /v1/models.
The SDK examples below use the client created above.
Send a
User-Agent header with every request. The OpenAI SDKs and cURL send one. Python’s urllib sends a default that’s blocked with 403 and error code: 1010, so set your own when you use it.Listing models
GET /v1/models lists the models currently offered. It requires a valid API key. Use a model’s id as the model value in your requests.
Models
Prices are in USD per million tokens. The context length counts input and output tokens together.
GET /v1/models returns each model’s context_length and capabilities.
Every response reports its token counts in usage. Input tokens include the model’s chat template, so they’re slightly higher than the tokens in your messages alone. When a request starts with the same tokens as a recent one, those input tokens come from the prompt cache. They’re reported in usage.prompt_tokens_details.cached_tokens and billed at the cached input price. qwen3.8-27b doesn’t use the prompt cache.
Reasoning
Every model reasons before it answers unless you turn reasoning off. The reasoning comes back apart from the answer, inmessage.reasoning, or in message.reasoning_content for glm-5.3 and glm-5.3-flash. When streaming, each chunk’s delta uses the same field. Reasoning tokens are billed as output tokens.
Set reasoning_effort to choose how much a model reasons. To turn reasoning off, pass "chat_template_kwargs": {"enable_thinking": false}. A reasoning_effort value that a model doesn’t accept returns a 400 error.
- glm-5.3 always reasons. It groups the values into three levels:
none,minimal,low, andenable_thinking: falsereason briefly,mediumandhighreason more, andxhigh,max, and the default reason the most. - glm-5.3-flash always reasons. It groups the values into three levels:
none,minimal,low, andenable_thinking: falsereason briefly,mediumandhighreason more, andxhigh,max, and the default reason the most. - gpt-oss-120b always reasons and ignores
enable_thinking. Itsusage.completion_tokens_details.reasoning_tokensis always0. The reasoning tokens are still counted, and billed, incompletion_tokens.
Tool calling
Pass your functions intools. When the model decides to call one, the response has tool_calls instead of an answer. Run the function, append each result as a tool message, and send the conversation again to get the final answer. Every model on this page supports tool calling.
Structured outputs
To get JSON that matches a schema, setresponse_format to json_schema with your JSON Schema. The answer in message.content is a JSON string that follows the schema. Every model on this page supports structured outputs.
Streaming responses
Setstream: true to receive the response as server-sent events while the model generates it. Each event is a data: line that carries a JSON chunk, and the stream ends with data: [DONE].
For chat completions, the last chunk before [DONE] has an empty choices array and a usage object with the token counts. It’s always sent, even if you don’t set stream_options.include_usage.
Long generations
Use streaming for any response that can take longer than about 2 minutes to complete. A non-streaming response arrives only once it’s complete, so a non-streaming request that takes longer than about 2 minutes fails with a504 error. A streaming response sends tokens as they’re generated, which keeps the connection active.
Every request, including streams, is limited to 20 minutes. A stream that sends nothing for about 2 minutes, or reaches that limit, ends without data: [DONE].
Canceling requests
Close the connection to cancel a streaming request. Generation stops when the connection closes.- Python SDK: call
stream.close(), orbreakout of awithblock that wraps the stream. - Node.js SDK:
breakout of thefor awaitloop, or callstream.controller.abort(). - cURL: press Ctrl+C.
Request IDs
Every response, including errors, carries anx-request-id header. Include it when you contact support about a request.
The OpenAI SDKs expose this header as response._request_id. When a request fails, read it from the error: error.request_id in Python, or error.requestID in Node.js. With cURL, add -i to print the response headers.
Rate limits
Each project has its own limits on each model:- Requests: 60 per minute.
- Tokens: 250,000 per minute, input and output combined. A request’s tokens count when it finishes, so one long request can use up the budget and hold the next request until the budget refills.
- Concurrent requests: a share of the model’s capacity, and at least 4. The error message states your current limit.
429 with the rate_limit_exceeded code and a Retry-After header. Wait that many seconds before you retry.
Errors
Errors use the OpenAI error format. Use the HTTP status to decide how to handle an error;error.code identifies the cause.
Retrying requests
A response withx-should-retry: true is safe to retry, and x-should-retry: false means it isn’t. Every 5xx response carries the header: it’s false whenever the request may already have run, such as a 502 or a 504 timeout. The OpenAI SDKs follow this header and the Retry-After delay automatically.
If you use another client, retry only responses marked x-should-retry: true, after the Retry-After delay.
Never retry a stream that has already returned events. A stream that ends without data: [DONE] was interrupted, and a retry runs the whole request again.
Availability during preview
AI Inference is in preview, and some models run in a single location. While that location has a hardware failure, or while we update the model, requests to that model fail with a503 until it’s back. Retry 503 responses after the Retry-After delay.
The list of models can change. Check GET /v1/models for the models offered now.