Matricxon API
Matricxon serves an HTTP API on port 8420, with JSON requests and streamed replies. The examples below use curl against a local server:
export MATRICXON_URL=http://localhost:8420Chat and generation
Section titled “Chat and generation”| Endpoint | Notes |
|---|---|
POST /api/chat |
Streaming NDJSON chat, with tools and images. A request_id lets you cancel just this reply |
POST /api/generate |
Raw-prompt completion, no chat template |
POST /api/embeddings, POST /api/embed |
Mean-pooled, L2-normalized vectors (single and list input) |
POST /api/rerank |
Scores documents against a query with a reranker model |
curl -N $MATRICXON_URL/api/chat \ -H 'Content-Type: application/json' \ -d '{ "model": "hf.co/unsloth/Llama-3.2-3B-Instruct-GGUF:Llama-3.2-3B-Instruct-Q3_K_M", "messages": [ {"role": "system", "content": "Answer in one sentence."}, {"role": "user", "content": "What is a GGUF file?"} ], "options": {"temperature": 0.7, "num_ctx": 4096} }'The reply streams as one JSON object per line. The last line has "done": true and the timings, in nanoseconds:
{"message":{"content":"A GGUF"},"done":false}{"message":{"content":" file is"},"done":false}...{"message":{"content":""},"done":true,"prompt_eval_count":31,"eval_count":24,"total_duration":5120000000}-Nturns off curl’s buffering, so the words appear as they arrive.- Replies always stream.
"stream": falseis accepted but not supported yet. options:temperature(0.8),top_p(0.9),top_k(40),repeat_penalty(1.1),num_ctx(2048),num_predict(-1, no limit) andseed. Defaults in brackets.- A model the server hasn’t loaded yet loads on the first call, which can take a while on a CPU.
Keep a model loaded, or unload it
Section titled “Keep a model loaded, or unload it”keep_alive is a whole number of seconds (Ollama’s "5m" form is not accepted). It applies to this model from this call on. Without it, the server’s default applies.
# Load the model and keep it for 24 hours, without generating anythingcurl $MATRICXON_URL/api/generate -H 'Content-Type: application/json' \ -d '{"model": "hf.co/unsloth/Llama-3.2-3B-Instruct-GGUF:Llama-3.2-3B-Instruct-Q3_K_M", "keep_alive": 86400}'
# Unload it now: no messages and keep_alive 0curl $MATRICXON_URL/api/chat -H 'Content-Type: application/json' \ -d '{"model": "hf.co/unsloth/Llama-3.2-3B-Instruct-GGUF:Llama-3.2-3B-Instruct-Q3_K_M", "messages": [], "keep_alive": 0}'Stop one reply
Section titled “Stop one reply”Give a reply your own request_id. The same empty call with that id stops only that reply: the model stays loaded and other users’ replies go on.
Send "model_role": "vision" when the model is used only to read an image (pAIring’s default vision model). It then doesn’t count toward MATRICXON_MAX_LOADED_MODELS, like embedding and reranker models, so it never unloads a chat model.
curl -N $MATRICXON_URL/api/chat -H 'Content-Type: application/json' \ -d '{"model": "hf.co/unsloth/Llama-3.2-3B-Instruct-GGUF:Llama-3.2-3B-Instruct-Q3_K_M", "messages": [{"role": "user", "content": "Write a long story."}], "request_id": "reply-42"}'
# From another terminalcurl $MATRICXON_URL/api/chat -H 'Content-Type: application/json' \ -d '{"model": "hf.co/unsloth/Llama-3.2-3B-Instruct-GGUF:Llama-3.2-3B-Instruct-Q3_K_M", "messages": [], "keep_alive": 0, "request_id": "reply-42"}'Generate
Section titled “Generate”Sends the prompt as written, without the model’s chat template:
curl -N $MATRICXON_URL/api/generate -H 'Content-Type: application/json' \ -d '{"model": "hf.co/unsloth/Llama-3.2-3B-Instruct-GGUF:Llama-3.2-3B-Instruct-Q3_K_M", "prompt": "The three primary colors are", "options": {"num_predict": 20}}'Each line carries a response piece instead of message.
Embeddings
Section titled “Embeddings”curl $MATRICXON_URL/api/embed -H 'Content-Type: application/json' \ -d '{"model": "hf.co/leliuga/all-MiniLM-L6-v2-GGUF:Q8_0", "input": ["first text", "second text"]}'{"embeddings": [[-0.0184, 0.0551, 0.0097, ...], [...]]}/api/embed takes one text or a list and returns embeddings. The older /api/embeddings takes one prompt and returns one embedding.
Rerank
Section titled “Rerank”Orders documents by how well they answer a query, for example the results of a knowledge-base search:
curl $MATRICXON_URL/api/rerank -H 'Content-Type: application/json' \ -d '{"model": "hf.co/ggml-org/Qwen3-Reranker-0.6B-Q8_0-GGUF:Q8_0", "query": "How do I run a model on a CPU?", "documents": ["Matricxon runs GGUF models on an ordinary CPU.", "Bananas are rich in potassium."], "top_n": 2}'{"model":"hf.co/ggml-org/Qwen3-Reranker-0.6B-Q8_0-GGUF:Q8_0", "results":[{"index":0,"relevance_score":0.9976,"document":null}, {"index":1,"relevance_score":0.00004,"document":null}]}index points into your documents list. Add "return_documents": true to get each text back. Up to 1000 documents per call.
Models
Section titled “Models”| Endpoint | Notes |
|---|---|
POST /api/pull |
Downloads hf.co/<repo>:<file> from Hugging Face with progress and a sha256 check. Admin |
GET /api/tags, POST /api/show, GET /api/ps |
Installed models with their capabilities, model details, loaded models with expiry |
DELETE /api/delete, POST /api/copy, POST /api/create |
Remove, duplicate, re-tag (create supports only FROM <tag>). Admin |
POST /api/infer-capabilities |
Matricxon-only: what a file would be able to do, before it is downloaded |
POST /api/push |
Always refused. Matricxon has no registry to push to |
Pulling resolves only hf.co/<repo>:<file> tags.
# What is installed, and what each model can docurl $MATRICXON_URL/api/tags
# One model's details, with the RAM it needscurl $MATRICXON_URL/api/show -H 'Content-Type: application/json' \ -d '{"model": "hf.co/leliuga/all-MiniLM-L6-v2-GGUF:Q8_0"}'{"capabilities":["embedding"],"details":{"family":"bert","parameter_size":"unknown","context_length":512},"estimated_ram_gb":0.05}# What is loaded now, and when each model unloadscurl $MATRICXON_URL/api/ps{"models":[{"name":"hf.co/leliuga/all-MiniLM-L6-v2-GGUF:Q8_0","size":25008064,"size_vram":0,"expires_at":"2026-10-20T05:50:43+00:00"}]}Capabilities are completion, tools, vision, embedding and rerank. Pull, delete, copy and create are admin calls (signed when a secret is set, below):
mx_admin POST /api/pull '{"model": "hf.co/leliuga/all-MiniLM-L6-v2-GGUF:Q8_0"}'mx_admin POST /api/copy '{"source": "hf.co/leliuga/all-MiniLM-L6-v2-GGUF:Q8_0", "destination": "minilm"}'mx_admin DELETE /api/delete '{"model": "minilm"}'A pull streams its progress, one JSON line per step (status, then completed and total bytes while downloading).
Server and storage
Section titled “Server and storage”| Endpoint | Notes |
|---|---|
GET /api/health |
Matricxon-only: supported architectures, quantizations, MoE and vision lists |
GET /api/version |
Version string |
GET /api/storage |
Matricxon-only: each storage folder, its role, size and free space |
PUT /api/runtime-settings |
Matricxon-only: change settings without a restart. Admin |
curl $MATRICXON_URL/api/version# {"version":"0.1.0"}
# Keep models loaded for 24 hours after their last use, from now onmx_admin PUT /api/runtime-settings '{"default_keep_alive_seconds": 86400}'# {"applied_now":["default_keep_alive_seconds"],"applied_next_load":[]}A live change lasts until the server restarts. To keep it, also set it in .env (see Configuration).
Saved chat caches
Section titled “Saved chat caches”See Prompt cache.
| Endpoint | Notes |
|---|---|
GET /api/cache/persistence |
Show the limits and how much is stored |
PUT /api/cache/persistence |
Change enabled, budget_mb or ttl_hours. Admin |
DELETE /api/cache/persistence |
Delete every saved cache. Admin |
DELETE /api/cache/persistence/chats/{tag} |
Delete the saved caches of one chat. Admin |
curl $MATRICXON_URL/api/cache/persistence{"enabled":true,"budget_mb":4096,"ttl_hours":168,"files":15,"chats":15,"used_bytes":601308576,"folder":"/mnt/shared/prompt_cache","shared":true}# Keep saved caches for 3 days; omitted fields stay as they aremx_admin PUT /api/cache/persistence '{"ttl_hours": 72}'Cluster
Section titled “Cluster”The cluster and consensus endpoints are used by pAIring. See Cluster.
Admin routes and the admin secret
Section titled “Admin routes and the admin secret”Routes that change models, caches, settings or the cluster are admin routes: pull, push, delete, copy, create, the cache changes and runtime settings above, and the cluster routes.
- With
MATRICXON_ADMIN_SECRETset, each admin call must be signed with it. The signature covers the method, path, body, a timestamp and a one-time value, so a captured call cannot be changed or replayed. pAIring signs its calls for you. - With no secret, admin routes are open. Then protect the network instead.
The signature does not hide the content. Use TLS, or a trusted network, for that.
Signing an admin call
Section titled “Signing an admin call”Each signed call carries three headers:
| Header | Value |
|---|---|
X-Matricxon-Time |
Unix time in seconds; accepted within 2 minutes of the server’s clock |
X-Matricxon-Nonce |
A random value, used once |
X-Matricxon-Signature |
HMAC-SHA256, in hex, of the five lines below |
The key is the SHA-256 of matricxon-admin| followed by the secret. The signed text is five lines: the time, the nonce, the method in capitals, the path with its query, and the SHA-256 (hex) of the body exactly as sent.
This shell function, used in the examples above, signs and sends a call with curl and openssl:
# Usage: mx_admin METHOD PATH [JSON-BODY]# Needs MATRICXON_URL and MATRICXON_ADMIN_SECRET in the environment.mx_admin() { local method=$1 path=$2 body=${3-} local stamp nonce key body_hash sig stamp=$(date +%s) nonce=$(openssl rand -hex 12) key=$(printf 'matricxon-admin|%s' "$MATRICXON_ADMIN_SECRET" | openssl dgst -sha256 -r | cut -d' ' -f1) body_hash=$(printf '%s' "$body" | openssl dgst -sha256 -r | cut -d' ' -f1) sig=$(printf '%s\n%s\n%s\n%s\n%s' "$stamp" "$nonce" "$method" "$path" "$body_hash" \ | openssl dgst -sha256 -mac HMAC -macopt "hexkey:$key" -r | cut -d' ' -f1) curl -sS -X "$method" "$MATRICXON_URL$path" \ -H 'Content-Type: application/json' \ -H "X-Matricxon-Time: $stamp" \ -H "X-Matricxon-Nonce: $nonce" \ -H "X-Matricxon-Signature: $sig" \ ${body:+--data-raw "$body"}}An unsigned or wrongly signed call is refused with 401:
{"detail":"admin request not signed with the admin secret"}