Documentation

API reference

Authentication, models, deployments, inference, streaming, keys, errors and usage.

Base URL

https://agentmesh-riuz.onrender.com/api/v1

All 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:

CredentialGet it fromUse it for
Session token (JWT)POST /auth/register or POST /auth/loginAccount actions: models, deployments, API keys, wallet, usage.
API key (am_sk_…)POST /api-keys or the dashboardCalling 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/models

Lists 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" (or llamacpp, vllm) to choose one; otherwise they are tried in that order.
  • config accepts only num_ctx (512–8192), region and require_gpu. Anything else is rejected.
  • Retrying with the same idempotency_key returns the same deployment.
  • No node available: 503 with {"detail": {"code": "no_eligible_node", "reasons": {...}, "by_runtime": {...}}}.
  • Not enough balance: 402 with {"detail": {"code": "insufficient_balance", "required": ..., "balance": ...}}.
Method and pathPurpose
GET /deploymentsYour deployments.
GET /deployments/{id}One deployment. Poll until status is READY; it then has openai_base_url and endpoint.
GET /deployments/{id}/eventsLifecycle events (progress, moves, errors).
POST /deployments/{id}/stopStop it.
POST /deployments/{id}/restartReload 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 model field is always replaced with the deployment's model.
  • For Ollama, keep_alive is ignored and options.num_ctx is 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": ...}.

CodeMeaningWhat to do
unauthorized401: missing, wrong, expired or revoked credentials.Check the key.
deployment_not_found404: no such deployment for you, or the key is scoped to a different deployment.Check the id and the key’s scope.
deployment_not_ready409: still starting, or moving to another node.Retry with backoff.
deployment_unhealthy503: health checks failing.Retry with backoff; it moves after 3 minutes.
node_unavailable503: the node went away.Retry with backoff; failover is automatic.
rate_limited429: over 60 requests per minute per key.Honour Retry-After.
too_many_concurrent_requests429: the deployment already has 4 requests in flight.Retry shortly, or deploy another replica of the model.
timeout504: the runtime did not start responding in time.Retry; try a smaller prompt or model.
request_too_large413: body over 1 MB.Send less.
unsupported_endpoint404: route not served by this runtime.Use /v1.

Limits apply per control-plane process.

Usage and billing

Method and pathReturns
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=30Requests, successes, failures and tokens per day and per deployment (1–90 days).
GET /billing/pricingThe price list in force.
GET /billing/charges?deployment_id=…What each billing window cost.
GET /walletsYour balance.
POST /payments/topupsStart a Paystack checkout (test mode): {"amount": 5000}.
GET /stats/publicNetwork 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.