- Add roles-based auth for service accounts - Document client_credentials flow - Add onboarding steps for new services - Clarify user vs service auth models
918 lines
19 KiB
Markdown
918 lines
19 KiB
Markdown
# 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 <token>' \
|
|
-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 via Authentik-issued JWT.
|
|
|
|
```bash
|
|
curl -H 'Authorization: Bearer <jwt-token>' \
|
|
https://api.riotpiao.com/v1/models
|
|
```
|
|
|
|
### Obtaining Tokens
|
|
|
|
**Service Account (client_credentials flow):**
|
|
|
|
For programmatic access (agents, CI, scripts), use a service account:
|
|
|
|
```bash
|
|
# Get credentials from k8s secret (once)
|
|
CLIENT_ID=$(kubectl -n portfolio get secret portfolio-agent-oidc -o jsonpath='{.data.CLIENT_ID}' | base64 -d)
|
|
CLIENT_SECRET=$(kubectl -n portfolio get secret portfolio-agent-oidc -o jsonpath='{.data.CLIENT_SECRET}' | base64 -d)
|
|
|
|
# Exchange for access token
|
|
TOKEN=$(curl -s -X POST https://authentik.riotpiao.com/application/o/token/ \
|
|
-d "grant_type=client_credentials" \
|
|
-d "client_id=$CLIENT_ID" \
|
|
-d "client_secret=$CLIENT_SECRET" \
|
|
-d "scope=openid profile groups permissions memory" | jq -r '.access_token')
|
|
|
|
# Use token
|
|
curl -H "Authorization: Bearer $TOKEN" \
|
|
https://api.riotpiao.com/v1/models
|
|
```
|
|
|
|
**Available service accounts:**
|
|
- `portfolio-agent` — Portfolio app (memory:read on homelab/portfolio projects)
|
|
- `memory-agent` — Memory service internal (memory:* on all projects)
|
|
|
|
**Human login (authorization_code flow):**
|
|
|
|
Browser-based OAuth2 via Authentik. Used by web apps, not CLI.
|
|
|
|
```
|
|
1. Redirect to: https://authentik.riotpiao.com/application/o/authorize/
|
|
?client_id=<app>&response_type=code&redirect_uri=<callback>&scope=openid+profile+groups+permissions
|
|
2. User authenticates
|
|
3. Exchange code for token at /application/o/token/
|
|
```
|
|
|
|
### JWT Claims
|
|
|
|
Authentik tokens include these custom claims:
|
|
|
|
```json
|
|
{
|
|
"sub": "hashed-user-id",
|
|
"groups": ["homelab-admins", "llm-admins"],
|
|
"permissions": ["llm:inference", "llm:read", "llm:write"],
|
|
"memory_projects": ["homelab", "portfolio"],
|
|
"memory_visibility": "public",
|
|
"memory_role": "user"
|
|
}
|
|
```
|
|
|
|
### Service Account Auth (Recommended for Services)
|
|
|
|
Service accounts use **roles** stored in user attributes. Simpler than groups.
|
|
|
|
**JWT claims (client_credentials flow):**
|
|
```json
|
|
{
|
|
"azp": "portfolio-agent",
|
|
"roles": ["llm:inference", "memory:read"]
|
|
}
|
|
```
|
|
|
|
**Gateway checks `roles` claim:**
|
|
```go
|
|
if hasRole(claims.Roles, "llm:inference") {
|
|
// allow
|
|
}
|
|
```
|
|
|
|
**Available roles:**
|
|
|
|
| Role | Grants access to |
|
|
|------|------------------|
|
|
| `llm:inference` | `/v1/chat/completions`, `/v1/embeddings`, `/v1/rerank` |
|
|
| `memory:read` | Memory queries |
|
|
| `memory:write` | Memory ingest |
|
|
| `s3:read` | S3/MinIO read |
|
|
| `s3:write` | S3/MinIO write |
|
|
|
|
---
|
|
|
|
### Onboarding a New Service
|
|
|
|
1. **Add to provisioning script** (`homelab/scripts/iam/authentik-provision.py`):
|
|
|
|
```python
|
|
SERVICE_ACCOUNTS = {
|
|
# ... existing ...
|
|
"my-new-service": {
|
|
"roles": ["llm:inference", "memory:read"], # what APIs it can call
|
|
"attributes": {
|
|
"memory_projects": ["my-project"], # optional: memory access scope
|
|
"memory_visibility": "public",
|
|
},
|
|
"secret_ns": "my-namespace", # k8s namespace for credentials
|
|
"secret_name": "my-service-oidc", # k8s secret name
|
|
},
|
|
}
|
|
```
|
|
|
|
2. **Run provisioning:**
|
|
|
|
```bash
|
|
export AUTHENTIK_BOOTSTRAP_TOKEN=$(kubectl -n iam get secret authentik-secrets \
|
|
-o jsonpath='{.data.AUTHENTIK_BOOTSTRAP_TOKEN}' | base64 -d)
|
|
python3 scripts/iam/authentik-provision.py
|
|
```
|
|
|
|
3. **Use credentials in your service:**
|
|
|
|
```bash
|
|
# Credentials stored in k8s secret
|
|
kubectl -n my-namespace get secret my-service-oidc -o yaml
|
|
# Contains: CLIENT_ID, CLIENT_SECRET, TOKEN_URL, ISSUER
|
|
|
|
# Get token
|
|
TOKEN=$(curl -s -X POST $TOKEN_URL \
|
|
-d "grant_type=client_credentials" \
|
|
-d "client_id=$CLIENT_ID" \
|
|
-d "client_secret=$CLIENT_SECRET" \
|
|
-d "scope=openid roles" | jq -r '.access_token')
|
|
|
|
# Call API
|
|
curl -H "Authorization: Bearer $TOKEN" https://api.riotpiao.com/v1/models
|
|
```
|
|
|
|
---
|
|
|
|
### User Auth (Groups → Permissions)
|
|
|
|
Human users use **groups** which map to **permissions**. Used for browser-based apps.
|
|
|
|
**JWT claims (authorization_code flow):**
|
|
```json
|
|
{
|
|
"groups": ["homelab-admins", "llm-admins"],
|
|
"permissions": ["*", "llm:inference", "llm:read", "llm:write"]
|
|
}
|
|
```
|
|
|
|
| Group | Permissions granted |
|
|
|-------|---------------------|
|
|
| `homelab-admins` | `*` (everything) |
|
|
| `llm-admins` | `llm:inference`, `llm:read`, `llm:write` |
|
|
| `llm-users` | `llm:inference` |
|
|
| `memory-users` | `memory:read` |
|
|
| `memory-writers` | `memory:read`, `memory:write` |
|
|
| `poimen-memory-admins` | `memory:*`, `memory:admin` |
|
|
|
|
**Memory-specific claims:**
|
|
|
|
| Claim | Description |
|
|
|-------|-------------|
|
|
| `memory_projects` | Projects user can access (`["*"]` = all) |
|
|
| `memory_visibility` | Max visibility level (`public`, `private`) |
|
|
| `memory_role` | Role for memory service (`user`, `admin`, `portfolio-agent`) |
|
|
|
|
---
|
|
|
|
## 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`
|