Skip to Content
API referenceModels API

Models API

This page is for developers who want to read and adjust the models their organization can use, or run a model on their own cloud account, from their own code. For example, a script can list which models an agent names that can’t be used right now. In the app, this is the Models page. For the concepts, see Models, Routing and Your cloud account.

REST reference for models and for running a model on your own cloud account. Every response is wrapped in { success, data }; every route is scoped to the caller’s current organization.

Models

Models arrive from connected providers by themselves (POST /llm-providers/connect); a provider’s models are selectable once its key check passes. These routes read and adjust them.

MethodEndpointRoleDescription
GET/modelsmemberList models. Filters: status, privacyTier, providerId, selectable=true
GET/models/agents/:agentId/issuesmemberThe models an agent names that cannot be used now, and why (the banner on the agent)
POST/modelsadminAdd a model a provider serves but does not list
POST/models/syncadminRead one provider’s list again ({ providerId }), or every active one with no body
GET/models/:idmemberModel detail
PATCH/models/:idadminOverride privacy tier, region, capabilities, context length, price, status
POST/models/:id/validateadminOne real call through one model. A provider’s key check covers its models; this is for an endpoint with no provider row
DELETE/models/:idadminRemove a model

Every model in a response carries computed fields: selectable (usable right now), allowed (its connection offers it; see Which models a connection offers), effectivePricing (the override when set, else the feed price) and, on the list, isNew (its connection started listing it within the last week).

Models an agent cannot use

GET /models/agents/:agentId/issues answers, for an agent you can read, every model it names (its model, roles, steps, checkers and team) that cannot be used now:

{ "success": true, "data": [ { "model": "Qwen/Qwen3-32B", "modelName": "Qwen/Qwen3-32B", "providerId": "7c1e...", "connectionName": "HF - everything", "reason": "The provider no longer lists it.", "where": ["model", "role Checker"], "since": "2026-09-29T08:00:00.000Z" } ] }

connectionName is null when the connection is not yours to see. The list is empty once every model is usable again.

Add a model by hand

For an id the provider serves but does not list. It is checked when its provider is.

curl -X POST https://api.almyty.com/models \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Qwen3 32B on our vLLM", "providerId": "7c1e...", "vendorModelId": "qwen3-32b", "privacyTier": "private_cloud", "region": "eu-central", "capabilities": { "tools": true }, "contextLength": 32768 }'
ParameterTypeRequiredDescription
namestringYesDisplay name
vendorModelIdstringYesThe id sent on the wire
providerIduuidOne ofA connected provider
endpointRefobjectOne of{ url } of an endpoint
modelVersionIduuidNoA registered version
capabilitiesobjectNoBooleans: tools, vision, reasoning, embedding, structuredOutput
contextLengthintegerNoContext in tokens
privacyTierstringNolocal, private_cloud, public (default)
regionstringNoRegion label
pricingOverrideobjectNo{ inPerMTok, outPerMTok, currency? }, dollars per million tokens
basestringNoWhat the model is based on, for example qwen3-14b
metadataobjectNoFree-form

Your own server

Any OpenAI-compatible server (vLLM, Ollama, TGI, llama.cpp, LiteLLM) is a custom provider. Connect it with POST /llm-providers/connect, type: "custom", the server’s base URL in configuration.apiUrl and, if it checks one, its key in configuration.apiKey. What the server lists at GET <base>/models becomes its models, usable once the check passes.

Validate

For an endpoint with no provider row (a provider’s models are covered by its key check, and a model on your cloud account is checked by itself when it reaches ready):

curl -X POST https://api.almyty.com/models/4f2a.../validate \ -H "Authorization: Bearer $TOKEN"
{ "success": true, "data": { "passed": true, "latencyMs": 812, "model": { "id": "4f2a...", "validationStatus": "passed", "selectable": true, "...": "..." } } }

A failed run answers with success: false, passed: false and error, and records the error on the model.

Sync

POST /models/sync with no body returns a per-provider summary; with { providerId } the summary for that provider: created and reinstated models, retired models, skipped count, and error per provider where the vendor could not be asked. The same read happens on connect, on every key check and every six hours without anyone calling it.

Model fields

