Skip to main content
Latitude.sh AI Inference provides access to AI models through a unified, OpenAI-compatible API. Run open-weight text, vision, and reasoning models from DeepSeek, Z.ai, OpenAI, and Qwen.
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.
API keys are prefixed with 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 at https://api.lsh.ai and is fully compatible with the OpenAI SDK. You can also make direct HTTP requests.
Replace 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, in message.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, and enable_thinking: false reason briefly, medium and high reason more, and xhigh, max, and the default reason the most.
  • glm-5.3-flash always reasons. It groups the values into three levels: none, minimal, low, and enable_thinking: false reason briefly, medium and high reason more, and xhigh, max, and the default reason the most.
  • gpt-oss-120b always reasons and ignores enable_thinking. Its usage.completion_tokens_details.reasoning_tokens is always 0. The reasoning tokens are still counted, and billed, in completion_tokens.

Tool calling

Pass your functions in tools. 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, set response_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

Set stream: 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 a 504 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(), or break out of a with block that wraps the stream.
  • Node.js SDK: break out of the for await loop, or call stream.controller.abort().
  • cURL: press Ctrl+C.

Request IDs

Every response, including errors, carries an x-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.
A request over a limit gets a 429 with the rate_limit_exceeded code and a Retry-After header. Wait that many seconds before you retry.
Contact support if your workload needs higher limits.

Errors

Errors use the OpenAI error format. Use the HTTP status to decide how to handle an error; error.code identifies the cause.
The table lists the common codes. Other codes can appear.

Retrying requests

A response with x-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 a 503 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.