Skip to Content
API referenceProviders API

Providers API

This page is for developers who want to connect AI model providers from their own code. A provider is a company whose AI models you use (for example OpenAI, Anthropic or Mistral), connected once with your own key. For example, a setup script for a new organization can connect its provider keys in one call. In the app, this is Models → Connect a provider; see Connect a provider.

Models page, with connected providers and their models

REST API reference for connecting and managing providers.

Endpoints

MethodEndpointDescription
POST/llm-providers/connectConnect a provider: save it, check the key, list its models, in one request (admin/owner)
GET/llm-providersList all providers
POST/llm-providersAdd a provider without waiting for its check (admin/owner)
GET/llm-providers/provider-typesEvery vendor the platform can call, with display name, features, key/docs links and listsModels
POST/llm-providers/test-connectionProbe a {type, apiKey} pair before saving it
POST/llm-providers/models/by-typeList a vendor’s models from a {type, apiKey} pair, before saving
GET/llm-providers/:idGet provider by ID
PATCH/llm-providers/:idUpdate a provider (admin/owner)
DELETE/llm-providers/:idDelete a provider (admin/owner); the owners of agents that used its models are told they are no longer available
GET/llm-providers/:id/agentsThe agents whose model runs on this connection: { agents: [{ id, name }], others }, named when the caller can see them and counted in others otherwise
GET/llm-providers/:id/usageRequest, token, and cost totals for one provider
GET/llm-providers/:id/modelsModels this saved provider currently lists
POST/llm-providers/:id/testCheck the key again
POST/llm-providers/:id/chatSend a chat message

Connect a provider

One request that saves the provider, checks its key with one real call, and lists its models. On success every model it lists is usable. On failure nothing is saved.

curl -X POST https://api.almyty.com/llm-providers/connect \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "type": "openai", "configuration": { "apiKey": "sk-..." } }'
ParameterTypeRequiredDescription
typestringYesThe provider type, as GET /llm-providers/provider-types lists it
namestringNoThe connection’s name, shown in every model chooser. Defaults to the provider’s own name; several connections of one provider can each have their own
configurationobjectNoThe key and the few fields the type needs, as for Add a Provider: apiKey, apiUrl (your own server, Ollama), bedrock.region, azure.resourceName and azure.deploymentName, vertex.projectId, runpod.endpointId, and model for a type whose listsModels is false
credentialIduuidNoUse a saved connection instead of pasting a key
visibilitystringNoorg (default), team or private
teamIduuidNoWith visibility: team
allowNewModels, hiddenModels, allowedModelsNoWhich models the connection offers; see Which models a connection offers. Every model, new ones included, when left out
{ "success": true, "data": { "provider": { "id": "7c1e...", "name": "OpenAI", "type": "openai", "isHealthy": true, "...": "..." }, "models": [{ "id": "4f2a...", "vendorModelId": "gpt-5", "selectable": true, "effectivePricing": { "inPerMTok": 1.25, "outPerMTok": 10 }, "...": "..." }], "check": { "ok": true, "responseTime": 412 } } }

A failure answers 400 with one plain sentence in message, the vendor’s own words in detail and the vendor’s key page in keyUrl:

errorWhen
KEY_REJECTEDThe vendor refused the key: "OpenAI rejected this key."
CHECK_FAILEDThe check did not pass for another reason (unreachable, timeout, a model the key cannot use): "Could not connect to OpenAI."
MODEL_REQUIREDThe type serves no model list and no configuration.model was given
INVALID_CONFIGURATIONA required field is missing or the URL is not allowed

The vendor’s own 401 never reaches you as a 401, so a client does not mistake it for its own session ending.

Which models a connection offers

Every model a connection’s key reaches is offered by default. Three fields, on connect, create and PATCH /llm-providers/:id, narrow that:

FieldTypeDescription
allowNewModelsbooleantrue (default): every model is offered except hiddenModels, and a model the provider lists later is offered at once. false: only allowedModels, and a model listed later waits until it is added
hiddenModelsstring[] | nullVendor model ids not offered while allowNewModels is true
allowedModelsstring[] | nullVendor model ids offered while allowNewModels is false. May be empty: the connection is then paused and offers nothing

Both lists are kept whichever way the switch is set, so flipping it back loses nothing. Pin a key to one model:

curl -X PATCH https://api.almyty.com/llm-providers/7c1e... \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "allowNewModels": false, "allowedModels": ["meta-llama/Llama-3.3-70B-Instruct"] }'

A model the connection does not offer reads allowed: false and selectable: false on GET /models, the router never plans it, and a chat call that names it through this connection answers 400 with MODEL_NOT_ALLOWED before anything reaches the provider. A call that names no model uses the connection’s default model when it is offered, else the best offered one. Changing these fields spends no key check. A change that would take away a model an agent uses is refused with 409 and MODEL_IN_USE; the body names the models, the agents the caller can see ({ id, name }) and a count of otherAgents, and nothing is saved. A rename changes the name of the key the connection made for itself too.

Add a provider

type picks the vendor, and everything else about the connection (the key, the base URL, the default call parameters) lives under configuration.