id, name, providerId, providerType, vendorModelId, endpointRef, base, modelVersionId, capabilities, contextLength, pricing, pricingSource (feed:litellm, feed:openrouter, native, adapter, manual, unpriced), pricingFetchedAt, pricingOverride, measuredLatencyMs ({ p50, p95, updatedAt }), privacyTier, region, status (active, inactive, error, deploying), validationStatus (never, passed, failed), lastValidatedAt, lastValidationError, metadata, createdAt, updatedAt, plus the computed allowed, selectable, effectivePricing and isNew.

For a model on your cloud account, endpointRef carries url, providerType and deploymentId (the id under /model-deployments below).

Routing

A routing policy travels inside an LLM Call node’s config, an autonomous agent’s modelConfig.routing, or the organization’s settings.defaultRouting; there is no routing endpoint of its own. The shape and every field are on Routing. The organization default is written with:

curl -X PATCH https://api.almyty.com/organizations/$ORG \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "settings": { "defaultRouting": { "objective": "cheapest", "privacyTier": "private_cloud" } } }'

null clears it; other settings keys are left as they are. The attribution of a routed answer (routing on the chat response, on nodeResults[nodeId], and on autonomous step output) is { modelId, modelVersionId, vendorModelId, providerId, rationale, attempt, tried, rejected }.

Your cloud account

A model on your own cloud account is created, sized and shut down through the /model-deployments routes; the clouds are listed by /model-adapters. Those are the API’s names for it: each cloud is an adapter with a providerType key, and each model running on one is a row under /model-deployments.

MethodEndpointRoleDescription
GET/model-adaptersmemberThe clouds: key, displayName, capabilities, modelSchemes, configSchema
GET/model-deploymentsmemberList models running on your clouds
POST/model-deploymentsadminStart a model on a cloud (records what you want; almyty does the rest)
GET/model-deployments/:idmemberWanted vs actual state, cost
POST/model-deployments/:id/scaleadmin{ replicas }; 0 stops it (scales to zero)
POST/model-deployments/:id/teardownadminShut it down: remove the endpoint at the cloud
DELETE/model-deployments/:idadminSame as teardown

