# API Reference: api.riotpiao.com Gateway to all homelab services. Single entry point for LLM inference, workflows, queues, memory, and cluster operations. **Base URL:** `https://api.riotpiao.com` --- ## Table of Contents 1. [Health & Status](#health--status) 2. [LLM Services](#llm-services) 3. [Workflow Services (Temporal)](#workflow-services-temporal) 4. [Queue Services (SQS)](#queue-services-sqs) 5. [Memory Services](#memory-services) 6. [IAM Services](#iam-services) 7. [S3 Services](#s3-services) 8. [Authentication](#authentication) 9. [Error Handling](#error-handling) --- ## Health & Status ### GET /healthz Liveness probe. Returns immediately without checks. ```bash curl https://api.riotpiao.com/healthz ``` **Response:** ```json { "status": "alive" } ``` **Status Code:** 200 --- ### GET /readyz Readiness probe. Returns 200 when gateway is ready (config loaded, connections available). ```bash curl https://api.riotpiao.com/readyz ``` **Response:** ```json { "status": "ready" } ``` **Status Code:** 200 (ready) or 503 (not ready) --- ## LLM Services ### GET /v1/models List all available models for inference. ```bash curl https://api.riotpiao.com/v1/models ``` **Response:** ```json { "object": "list", "data": [ { "id": "reasoning", "object": "model", "owned_by": "api.riotpiao.com", "created": 1700000000 }, { "id": "ornith:35b", "object": "model", "owned_by": "api.riotpiao.com", "created": 1700000000 }, { "id": "qwen2.5:3b-instruct", "object": "model", "owned_by": "api.riotpiao.com", "created": 1700000000 }, { "id": "nomic-ai/nomic-embed-text-v2-moe", "object": "model", "owned_by": "api.riotpiao.com", "created": 1700000000 }, { "id": "BAAI/bge-reranker-base", "object": "model", "owned_by": "api.riotpiao.com", "created": 1700000000 } ] } ``` **Status Code:** 200 --- ### POST /v1/chat/completions Chat with an LLM model. Supports streaming, tool calling, and multi-turn conversations. ```bash curl -X POST https://api.riotpiao.com/v1/chat/completions \ -H 'Content-Type: application/json' \ -d '{ "model": "reasoning", "messages": [ {"role": "user", "content": "What is 2+2?"} ] }' ``` **Request Body:** ```json { "model": "reasoning", "messages": [ { "role": "user", "content": "string or array" } ], "temperature": 0.7, "top_p": 1.0, "max_tokens": 2048, "stream": false, "tools": [ { "type": "function", "function": { "name": "function_name", "description": "What it does", "parameters": { "type": "object", "properties": {}, "required": [] } } } ] } ``` **Response (non-streaming):** ```json { "id": "chatcmpl-123", "object": "chat.completion", "created": 1704000000, "model": "reasoning", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "2+2=4" }, "finish_reason": "stop" } ], "usage": { "prompt_tokens": 10, "completion_tokens": 5, "total_tokens": 15 } } ``` **Response (streaming, SSE format):** ``` data: {"id":"...","object":"chat.completion.chunk","choices":[{"delta":{"content":"2"}}]} data: {"id":"...","object":"chat.completion.chunk","choices":[{"delta":{"content":"+"}}]} data: {"id":"...","object":"chat.completion.chunk","choices":[{"delta":{"content":"2"}}]} data: {"id":"...","object":"chat.completion.chunk","choices":[{"delta":{"content":"="}}]} data: {"id":"...","object":"chat.completion.chunk","choices":[{"delta":{"content":"4"}}]} data: [DONE] ``` **Status Codes:** - 200 OK - 400 Bad Request (invalid model, missing fields, invalid JSON) - 500 Internal Server Error (upstream issue) **Available Models:** - `reasoning` — DeepSeek-R1-Distill reasoning model (8 concurrent slots) - `ornith:35b` — Ollama 35B model - `qwen2.5:3b-instruct` — Qwen 2.5 3B model --- ### POST /v1/embeddings Generate text embeddings. ```bash curl -X POST https://api.riotpiao.com/v1/embeddings \ -H 'Content-Type: application/json' \ -d '{ "model": "nomic-ai/nomic-embed-text-v2-moe", "input": ["text to embed", "another text"] }' ``` **Request Body:** ```json { "model": "nomic-ai/nomic-embed-text-v2-moe", "input": "string or array of strings", "encoding_format": "float" } ``` **Response:** ```json { "object": "list", "data": [ { "object": "embedding", "embedding": [0.1, 0.2, 0.3, ...], "index": 0 }, { "object": "embedding", "embedding": [0.4, 0.5, 0.6, ...], "index": 1 } ], "model": "nomic-ai/nomic-embed-text-v2-moe", "usage": { "prompt_tokens": 20, "total_tokens": 20 } } ``` **Status Codes:** - 200 OK - 400 Bad Request (invalid model or input) - 500 Internal Server Error --- ### POST /v1/rerank Rerank documents by relevance to a query. ```bash curl -X POST https://api.riotpiao.com/v1/rerank \ -H 'Content-Type: application/json' \ -d '{ "model": "BAAI/bge-reranker-base", "query": "machine learning", "texts": [ "Machine learning is AI", "Python is a language", "Deep learning is ML" ], "top_k": 2 }' ``` **Request Body:** ```json { "model": "BAAI/bge-reranker-base", "query": "search query", "texts": ["text1", "text2", "text3"], "top_k": 2, "return_documents": true } ``` **Response:** ```json { "results": [ { "index": 0, "score": 0.95, "text": "Machine learning is AI" }, { "index": 2, "score": 0.85, "text": "Deep learning is ML" } ] } ``` **Status Codes:** - 200 OK - 400 Bad Request - 500 Internal Server Error --- ## Workflow Services (Temporal) Base path: `/workflow` All operations use REST with JSON body. Internally translated to gRPC (port 7233). ### POST /workflow Execute a workflow operation via action dispatch. ```bash curl -X POST https://api.riotpiao.com/workflow \ -H 'Content-Type: application/json' \ -d '{ "action": "START_WORKFLOW", "namespace": "default", "payload": { "workflow_id": "order-123", "workflow_type": "ProcessOrder", "task_queue": "orders_queue", "input": { "order_id": "123", "amount": 99.99 } } }' ``` **Supported Actions:** #### START_WORKFLOW Start a new workflow execution. **Payload:** ```json { "workflow_id": "unique-id", "workflow_type": "WorkflowName", "task_queue": "queue_name", "input": {"field": "value"}, "options": { "workflow_execution_timeout": 3600, "workflow_run_timeout": 1800, "workflow_task_timeout": 300 } } ``` **Response:** ```json { "success": true, "action": "START_WORKFLOW", "data": { "workflow_id": "order-123", "run_id": "abc123def", "start_time": "2026-08-27T..." } } ``` #### DESCRIBE_WORKFLOW Get workflow execution details. **Payload:** ```json { "workflow_id": "order-123", "run_id": "abc123def" } ``` **Response:** ```json { "success": true, "action": "DESCRIBE_WORKFLOW", "data": { "workflow_id": "order-123", "run_id": "abc123def", "status": "RUNNING", "start_time": "2026-08-27T..." } } ``` #### LIST_WORKFLOWS List workflow executions with filtering. **Payload:** ```json { "status": "RUNNING", "page_size": 50, "next_page_token": "" } ``` #### GET_WORKFLOW_HISTORY Retrieve workflow execution history (events). **Payload:** ```json { "workflow_id": "order-123", "run_id": "abc123def", "max_events": 100 } ``` #### SIGNAL_WORKFLOW Send a signal to a running workflow (trigger handler). **Payload:** ```json { "workflow_id": "order-123", "run_id": "abc123def", "signal_name": "payment_received", "input": {"amount": 99.99} } ``` #### QUERY_WORKFLOW Query workflow state without modifying it (read-only). **Payload:** ```json { "workflow_id": "order-123", "run_id": "abc123def", "query_type": "get_status" } ``` #### CANCEL_WORKFLOW Request graceful cancellation. **Payload:** ```json { "workflow_id": "order-123", "run_id": "abc123def" } ``` #### TERMINATE_WORKFLOW Stop workflow immediately. **Payload:** ```json { "workflow_id": "order-123", "run_id": "abc123def", "reason": "User cancelled" } ``` #### Other Actions - RESET_WORKFLOW - UPDATE_WORKFLOW - HEARTBEAT_ACTIVITY - COMPLETE_ACTIVITY - FAIL_ACTIVITY **Status Codes:** - 200 OK - 400 Bad Request (invalid action or fields) - 404 Not Found (workflow not found) - 503 Service Unavailable (Temporal unreachable) --- ## Queue Services (SQS) Base path: `/sqs` (via X-Service header routing) Operations via ServiceAdapter CRD. Use header-based dispatch: ```bash curl -X GET https://api.riotpiao.com/ \ -H 'X-Service: sqs' \ -H 'X-Resource: queue/my-queue/messages' ``` **Supported Resources:** - `queue` — List queues - `queue/{name}/message` — Send/receive messages - `queue/{name}/messages` — Batch operations --- ## Memory Services Base path: `/` (via X-Service header) Query and manage semantic memory for knowledge retrieval. ```bash curl -X GET https://api.riotpiao.com/ \ -H 'X-Service: memory' \ -H 'X-Resource: query' \ -G --data-urlencode 'query=explain machine learning' \ --data-urlencode 'level=L1,L2' ``` **Supported Resources:** - `query` — Search memory (GET with params) - `skill` — List/retrieve skills - `project` — List/describe projects - `ingest` — Add new documents (POST, requires memory:write capability) --- ## IAM Services Base path: `/` (via X-Service header) Manage Authentik users, groups, and permissions. ```bash curl -X GET https://api.riotpiao.com/ \ -H 'Authorization: Bearer ' \ -H 'X-Service: iam' \ -H 'X-Resource: user' ``` **Supported Resources:** - `user` — List/create users - `user/{id}` — Get/update/delete specific user - `role` (group) — Manage groups/roles - `permission` — List permissions - `flow` — List authentication flows --- ## S3 Services Base path: `/` (via X-Service header) Object storage operations via MinIO. ```bash curl -X GET https://api.riotpiao.com/ \ -H 'X-Service: s3' \ -H 'X-Resource: bucket/my-bucket/objects' ``` **Supported Resources:** - `bucket` — List buckets - `bucket/{name}/objects` — List objects in bucket - `bucket/{name}/object/{key}` — Get/put/delete object --- ## Authentication ### Bearer Token (JWT) All operations except `/healthz` and `/readyz` require authentication. ```bash curl -H 'Authorization: Bearer ' \ https://api.riotpiao.com/v1/models ``` ### Obtaining Tokens **Via Authentik OIDC (human login):** ```bash core auth login --username user@example.com ``` **Via service account (programmatic):** ```bash core mwinit login --username service-account --password secret export RIOTPIAO_TOKEN=$(cat ~/.talos/.riotpiao-auth) curl -H "Authorization: Bearer $RIOTPIAO_TOKEN" \ https://api.riotpiao.com/v1/models ``` ### Capabilities (RBAC) Tokens embed capabilities in claims. Required capabilities: - `llm:inference` — `/v1/*` chat/embeddings/rerank - `workflow:execute` — `/workflow` operations - `memory:read` — Memory queries - `memory:write` — Memory ingest - `sqs:access` — Queue operations - `s3:access` — S3 operations - `iam:admin` — IAM management --- ## Error Handling ### Problem Details (RFC 9457) All error responses use standardized JSON format: ```json { "type": "https://api.example.com/problems/unknown-model", "title": "Unknown Model", "status": 400, "detail": "Model 'gpt-4' is not available. See valid_models for available options.", "valid_models": ["reasoning", "ornith:35b", ...] } ``` ### HTTP Status Codes | Status | Meaning | |--------|---------| | 200 | Success | | 400 | Bad Request (validation error, invalid model, missing fields) | | 401 | Unauthorized (invalid/missing token) | | 403 | Forbidden (insufficient permissions/capability) | | 404 | Not Found (workflow, resource) | | 409 | Conflict (duplicate workflow_id) | | 429 | Too Many Requests (rate limit exceeded) | | 503 | Service Unavailable (backend unreachable) | | 504 | Gateway Timeout (request exceeded timeout) | ### Error Examples **Unknown Model:** ```bash curl -X POST https://api.riotpiao.com/v1/chat/completions \ -d '{"model":"gpt-4","messages":[]}' # Returns 400 { "type": "https://api.example.com/problems/unknown-model", "title": "Unknown Model", "status": 400, "detail": "Model 'gpt-4' is not available", "valid_models": ["reasoning", "ornith:35b", "qwen2.5:3b-instruct", ...] } ``` **Temporal Unavailable:** ```bash curl -X POST https://api.riotpiao.com/workflow \ -d '{"action":"START_WORKFLOW",...}' # Returns 503 if Temporal server unreachable { "success": false, "error": "TEMPORAL_UNAVAILABLE", "message": "Temporal server connection not available" } ``` --- ## Examples ### Complete RAG Pipeline 1. **Query embedding:** ```bash curl -X POST https://api.riotpiao.com/v1/embeddings \ -H 'Authorization: Bearer $TOKEN' \ -d '{ "model": "nomic-ai/nomic-embed-text-v2-moe", "input": "how do neural networks work" }' | jq '.data[0].embedding' ``` 2. **Rerank documents:** ```bash curl -X POST https://api.riotpiao.com/v1/rerank \ -H 'Authorization: Bearer $TOKEN' \ -d '{ "model": "BAAI/bge-reranker-base", "query": "how do neural networks work", "texts": ["doc1", "doc2", "doc3"], "top_k": 2 }' ``` 3. **Chat with context:** ```bash curl -X POST https://api.riotpiao.com/v1/chat/completions \ -H 'Authorization: Bearer $TOKEN' \ -d '{ "model": "reasoning", "messages": [ { "role": "user", "content": "Based on these documents: [top-2 from rerank]\nQuestion: how do neural networks work?" } ] }' ``` ### Workflow Orchestration ```bash # Start workflow WORKFLOW_ID="order-$(date +%s)" curl -X POST https://api.riotpiao.com/workflow \ -H 'Authorization: Bearer $TOKEN' \ -d "{ \"action\": \"START_WORKFLOW\", \"namespace\": \"default\", \"payload\": { \"workflow_id\": \"$WORKFLOW_ID\", \"workflow_type\": \"ProcessOrder\", \"task_queue\": \"orders\", \"input\": {\"order_id\": \"123\"} } }" # Monitor execution curl -X POST https://api.riotpiao.com/workflow \ -H 'Authorization: Bearer $TOKEN' \ -d "{ \"action\": \"DESCRIBE_WORKFLOW\", \"namespace\": \"default\", \"payload\": {\"workflow_id\": \"$WORKFLOW_ID\"} }" # Send signal when payment received curl -X POST https://api.riotpiao.com/workflow \ -H 'Authorization: Bearer $TOKEN' \ -d "{ \"action\": \"SIGNAL_WORKFLOW\", \"namespace\": \"default\", \"payload\": { \"workflow_id\": \"$WORKFLOW_ID\", \"signal_name\": \"payment_received\", \"input\": {\"amount\": 99.99} } }" ``` --- ## Rate Limits & Quotas - `/v1/chat/completions` — 8 concurrent slots (reasoning model) - `/v1/embeddings` — 10 concurrent - `/v1/rerank` — 10 concurrent - `/workflow` — 100 concurrent operations - Retry-After header set on 429 responses --- ## Timeouts | Endpoint | Connect | Read | Write | |----------|---------|------|-------| | `/v1/chat/completions` | 10s | 1h | 1h | | `/v1/embeddings` | 10s | 10m | 10m | | `/v1/rerank` | 10s | 10m | 10m | | `/workflow` | 10s | 30s | 10s | --- ## Support - **Health:** `curl https://api.riotpiao.com/healthz` - **Readiness:** `curl https://api.riotpiao.com/readyz` - **Models:** `curl https://api.riotpiao.com/v1/models` - **Logs:** `kubectl -n api logs deployment/homelab-frontend` --- ## LLM Inference in Workflows The Poimen workflows system includes built-in LLM inference activities that call `/v1/chat/completions` via the gateway. ### LLMInferenceActivity Single-prompt LLM inference within a workflow. **Workflow Definition (Canvas Node):** ```json { "id": "llm-node-1", "type": "llm-inference", "label": "Analyze Code with LLM", "data": { "model": "reasoning", "system_prompt": "You are a code analysis expert. Provide detailed feedback.", "user_prompt": "Analyze this code for security issues: {{ previous_output.code }}", "temperature": 0.7, "max_tokens": 2048 } } ``` **Backend Implementation:** The LLMInferenceActivity in the workflows backend automatically: 1. Substitutes template variables (e.g., `{{ previous_output.code }}`) 2. Calls `/v1/chat/completions` with the resolved prompt 3. Returns the LLM response as activity output 4. Retries on transient failures (up to 3 attempts) 5. Timeouts after 120 seconds **Output:** ```json { "response": "The code has several security vulnerabilities...", "model": "reasoning", "stop_reason": "stop_sequence", "tokens_used": 450 } ``` **Supported Models:** - `reasoning` — DeepSeek-R1-Distill (best for complex analysis) - `ornith:35b` — Ollama 35B - `ornith:13b` — Ollama 13B - `qwen2.5:3b` — Qwen 2.5 3B --- ### LLMBatchInferenceActivity Multiple-prompt LLM inference (sequential processing). **Workflow Definition:** ```json { "id": "llm-batch-1", "type": "llm-batch-inference", "label": "Batch Code Review", "data": { "model": "reasoning", "system_prompt": "Review each code snippet and provide feedback.", "prompts": [ "Review snippet 1: {{ files[0].content }}", "Review snippet 2: {{ files[1].content }}", "Review snippet 3: {{ files[2].content }}" ] } } ``` **Output:** ```json { "responses": [ "Snippet 1 review...", "Snippet 2 review...", "Snippet 3 review..." ], "model": "reasoning", "errors": [] } ``` **Typical Use Cases:** - Batch code review across multiple files - Parallel document summarization - Comparative analysis of alternatives - Policy compliance checking --- ### Workflow Integration Examples **1. Code Analysis Workflow** ``` Clone Repo → Analyze Code → LLM Security Review → Generate Report → Notify ``` **2. Document Processing** ``` Retrieve Documents → Embed + Index → LLM Summarize (batch) → Archive ``` **3. Multi-Stage Review** ``` Retrieve Memory → LLM Context Extraction → Route to Activity A/B/C → Notify ``` --- ### Error Handling If LLM inference fails: - First activity retry (2-second backoff) - Second activity retry (4-second backoff) - Third activity retry (8-second backoff) - If all retries fail, workflow records error and proceeds to next activity (or fails if terminal) **Common Failure Scenarios:** - Network timeout: `connection refused` (retry automatically) - Model not found: `unknown model: xyz` (terminal error) - Rate limited: HTTP 429 (retry with exponential backoff) - Prompt too long: `context length exceeded` (terminal error) --- ### Performance & Cost - Single prompt inference: ~100-500ms (model-dependent) - Batch processing: Serial (not parallel), ~100-500ms per prompt - Model inference costs: Free (on-premise Ollama/Reasoning models) - Token counting: Provided in response for quota tracking **Optimization Tips:** - Use `ornith:13b` or `qwen2.5:3b` for faster inference - Use `reasoning` only for complex analysis that needs reasoning - Cache frequently-used prompts at workflow level - Use batch activity for multiple similar prompts (better throughput)