API Reference
Models & catalogue
Pendra exposes two model surfaces: a live models endpoint
that lists what's actually serving right now across connected workers,
and a catalogue endpoint that lists everything Pendra can
install for you via the curated-install flow. Model weights are hosted on
Pendra's own CDN (get.pendra.ai) and checksum-verified at
install time.
Live models
GET /api/v1/models returns the OpenAI-shaped models list:
curl https://api.pendra.ai/api/v1/models \
-H "Authorization: Bearer pdr_sk_..."
Response
Standard OpenAI list envelope. Each entry is what's actually
serving on a connected worker right now — restart a worker and the list
updates within seconds.
{
"object": "list",
"data": [
{
"id": "llama3.3:70b",
"object": "model",
"created": 1733519426,
"owned_by": "pendra",
"type": "chat",
"capabilities": ["completion", "tools"],
"parameter_size": "70B"
},
{
"id": "qwen3.6:27b",
"object": "model",
"created": 1776313891,
"owned_by": "pendra",
"type": "chat",
"capabilities": ["completion", "tools", "thinking"],
"parameter_size": "27B",
"reasoning": "hybrid"
},
{
"id": "nomic-embed-text",
"object": "model",
"created": 1707947709,
"owned_by": "pendra",
"type": "embedding",
"capabilities": ["embedding"]
}
]
}
created is the model's release date, in Unix epoch seconds.
It's 0 for the occasional model we don't have a date for.
What's in a live-model entry
Beyond the standard OpenAI id / object /
created / owned_by, each entry carries a few
Pendra fields so you can pick the right model without a second call:
type— the single capability this model serves:chat,image,embedding,rerank,ocr,transcription, orspeech. This is the same value you filter on with?type=below.capabilities— everything the model can do, as an array:completion,vision,tools,thinking,embedding,rerank,ocr,transcription,image,speech. Check for one withincludes()rather than comparing the whole array.disabled_capabilities— any of the above that the worker has turned off for this model (e.g.["vision"]). Absent when nothing is disabled.parameter_size— the model's size as a human string (e.g."70B"). Absent when it isn't known.reasoning—reasoning(always thinks before answering) orhybrid(thinking you can toggle per request). Absent on non-reasoning models.recommended_sizeandrecommended_steps— on image models, the default resolution (e.g."1024x1024") and step count to start from. See image generation.voicesanddefault_voice— on speech models, the preset voices you can pass asvoice, and the one used when you omit it. See text to speech.
A speech model's entry, for example, looks like this — the
voices and default_voice are exactly what the
text-to-speech guide points
you here to read:
{
"id": "your-speech-model",
"object": "model",
"created": 1748736000,
"owned_by": "pendra",
"type": "speech",
"capabilities": ["speech"],
"voices": ["ryan", "vivian", "aria"],
"default_voice": "ryan"
}
Filter by type
Pass ?type= to narrow the list to a single capability:
chat, image, embedding,
rerank, ocr, transcription, or
speech.
curl "https://api.pendra.ai/api/v1/models?type=embedding" \
-H "Authorization: Bearer pdr_sk_..."
Codex compatibility
OpenAI Codex sends a client_version query parameter and
expects a different envelope ({"models": [...]} instead
of the standard OpenAI list). Pendra detects Codex and returns the right
shape automatically — no configuration needed.
The model catalogue
GET /api/v1/catalogue lists the models Pendra can install on
your worker via one click in the console. You can call it without a key to
see the public catalogue; if you send your API key, the response also
includes any models Pendra has made available specifically to your
organisation. Catalogue installs download a verified GGUF onto the worker.
Every entry is vetted by Pendra before it appears in the catalogue.
curl https://api.pendra.ai/api/v1/catalogue
Catalogue response
Returns a flat list of catalogue entries. Each entry describes a canonical Pendra model plus its variants (sizes and quantisations), and each variant carries the verified GGUF that Pendra installs.
{
"data": [
{
"id": "gemma4",
"name": "Gemma 4",
"publisher": "Google DeepMind",
"description": "...",
"capabilities": ["completion", "vision", "thinking", "tools"],
"context_length": 262144,
"homepage": "https://...",
"licence": "apache-2.0",
"reasoning": "reasoning",
"publishing_country": "us,gb",
"release_quarter": "Q2 2026",
"variants": [
{
"id": "gemma4:12b",
"label": "12B",
"parameter_size": "12B",
"architecture": "dense",
"architectures": ["dense"],
"quantization": "Q4_K_M",
"context_length": 262144,
"disk_size": 7300000000,
"estimated_vram_bytes": 9500000000,
"kv_bytes_per_token": 147456,
"bits_per_weight": 4.83,
"gguf_url": "https://get.pendra.ai/models/...",
"gguf_sha256": "...",
"gguf_size_bytes": 7300000000,
"task": "chat",
"installable_via": ["dashboard", "cli"]
},
{
"id": "gemma4:26b",
"label": "26B",
"parameter_size": "26B",
"architecture": "moe",
"architectures": ["moe"],
"active_parameters": "4B",
"quantization": "Q4_K_M",
"context_length": 262144,
"disk_size": 16000000000,
"estimated_vram_bytes": 18400000000,
"kv_bytes_per_token": 98304,
"bits_per_weight": 4.80,
"gguf_url": "https://get.pendra.ai/models/...",
"gguf_sha256": "...",
"gguf_size_bytes": 16000000000,
"task": "chat",
"installable_via": ["dashboard", "cli"]
}
]
},
{
"id": "nomic-embed-text",
"name": "nomic-embed-text-v1.5",
"publisher": "Nomic",
"description": "...",
"capabilities": ["embedding"],
"context_length": 2048,
"homepage": "https://...",
"licence": "apache-2.0",
"variants": [
{
"id": "nomic-embed-text:nomic-embed-text-v1.5",
"label": "v1.5",
"quantization": "Q4_K_M",
"disk_size": 84106624,
"gguf_url": "https://get.pendra.ai/models/...",
"gguf_sha256": "...",
"gguf_size_bytes": 84106624,
"task": "embedding",
"installable_via": ["dashboard", "cli"]
}
]
}
]
}
What's in a catalogue entry
id— canonical Pendra ID (e.g.qwen3.5).capabilities— an array describing what the model can do:completion,vision,tools,thinking,embedding,rerank,ocr,image.variants— sizes and quantisations, each carrying the GGUF install metadata:gguf_url+gguf_sha256(the model weights, served from Pendra's CDN atget.pendra.aiand checksum-verified at install time),gguf_size_bytes,disk_size(total on-disk footprint in bytes, including the vision projector and every shard where applicable), andinstallable_via(e.g.["dashboard", "cli"]).gguf_parts— present instead ofgguf_urlon very large models whose weights ship as several files (sharded GGUF, e.g. a 235B MoE or a frontier model). It's an ordered list of{ url, sha256, size_bytes }parts, each served fromget.pendra.aiand checksum-verified; Pendra downloads and verifies every part, then loads the model from the first one. You don't need to handle this differently — installing the variant works the same way.architectures— on each chat variant, the list of architecture properties that size has:dense,moe(Mixture-of-Experts),hybrid(a state-space/attention mix), ordiffusion. It's a list because a size can be more than one at once — a Mixture-of-Experts model built on a hybrid state-space stack is both, and comes back as["hybrid", "moe"]. Check for a value withincludes()rather than comparing the whole list. MoE sizes also carryactive_parameters(the per-token count, e.g."3B"for a 35B model — see the architecture guide). Embedding, transcription, and image models omit both.architecture— the single value that best describes the same size, for code that wants one string to show. It's always one of the entries inarchitectures, so it stays safe to display — but don't test it for a specific value: a size that is both hybrid and MoE reads"hybrid"here, and a check likearchitecture === "moe"would miss it. Usearchitecturesfor that.estimated_vram_bytes— roughly how much GPU memory this variant needs to run entirely on the GPU: the weights plus the cache Pendra holds back for your conversation context. Compare it against a card's memory to tell, before you install anything, whether a size will fit — a 24 GB card is24 * 1024 ** 3= 25,769,803,776 bytes, and you want comfortable headroom rather than a bare fit. It's an estimate, not a promise: it's calculated from the model's own file header using the same arithmetic the worker uses when it loads the model, so the two agree, but real usage moves with your context length and batch size. Absent on a few older catalogue entries, wheredisk_sizeis the best rough proxy.kv_bytes_per_token— how much cache memory one token of context costs, so you can work out what a longer context adds: 32,768 tokens on a variant reporting 147,456 bytes/token is about 4.8 GB on top of the weights.0is a real answer and not an error — some models use a sliding-window attention scheme whose cache doesn't grow per token in this way, and Pendra budgets a flat allowance for them instead. Preferestimated_vram_bytesfor the "will it fit" question; this field is for reasoning about the context you plan to use.bits_per_weight— the average number of bits each parameter is stored in, which is how aggressively the variant is quantised. Higher is closer to the original model. Around 8 is near-lossless, 5–6 is a common quality choice, and 4 and below trades noticeable accuracy for a much smaller download. Useful for choosing between two quantisations of the same size: the one with more bits per weight is the more faithful of the two. Absent when the model's parameter count isn't known — Pendra reports it only when it's measured, never estimated from the quantisation name.reasoning— at the model level:reasoning(thinks before answering) orhybrid(thinking you can toggle on or off per request). Absent on non-reasoning models.publishing_country— the publisher's country as one or two comma-separated ISO 3166-1 alpha-2 codes (e.g."cn", or"us,gb"for a model published by an organisation spanning two countries). Absent when unknown.release_quarter— when the model was publicly released, to the quarter (e.g."Q2 2026"). Absent when unknown.- parameter size, context length, licence.
Curated installs
Every catalogued variant installs onto the worker — one click in the
console, or pendra models install <id> from the CLI. The
installable_via field on each variant tells you where it can
be installed from (dashboard, cli, or both).
Naming conventions
Chat models use the name:tag convention (e.g.
qwen3.5:0.8b, llama3.3:70b). Embedding models use a
slug-style id (e.g. nomic-embed-text:nomic-embed-text-v1.5).
The full set of names lives in the catalogue endpoint above.