SDKs
HTTP / cURL
Everything is plain JSON over HTTPS. Any language with an HTTP client can call it.
Anatomy of a request#
curl https://api.xkiro.com/v1/chat/completions \
-H "Authorization: Bearer $XKIRO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-5.6-sol",
"messages": [{ "role": "user", "content": "Hello" }]
}'- Base URL —
https://api.xkiro.com, with/v1as the first path segment. - Auth —
Authorization: Bearerorx-api-key, whichever you prefer. - Body — JSON, except
/v1/images/editswhich is multipart because it carries a file.
Streaming over raw HTTP#
Add -N so curl does not buffer, and read the data: lines as they arrive.
curl -N https://api.xkiro.com/v1/chat/completions \
-H "Authorization: Bearer $XKIRO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-5.6-sol",
"stream": true,
"messages": [{ "role": "user", "content": "Count to five." }]
}'Events can split across chunks
A network read can land in the middle of an event. Buffer the tail and only parse complete events — parsing half of one throws. There is a correct reader on Streaming.
Other languages#
Go
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
"time"
)
func main() {
body, _ := json.Marshal(map[string]any{
"model": "openai/gpt-5.6-sol",
"messages": []map[string]string{
{"role": "user", "content": "Hello"},
},
})
req, _ := http.NewRequest("POST",
"https://api.xkiro.com/v1/chat/completions", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("XKIRO_API_KEY"))
req.Header.Set("Content-Type", "application/json")
// Above the 95-second blocking limit, so a slow-but-healthy request is not
// killed by the client before the server answers.
client := &http.Client{Timeout: 120 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
var out map[string]any
json.NewDecoder(res.Body).Decode(&out)
fmt.Println(out)
}PHP
<?php
$ch = curl_init("https://api.xkiro.com/v1/chat/completions");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 120,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("XKIRO_API_KEY"),
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => json_encode([
"model" => "openai/gpt-5.6-sol",
"messages" => [["role" => "user", "content" => "Hello"]],
]),
]);
$response = json_decode(curl_exec($ch), true);
echo $response["choices"][0]["message"]["content"];Ruby
require "net/http"
require "json"
uri = URI("https://api.xkiro.com/v1/chat/completions")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.read_timeout = 120
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer #{ENV['XKIRO_API_KEY']}"
req["Content-Type"] = "application/json"
req.body = {
model: "openai/gpt-5.6-sol",
messages: [{ role: "user", content: "Hello" }]
}.to_json
puts JSON.parse(http.request(req).body).dig("choices", 0, "message", "content")Checklist for a hand-rolled client#
- Timeout above 95 seconds for blocking calls, so your client does not give up before the server does.
- Retry only 429, 500, 502 and 503, with exponential backoff and jitter. See Error codes.
- Read to the end of a stream. Usage totals arrive on the final event; stopping early records zero.
- Ignore unknown fields. New ones are added without a version bump, and a strict parser turns an additive change into an outage.
- Never log the key. Not in request dumps, not in error reports.
