API reference

GET /models

List the curated model ids.

Krallo exposes a small, fixed catalogue of curated model ids. Each id is a stable public alias — the underlying provider and model version can change without breaking your integration, and Krallo never exposes the internal routing string a public id maps to. Use this endpoint to discover the valid ids, then pass one to the model field of Chat completions.

The response is deliberately OpenAI-shaped ({ "object": "list", "data": [ … ] }) so that OpenAI-compatible clients — opencode, Aider, Continue, nanocoder, or any SDK pointed at base URL https://exe.krallo.com/api/v1 — can probe it during startup and populate a model picker automatically.

Request

GET/api/v1/models

Authenticated with a bearer key. This endpoint requires a valid key only — it does not require any specific scope, unlike /chat/completions (which needs ai:invoke). It is rate-limited per key but not metered: listing models never draws down your credit balance.

See Authentication for how to send the key.

Parameters

None. The endpoint takes no path, query, or body parameters. Any query string is ignored, and a request body is not read.

HeaderRequiredDescription
AuthorizationrequiredBearer krallo_live_… — a live API key.

Example request

cURL
curl https://exe.krallo.com/api/v1/models \
  -H "Authorization: Bearer $KRALLO_API_KEY"
Node.js
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.KRALLO_API_KEY,
  baseURL: "https://exe.krallo.com/api/v1",
});

const models = await client.models.list();
for (const m of models.data) {
  console.log(m.id); // krallo-chat, krallo-code, krallo-fast, krallo-reasoning
}

The curated model ids

Four public ids are available. All are owned_by krallo. Pick by the shape of the work, not by a specific underlying model — Krallo may re-point an alias to a newer or better model at any time.

Model idBest for
krallo-code default Agentic coding — code generation, editing, and tool-driven work. This is the default model used by Chat completions when the model field is omitted or blank, and the default surfaced to opencode/Aider/Continue/nanocoder.
krallo-chat General-purpose conversation and everyday assistant turns where balanced quality and cost matter more than deep reasoning.
krallo-reasoning Hard, multi-step problems that benefit from extended, deliberate reasoning — analysis, planning, and complex logic.
krallo-fast Low-latency, low-cost turns — classification, short rewrites, extraction, and other high-volume simple tasks where speed and price win.

The ids in data are returned in alphabetical order: krallo-chat, krallo-code, krallo-fast, krallo-reasoning. Do not hard-code the ordering as a priority ranking — treat it as a set. The default model is always krallo-code regardless of list position.

Response

200 OK with an OpenAI-shaped list envelope. Each element is a minimal model object — Krallo returns only id, object, and owned_by; it does not return context windows, pricing, or created timestamps.

FieldTypeDescription
objectstringAlways "list".
dataarrayThe curated model objects, alphabetically ordered by id.
data[].idstringThe public model id you pass to model in a completion request.
data[].objectstringAlways "model".
data[].owned_bystringAlways "krallo".

Example response

{
  "object": "list",
  "data": [
    { "id": "krallo-chat",      "object": "model", "owned_by": "krallo" },
    { "id": "krallo-code",      "object": "model", "owned_by": "krallo" },
    { "id": "krallo-fast",      "object": "model", "owned_by": "krallo" },
    { "id": "krallo-reasoning", "object": "model", "owned_by": "krallo" }
  ]
}

Every authenticated response also carries advisory rate-limit headers — X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset — reflecting your per-key budget.

Passing a model to chat completions

The id values from this list are exactly what Chat completions accepts in its model field:

{
  "model": "krallo-reasoning",
  "messages": [
    { "role": "user", "content": "Prove that the sum of two even integers is even." }
  ]
}

Errors

The catalogue is fixed, so this endpoint has no request-validation errors of its own beyond the wrong HTTP method — the remaining failures come from the shared auth and rate-limit gates.

StatusCodeWhen
404not_foundThe developer API is disabled for this deployment (the master switch is off). Every /api/v1 route 404s while dark.
401unauthorizedNo Authorization: Bearer credential was sent.
401invalid_tokenThe bearer token does not match any known key.
401token_revokedThe key has been revoked.
401token_expiredThe key has passed its expiry time.
403app_disabledThe owning app is inactive or missing.
403owner_suspendedThe owner account (or a linked identity) is suspended.
405method_not_allowedAny method other than GET (or the CORS preflight OPTIONS, which returns 204).
429—The per-key rate limit (or the coarse per-IP auth-flood throttle) was exceeded. See Rate limits.

This endpoint mixes error shapes. Its own 405 method_not_allowed is emitted in the OpenAI-shaped form ({ "error": { "message", "type" } }) so OpenAI SDKs parse it. The auth failures above use the standard developer-API envelope ({ "error": { "code", "message" }, "meta": { "request_id" } }), while the 429 is a flat { "error": "rate_limited", … } body with a Retry-After header. See Errors for the formats and guidance on handling them.