GET /model-adapters carries modelSchemes per cloud: every source it accepts, as literal prefixes (hf://, s3://, bedrock://, …). A form filters both ways with it: the clouds that can run the source you have, or the sources the cloud you picked will take. configSchema is a JSON schema for the cloud’s providerConfig; properties marked "x-secret": true are encrypted at rest and never returned.

Start a model from a Hugging Face repository:

curl -X POST https://api.almyty.com/model-deployments \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "model": "hf://Qwen/Qwen3-0.6B", "providerType": "huggingface-endpoints", "name": "Qwen3 0.6B", "desired": { "replicas": 1, "region": "eu-west-1", "privacyTier": "private_cloud" }, "providerConfig": { "token": "hf_...", "namespace": "acme", "region": "eu-west-1", "instanceType": "nvidia-a10g" }, "budgetId": "5d3f..." }'

Or a model the cloud already hosts:

{ "model": "fireworks://accounts/acme/models/qwen3-tuned", "providerType": "fireworks" }
ParameterTypeRequiredDescription
modelstringOne ofThe model source: weights (hf://org/repo, pinned to its exact commit for you, or hf://org/repo@sha; s3://bucket/prefix@etag, gs://bucket/prefix@generation, file:///path@sha) or a model the cloud already hosts (bedrock://, sagemaker://, vertex://, foundry://, azureml://, fireworks://, together://, baseten://)
modelVersionIduuidOne ofA registered version instead of model
providerTypestringYesThe cloud’s key from GET /model-adapters
namestringNoThe model’s display name in the list
vendorModelIdstringNoThe id sent on the wire once the endpoint is up, when it differs from what the source implies
basestringNoModel family, when the cloud checks it and the source doesn’t carry one
desiredobjectNohardware, replicas, minScale, maxScale, quantization, region, privacyTier
providerConfigobjectNoThe cloud’s config, validated against its configSchema; x-secret fields encrypted
credentialIduuidNoA saved connection whose fields the cloud reads; inline secrets in providerConfig are layered over it
budgetIduuidNoSpend budget; reaching it stops the model (scales to zero)
modelIduuidNoAn existing model to attach instead of creating a new one

Exactly one of model or modelVersionId is required; naming neither is MODEL_REQUIRED. A source the cloud can’t read is refused with ADAPTER_UNSUPPORTED_SOURCE and an accepts array of the schemes it does take. An s3:// source in an organization with no bucket connection is REGISTRY_NOT_CONNECTED.

The model exists at once. Unless modelId names an existing one, POST /model-deployments creates the model in the list straight away, with status: deploying (not selectable), and links it. When the endpoint is ready the model gets endpointRef.url and endpointRef.deploymentId, turns active, takes the region the cloud reports (or the one asked for), and is priced from the cloud’s cost report (pricingSource: adapter) where the cloud reports a per-token price and no override is set. Validate it and it is selectable.

A row in a response carries state (pending, deploying, ready, degraded, scaling, tearing_down, torn_down, orphaned, failed), modelRef or modelVersionId, desired, actual (state, url, replicas, hardware, region, message, spentCents, ratePerHourCents), externalRef, lastReconcileAt, lastError, budgetId, and providerConfig with every secret shown as ********. scale and teardown change the wanted state only; the reconcile sweep (MODEL_RECONCILE_CRON, every two minutes, plus a run right after each change) is the only thing that talks to the cloud.

Cloud errors carry ADAPTER_UNKNOWN, ADAPTER_UNSUPPORTED_SOURCE (the source’s scheme is not one this cloud reads), ADAPTER_UNSUPPORTED_OPERATION (the cloud cannot do this at all), ADAPTER_UNSUPPORTED_ARCHITECTURE, ADAPTER_PREVIEW_NOT_ENABLED, ADAPTER_AUTH, ADAPTER_ERROR.

No cloud has yet been run against a real account; see Your cloud account for what each one actually accepts.

Registered versions

Optional, for power users. Nothing needs a registered version: POST /model-deployments takes the source directly and pins a Hugging Face repository for you. Register one when you want a manifest digest, lineage and evaluation history recorded against your own weights, then pass its id as modelVersionId.

MethodEndpointRoleDescription
GET/model-versionsmemberList registered versions
POST/model-versionsadminRegister a pinned URI
GET/model-versions/:idmemberVersion detail with manifest summary
DELETE/model-versions/:idadminRemove a version no running model references
curl -X POST https://api.almyty.com/model-versions \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "qwen3-14b-support-ft", "registryUri": "s3://acme-models/qwen3-14b-support@e3b0c442" }'
ParameterTypeRequiredDescription
namestringYesVersion name
registryUristringYeshf://org/repo@sha, s3://bucket/prefix@etag, gs://bucket/prefix@generation or file:///path@sha; the pin is required
basestringFor a URI without a manifestModel family
quantizationsstring[]NoFor example ["bf16", "awq-int4"]
lineageobjectNo{ trainingJobId?, datasetRef?, parentVersionId? }
metadataobjectNoFree-form

Registering an s3:// version reads and validates almyty-manifest.json at the URI and fills base, size, digest and quantizations from it; an unreadable manifest is an error. For every other scheme the manifest is optional, and base is required when it is absent. The layout under the prefix is the manifest plus plain safetensors (model.safetensors, or sharded model-00001-of-0000N.safetensors) and the tokenizer files it references:

{ "schemaVersion": 1, "base": "qwen3-14b", "tokenizer": "s3://acme-models/qwen3-14b-support@e3b0c442/tokenizer", "chatTemplate": "chatml", "license": "Apache-2.0", "created": "2026-09-08T09:00:00Z", "files": [{ "path": "model.safetensors", "sizeBytes": 29000000000, "sha256": "..." }], "quantizations": ["bf16", "awq-int4"], "lineage": { "parentVersionId": "..." } }

Required: schemaVersion (1), base, tokenizer, license, created and at least one entry in files with relative paths. The manifest’s canonical SHA-256 is recorded as manifestSha; the sum of files[].sizeBytes becomes sizeBytes.

Errors: REGISTRY_NOT_CONNECTED (no bucket connection for the organization, on an s3:// URI), VERSION_IN_USE on delete while a model that is not shut down references the version.

Audit actions

model_registered, model_validated, model_price_updated, model_routed, model_route_escalated, state transitions of models on your clouds, model_deployment_budget_stop, model_deployment_orphan_teardown.