Quickstart
Zero to a first response in five steps.
Everything below happens once. After this, every call you make is the same request shape you'd send to OpenAI, aimed at a different base URL.
1. Create an account
Sign up with an email and password. We send a verification link — you can't sign in or create a key until you click it, so use an address you can check right now. Signing up creates an organisation and a default project for you automatically; you don't have to think about either one to make your first call.
2. Create an API key
Once you're signed in, go to API keys and create one. The key is shown exactly once, at creation — copy it somewhere before you close the dialog, because the server never stores it in a form it can show you again. Set it as an environment variable rather than pasting it into code:
export LARSA_API_KEY="sk-larsa-..."Every key starts with sk-larsa-, so a copy of one sitting in a repository is easy to catch in a secret scan. Authentication covers scoping a key to a project and specific models, and what to do if one leaks.
3. Install a client
Python and JavaScript/TypeScript have an official OpenAI client; point its base_url at ours and it works unmodified. Every other language below talks plain HTTP — there is nothing to install beyond what the sample imports.
pip install openainpm install openai4. Make the call
larsa-general is the general-purpose model — a reasonable default while you're finding your way around. Each sample below prints the answer on success and a short message on failure.
curl https://api.console.larsa.larsima.com/v1/chat/completions \
-H "Authorization: Bearer $LARSA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "larsa-general",
"messages": [
{"role": "user", "content": "In one sentence, what is the Larsa API?"}
]
}'import os
from openai import OpenAI, APIStatusError
client = OpenAI(
api_key=os.environ["LARSA_API_KEY"],
base_url="https://api.console.larsa.larsima.com/v1",
)
try:
response = client.chat.completions.create(
model="larsa-general",
messages=[
{"role": "user", "content": "In one sentence, what is the Larsa API?"}
],
)
print(response.choices[0].message.content)
except APIStatusError as e:
print(f"request failed ({e.status_code}): {e.message}")
import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.LARSA_API_KEY,
baseURL: "https://api.console.larsa.larsima.com/v1",
});
try {
const response = await client.chat.completions.create({
model: "larsa-general",
messages: [
{ role: "user", content: "In one sentence, what is the Larsa API?" },
],
});
console.log(response.choices[0].message.content);
} catch (err) {
console.error(`request failed (${err.status}): ${err.message}`);
}
import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.LARSA_API_KEY,
baseURL: "https://api.console.larsa.larsima.com/v1",
});
async function main(): Promise<void> {
try {
const response = await client.chat.completions.create({
model: "larsa-general",
messages: [
{ role: "user", content: "In one sentence, what is the Larsa API?" },
],
});
console.log(response.choices[0].message.content);
} catch (err) {
if (err instanceof OpenAI.APIError) {
console.error(`request failed (${err.status}): ${err.message}`);
} else {
throw err;
}
}
}
main();
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
)
type message struct {
Role string `json:"role"`
Content string `json:"content"`
}
type chatRequest struct {
Model string `json:"model"`
Messages []message `json:"messages"`
}
type chatResponse struct {
Choices []struct {
Message message `json:"message"`
} `json:"choices"`
Error *struct {
Message string `json:"message"`
} `json:"error"`
}
func main() {
reqBody, _ := json.Marshal(chatRequest{
Model: "larsa-general",
Messages: []message{
{Role: "user", Content: "In one sentence, what is the Larsa API?"},
},
})
req, err := http.NewRequest("POST",
"https://api.console.larsa.larsima.com/v1/chat/completions",
bytes.NewReader(reqBody))
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("LARSA_API_KEY"))
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
var out chatResponse
if err := json.Unmarshal(body, &out); err != nil {
panic(err)
}
if res.StatusCode != http.StatusOK {
msg := string(body)
if out.Error != nil {
msg = out.Error.Message
}
fmt.Printf("request failed (%d): %s\n", res.StatusCode, msg)
return
}
fmt.Println(out.Choices[0].Message.Content)
}
// Cargo.toml:
// [dependencies]
// reqwest = { version = "0.12", features = ["json", "blocking"] }
// serde_json = "1"
use std::env;
use serde_json::json;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let api_key = env::var("LARSA_API_KEY")?;
let body = json!({
"model": "larsa-general",
"messages": [
{"role": "user", "content": "In one sentence, what is the Larsa API?"}
]
});
let client = reqwest::blocking::Client::new();
let res = client
.post("https://api.console.larsa.larsima.com/v1/chat/completions")
.bearer_auth(api_key)
.json(&body)
.send()?;
let status = res.status();
let data: serde_json::Value = res.json()?;
if !status.is_success() {
let message = data["error"]["message"].as_str().unwrap_or("unknown error");
eprintln!("request failed ({status}): {message}");
return Ok(());
}
println!("{}", data["choices"][0]["message"]["content"].as_str().unwrap_or(""));
Ok(())
}
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class QuickstartExample {
public static void main(String[] args) throws Exception {
String apiKey = System.getenv("LARSA_API_KEY");
String body = "{"
+ "\"model\": \"larsa-general\","
+ "\"messages\": [{\"role\": \"user\", "
+ "\"content\": \"In one sentence, what is the Larsa API?\"}]"
+ "}";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.console.larsa.larsima.com/v1/chat/completions"))
.header("Authorization", "Bearer " + apiKey)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> response =
client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() != 200) {
System.err.println("request failed (" + response.statusCode()
+ "): " + response.body());
return;
}
// A minimal HTTP example prints the raw JSON body; parse it with
// whatever JSON library your project already uses.
System.out.println(response.body());
}
}
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
var apiKey = Environment.GetEnvironmentVariable("LARSA_API_KEY");
var payload = new
{
model = "larsa-general",
messages = new[]
{
new { role = "user", content = "In one sentence, what is the Larsa API?" }
}
};
using var client = new HttpClient { BaseAddress = new Uri("https://api.console.larsa.larsima.com/v1/") };
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);
var body = new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");
var response = await client.PostAsync("chat/completions", body);
var json = await response.Content.ReadAsStringAsync();
using var doc = JsonDocument.Parse(json);
if (!response.IsSuccessStatusCode)
{
var message = doc.RootElement.GetProperty("error").GetProperty("message").GetString();
Console.Error.WriteLine($"request failed ({(int)response.StatusCode}): {message}");
return;
}
var content = doc.RootElement
.GetProperty("choices")[0]
.GetProperty("message")
.GetProperty("content")
.GetString();
Console.WriteLine(content);
<?php
$apiKey = getenv('LARSA_API_KEY');
$payload = json_encode([
'model' => 'larsa-general',
'messages' => [
['role' => 'user', 'content' => 'In one sentence, what is the Larsa API?'],
],
]);
$ch = curl_init('https://api.console.larsa.larsima.com/v1/chat/completions');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$data = json_decode($response, true);
if ($status !== 200) {
fwrite(STDERR, "request failed ($status): {$data['error']['message']}\n");
exit(1);
}
echo $data['choices'][0]['message']['content'], PHP_EOL;
require "net/http"
require "json"
require "uri"
api_key = ENV.fetch("LARSA_API_KEY")
uri = URI("https://api.console.larsa.larsima.com/v1/chat/completions")
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer #{api_key}"
request["Content-Type"] = "application/json"
request.body = {
model: "larsa-general",
messages: [
{ role: "user", content: "In one sentence, what is the Larsa API?" },
],
}.to_json
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(request)
end
data = JSON.parse(response.body)
if response.code != "200"
warn "request failed (#{response.code}): #{data['error']['message']}"
exit 1
end
puts data["choices"][0]["message"]["content"]
reasoning_effort, so the model decides how much to think before answering out loud. If a run ever comes back empty, see `reasoning_effort` in the chat reference — setting it to "none" is the one value guaranteed to produce a visible answer.5. Read the response
A successful call returns a chat.completion object. The text you want is choices[0].message.content; usage is the exact token count the request billed.
{
"id": "chatcmpl-9f2a1c3e7b1a4e0daf3b6c2e1f9a7d55",
"object": "chat.completion",
"created": 1755878402,
"model": "larsa-general",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "The Larsa API is an OpenAI-compatible gateway that serves chat, vision, speech, translation and legal retrieval from dedicated GPU hardware."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 21,
"completion_tokens": 28,
"total_tokens": 49
}
}6. Handle the error
A failed call is still valid JSON — the top-level shape changes to a single error object instead of choices. This is the exact body the gateway returns for a request with no key at all:
{
"error": {
"message": "Authentication Error, No api key passed in.",
"type": "auth_error",
"param": "None",
"code": "401"
}
}Every sample above checks for this before touching choices. Errors lists every status code and what each one means.