curl -X POST https://api.almyty.com/llm-providers \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "OpenAI Production", "type": "openai", "configuration": { "apiKey": "sk-...", "model": "gpt-4o", "temperature": 0.7, "maxTokens": 4096 } }'

Parameters

ParameterTypeRequiredDescription
namestringYesDisplay name, max 100 characters
typestringYesVendor key. One of the values GET /llm-providers/provider-types returns: openai, anthropic, google, mistral, ollama, azure_openai, aws_bedrock, custom, and the rest. An unknown value is rejected.
configurationobjectYesConnection and default call settings; see below
descriptionstringNoMax 1000 characters
credentialIduuidNoPoint at an existing connection instead of pasting configuration.apiKey. null clears the reference
usageCredentialIduuidNoConnection holding the admin key for the vendor’s usage/cost API
capabilitiesobjectNo{supportedModels, maxTokens, supportsFunctionCalling, supportsStreaming, supportsBatching, supportsVision, supportsAudio, supportsToolUse, supportedToolFormats}
metadataobjectNo{version, region, endpoint, modelInfo}
visibilityorg | team | privateNoWho in the organization sees the provider
teamIdstringNoThe owning team when visibility is team
allowNewModels, hiddenModels, allowedModelsNoWhich models it offers; see above

Creating, updating, and deleting a provider require the admin or owner role. Reading, testing, and chatting are open to member as well.

configuration

Every field is optional; what a given vendor needs depends on its type.

FieldTypeDescription
apiKeystringThe pasted key. It becomes a Credential row rather than a column on the provider, and reads back masked
usageApiKeystringAdmin or org-scoped key for the vendor’s usage/cost API, where the vendor publishes one
apiUrlstringBase URL override: self-hosted servers, regional endpoints, and OpenAI-compatible hosts
apiVersionstringVendor API version, where the vendor pins one
modelstringDefault model for calls that do not name one
maxTokens, temperature, topP, topK, frequencyPenalty, presencePenaltynumberDefault call parameters
timeout, retriesnumberPer-call timeout in milliseconds, and retry count
rateLimitsobject{requestsPerMinute, requestsPerHour, tokensPerMinute, tokensPerHour}
azureobject{deploymentName, resourceName, apiVersion}
bedrockobject{region, accessKeyId, secretAccessKey, sessionToken}
huggingfaceobject{endpoint, taskType}
customobject{headers, authMethod, requestFormat} for an OpenAI-compatible host that needs shaping

Response

The provider comes back with its secrets stripped: configuration is reduced to the non-secret call settings, and the key is referenced rather than returned.

{ "success": true, "data": { "id": "prov-uuid", "name": "OpenAI Production", "type": "openai", "status": "active", "configuration": { "model": "gpt-4o", "maxTokens": 4096, "temperature": 0.7, "apiUrl": null }, "totalRequests": 0, "totalCost": 0, "createdAt": "2026-03-01T10:00:00Z" }, "message": "Provider added" }

status is one of active, inactive, error, or maintenance.

Test connection

Verify a saved provider is configured correctly. The platform makes one short real call, using the provider’s configured model or, when it has none, whatever the vendor currently serves:

curl -X POST https://api.almyty.com/llm-providers/{id}/test \ -H "Authorization: Bearer $TOKEN"
{ "success": true, "data": { "isHealthy": true, "responseTime": 450 }, "message": "Connection test completed" }

A failed probe returns isHealthy: false with an error string rather than an HTTP error.

To check a key before saving anything, post the pair to /llm-providers/test-connection:

curl -X POST https://api.almyty.com/llm-providers/test-connection \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "type": "openai", "apiKey": "sk-..." }'

That returns {ok, latencyMs, modelCount}. Ollama is keyless, so apiKey may be omitted for it.

Send a chat message

The body is a message list, not a single string:

curl -X POST https://api.almyty.com/llm-providers/{id}/chat \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "messages": [ { "role": "user", "content": "Hello, what can you do?" } ], "sessionId": "optional-session-uuid" }'

messages is required. model overrides the provider default; maxTokens (1–200000), temperature (0–2), topP (0–1), topK (0–100), frequencyPenalty and presencePenalty (−2–2), stopSequences, tools, toolIds, and stream are all optional. Pass routing instead of model to let the model catalog pick, in which case the response carries a routing attribution saying which card answered.

Sessions maintain conversation history. Omit sessionId for one-off messages.

Supported providers

Which vendors almyty can call is registry data, not a list frozen in these docs, and which models are usable is a property of your organization’s catalog rather than of the platform. Three endpoints answer it live:

QuestionCall
Which vendor types exist?GET /llm-providers/provider-types
What does this saved provider currently serve?GET /llm-providers/:id/models
What would this key serve, before I save it?POST /llm-providers/models/by-type with {type, apiKey}

A model is usable once it is active, points at a callable provider, and that provider’s key check has passed; the check covers every model the provider lists. GET /models lists them with that state and POST /models/sync reads a provider’s list again. See the Models guide for the whole flow.

custom is the escape hatch: any OpenAI-compatible API, pointed at with configuration.apiUrl and shaped with configuration.custom.