Documentation
API reference
Authentication, models, deployments, inference, streaming, keys, errors and usage.
Base URL
https://agentmesh-riuz.onrender.com/api/v1All paths below are relative to it. The full machine-readable schema is at https://agentmesh-riuz.onrender.com/api/v1/docs (OpenAPI). Requests and responses are JSON. Every response carries an X-Request-ID header; quote it when reporting a problem.
Authentication
There are two kinds of credentials:
| Credential | Get it from | Use it for |
|---|---|---|
| Session token (JWT) | POST /auth/register or POST /auth/login | Account actions: models, deployments, API keys, wallet, usage. |
API key (am_sk_…) | POST /api-keys or the dashboard | Calling deployments through the gateway (/deployments/{id}/v1/…, /ollama/…) only. The gateway also accepts a session token; that is how the dashboard's Try it works. |
Sign in and keep the token
JWT=$(curl -s -X POST https://agentmesh-riuz.onrender.com/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email": "you@example.com", "password": "your-password"}' | python3 -c 'import json,sys; print(json.load(sys.stdin)["access_token"])')Register with POST /auth/register and {"email", "password", "role"}, where role is customer or provider and the password has at least 8 characters. Both endpoints return access_token and the user. Send the token as Authorization: Bearer $JWT. GET /auth/me returns the signed-in user. Login and registration are rate limited (429 with Retry-After).
Models
curl https://agentmesh-riuz.onrender.com/api/v1/modelsLists approved models. Each has artifacts: one per runtime that can serve it, pinned to an Ollama tag or a Hugging Face commit, with estimated min_ram_mb, min_disk_mb, min_vram_mb and gpu_required. last_ready_at shows when a deployment of it last passed its readiness test. GET /models/{id} returns one model.
Deployments
Create
curl -X POST https://agentmesh-riuz.onrender.com/api/v1/deployments \
-H "Authorization: Bearer $JWT" -H "Content-Type: application/json" \
-d '{"model_id": "<model-id>", "config": {"num_ctx": 4096}, "idempotency_key": "my-retry-key"}'- Add
"runtime": "ollama"(orllamacpp,vllm) to choose one; otherwise they are tried in that order. configaccepts onlynum_ctx(512–8192),regionandrequire_gpu. Anything else is rejected.- Retrying with the same
idempotency_keyreturns the same deployment. - No node available:
503with{"detail": {"code": "no_eligible_node", "reasons": {...}, "by_runtime": {...}}}. - Not enough balance:
402with{"detail": {"code": "insufficient_balance", "required": ..., "balance": ...}}.
| Method and path | Purpose |
|---|---|
GET /deployments | Your deployments. |
GET /deployments/{id} | One deployment. Poll until status is READY; it then has openai_base_url and endpoint. |
GET /deployments/{id}/events | Lifecycle events (progress, moves, errors). |
POST /deployments/{id}/stop | Stop it. |
POST /deployments/{id}/restart | Reload it on its current node from the cached model. |
DELETE /deployments/{id} | Stop, hide, and revoke its scoped keys. Usage records are kept. |
Statuses: SCHEDULED → PROVISIONING → STARTING → READY, plus UNHEALTHY, STOPPING, STOPPED, CANCELLED and FAILED (with error_code and error_message). See the customer guide for what each means.
API keys
curl -X POST https://agentmesh-riuz.onrender.com/api/v1/api-keys -H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" -d '{"name": "my-app", "deployment_id": "<deployment-id>"}'The key is returned once. Omit deployment_id to allow all your deployments. GET /api-keys lists keys (without secrets); DELETE /api-keys/{id} revokes one.
Inference
Every deployment has openai_base_url, …/deployments/{id}/v1, which works for every runtime: /chat/completions, /completions and /models.
curl https://agentmesh-riuz.onrender.com/api/v1/deployments/<deployment-id>/v1/chat/completions \
-H "Authorization: Bearer $AGENTMESH_API_KEY" -H "Content-Type: application/json" \
-d '{"model": "any", "messages": [{"role": "user", "content": "Hello"}]}'Ollama's native API
Ollama deployments also expose endpoint, …/deployments/{id}/ollama, with /api/chat and /api/generate. Calling it on a llama.cpp or vLLM deployment returns 404. Model-management routes (api/pull, api/delete, …) are never exposed.
curl https://agentmesh-riuz.onrender.com/api/v1/deployments/<deployment-id>/ollama/api/chat -H "Authorization: Bearer $AGENTMESH_API_KEY" \
-d '{"messages": [{"role": "user", "content": "Hello"}]}'Behaviour to know
- The
modelfield is always replaced with the deployment's model. - For Ollama,
keep_aliveis ignored andoptions.num_ctxis set to the deployment's context size. - Prompts and responses pass through the provider’s machine and are not stored by AgentMesh.
Streaming
Set "stream": true for server-sent events on /v1. AgentMesh adds stream_options.include_usage unless you set it, so the final chunk carries a usage object used for metering. The Ollama native API streams NDJSON.
curl -N https://agentmesh-riuz.onrender.com/api/v1/deployments/<deployment-id>/v1/chat/completions \
-H "Authorization: Bearer $AGENTMESH_API_KEY" -H "Content-Type: application/json" \
-d '{"model": "any", "stream": true, "messages": [{"role": "user", "content": "Write a haiku"}]}'SDK examples
Any OpenAI-compatible client works. Point its base URL at your deployment.
Python: pip install openai
import os
from openai import OpenAI
client = OpenAI(
base_url="https://agentmesh-riuz.onrender.com/api/v1/deployments/<deployment-id>/v1",
api_key=os.environ["AGENTMESH_API_KEY"],
)
stream = client.chat.completions.create(
model="any",
messages=[{"role": "user", "content": "Explain DNS in one paragraph"}],
stream=True,
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)JavaScript / TypeScript: npm install openai
import OpenAI from 'openai';
const client = new OpenAI({
baseURL: 'https://agentmesh-riuz.onrender.com/api/v1/deployments/<deployment-id>/v1',
apiKey: process.env.AGENTMESH_API_KEY,
});
const reply = await client.chat.completions.create({
model: 'any',
messages: [{ role: 'user', content: 'Hello' }],
});
console.log(reply.choices[0].message.content);Errors and limits
Gateway errors use {"error": {"code": "...", "message": "..."}}. Account endpoints use FastAPI's {"detail": ...}.
| Code | Meaning | What to do |
|---|---|---|
unauthorized | 401: missing, wrong, expired or revoked credentials. | Check the key. |
deployment_not_found | 404: no such deployment for you, or the key is scoped to a different deployment. | Check the id and the key’s scope. |
deployment_not_ready | 409: still starting, or moving to another node. | Retry with backoff. |
deployment_unhealthy | 503: health checks failing. | Retry with backoff; it moves after 3 minutes. |
node_unavailable | 503: the node went away. | Retry with backoff; failover is automatic. |
rate_limited | 429: over 60 requests per minute per key. | Honour Retry-After. |
too_many_concurrent_requests | 429: the deployment already has 4 requests in flight. | Retry shortly, or deploy another replica of the model. |
timeout | 504: the runtime did not start responding in time. | Retry; try a smaller prompt or model. |
request_too_large | 413: body over 1 MB. | Send less. |
unsupported_endpoint | 404: route not served by this runtime. | Use /v1. |
Limits apply per control-plane process.
Usage and billing
| Method and path | Returns |
|---|---|
GET /usage/{deployment_id} | One record per request: endpoint, status, duration, bytes, token counts. Newest 200 by default (?limit= up to 1000). |
GET /usage/summary?days=30 | Requests, successes, failures and tokens per day and per deployment (1–90 days). |
GET /billing/pricing | The price list in force. |
GET /billing/charges?deployment_id=… | What each billing window cost. |
GET /wallets | Your balance. |
POST /payments/topups | Start a Paystack checkout (test mode): {"amount": 5000}. |
GET /stats/public | Network counts; no authentication. |
Token counts are runtime_reported: they come from the provider's machine and are not independently verified. When the runtime does not report them they are null; they are never estimated.