Complete guide for calling gateway-backed services: ✅ Quick start with X-Service routing ✅ Authentication & token generation (Authentik OAuth2) ✅ Service map (SQS, Memory, S3, IAM, Workflow) ✅ Service-specific guides with curl examples ✅ SQS: Send/receive/acknowledge messages ✅ S3/MinIO: Upload/download/list objects ✅ IAM: User & role management ✅ Temporal: gRPC-only, SDK usage ✅ Error handling (RFC 9457) ✅ Request/response examples ✅ Integration testing ✅ Debugging guide Covers: • Bearer token flows • X-Service header routing • Service-specific auth requirements • Status codes & error mapping • Long-polling for SQS • Rate limits & quotas Ready for production use.
13 KiB
Service Usage Guide
Complete guide for calling all gateway-backed services via api.riotpiao.com.
Table of Contents
Quick Start
All services use the X-Service header to route requests:
curl -X POST https://api.riotpiao.com/path \
-H "X-Service: <service_name>" \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-d '{"key": "value"}'
| Header | Purpose | Example |
|---|---|---|
X-Service |
Route to named service | X-Service: sqs |
X-Resource |
(Optional) Resource ID for auth | X-Resource: agent-worker-queue |
Authorization |
Bearer token (required for auth-protected services) | Authorization: Bearer eyJ... |
Authentication
Getting a Token
From Authentik (OAuth2 client credentials flow):
AUTHENTIK_URL=https://authentik.riotpiao.com
CLIENT_ID="your-client-id"
CLIENT_SECRET="your-client-secret"
TOKEN=$(curl -s -X POST ${AUTHENTIK_URL}/application/o/token/ \
-d "grant_type=client_credentials&client_id=${CLIENT_ID}&client_secret=${CLIENT_SECRET}&scope=openid" \
| jq -r '.access_token')
echo $TOKEN
Replace your-client-id and your-client-secret with Authentik app credentials.
Service-Specific Auth
| Service | Auth Required | Token Audience | Notes |
|---|---|---|---|
| sqs | ✅ Yes (gateway validates) | sqs |
JWT signature & claims verified by gateway before proxying |
| memory | ❌ No | — | Pass-through (service-owned if needed) |
| s3 (MinIO) | ❌ No | — | Native OIDC support (service-owned) |
| iam | ❌ No | — | Pass-through (service-owned if needed) |
| workflow (Temporal) | ❌ No | — | Native JWT support (service-owned) |
Service Map
Gateway Services (via X-Service header)
api.riotpiao.com
├─ X-Service: sqs
│ ├─ Upstream: management-service.sqs.svc.cluster.local:8080
│ ├─ Auth: ✅ Gateway validates JWT
│ └─ Docs: docs/API-sqs.md
│
├─ X-Service: memory
│ ├─ Upstream: poimen-memory.memory.svc.cluster.local:9090
│ ├─ Auth: ❌ Pass-through (service-owned)
│ └─ Docs: See Memory Service section below
│
├─ X-Service: s3
│ ├─ Upstream: minio.data.svc.cluster.local:9000
│ ├─ Auth: ❌ Native OIDC (service-owned)
│ └─ Notes: S3-compatible API
│
├─ X-Service: iam
│ ├─ Upstream: keycloak.iam.svc.cluster.local:8080 (or equivalent)
│ ├─ Auth: ❌ Pass-through (service-owned)
│ └─ Docs: See IAM Service section below
│
└─ X-Service: workflow
├─ Upstream: temporal-frontend.temporal.svc.cluster.local:7233
├─ Auth: ❌ Native JWT support (service-owned)
├─ Protocol: gRPC only (returns 501 for HTTP)
└─ Docs: docs/TEMPORAL_USAGE.md
Path Prefixes (legacy, before X-Service migration)
api.riotpiao.com
├─ /v1/* → llm-serving (predictors: vLLM, Ollama, TEI)
├─ /sqs/* → management-service (Kafka queues)
├─ /workflow/* → Temporal (workflows)
└─ /cluster/* → atlas (topology & Argo delivery)
Migration note: X-Service routing is the current standard. Path prefixes are deprecated.
Service-Specific Guides
SQS (Kafka Queue Management)
Endpoint: POST https://api.riotpiao.com/
Headers:
X-Service: sqs
Authorization: Bearer <jwt>
Send a message:
QUEUE="agent-worker-queue"
BODY=$(printf "hello world" | base64)
curl -X POST https://api.riotpiao.com/ \
-H "X-Service: sqs" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"messageBody\": \"$BODY\",
\"messageAttributes\": {\"values\": {}},
\"delaySeconds\": 0
}"
Response:
{
"messageId": "d9f94e63-b2c1-4e9f-8c5f-8d5e3c1b7a0f",
"sequenceNumber": ""
}
Receive messages (long poll, up to 20s):
QUEUE="agent-worker-queue"
curl -X GET "https://api.riotpiao.com/?X-Service=sqs&queue=$QUEUE&maxNumberOfMessages=10&waitTimeSeconds=20" \
-H "Authorization: Bearer $TOKEN"
Response:
{
"messages": [
{
"messageId": "d9f94e63-b2c1-4e9f-8c5f-8d5e3c1b7a0f",
"receiptHandle": "...",
"body": "aGVsbG8gd29ybGQ=",
"attributes": {"values": {}},
"receiveCount": 1,
"enqueuedAt": "2026-08-27T22:18:37Z"
}
]
}
Acknowledge (delete) a message:
RECEIPT="..."
curl -X DELETE https://api.riotpiao.com/ \
-H "X-Service: sqs" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"receiptHandle\": \"$RECEIPT\"}"
Full documentation: docs/API-sqs.md
Memory Service (Context & Embeddings)
Endpoint: https://api.riotpiao.com/
Headers:
X-Service: memory
Status: Service definition in progress. Uses PostgreSQL + pg_vector for embeddings.
Planned operations:
- Store session memory / agent context
- Query by similarity (embedding search)
- Update with approval workflow (GRM/Git review)
Coming soon: Full API documentation.
S3 / MinIO (Object Storage)
Endpoint: https://api.riotpiao.com/
Headers:
X-Service: s3
List buckets:
curl -X GET https://api.riotpiao.com/ \
-H "X-Service: s3" \
-H "Authorization: Bearer $TOKEN"
List objects in bucket:
curl -X GET https://api.riotpiao.com/?bucket=my-bucket&prefix=data/ \
-H "X-Service: s3"
Put object:
curl -X PUT https://api.riotpiao.com/my-bucket/path/to/object.json \
-H "X-Service: s3" \
--data-binary @object.json
Get object:
curl -X GET https://api.riotpiao.com/my-bucket/path/to/object.json \
-H "X-Service: s3"
Full S3/MinIO API: Standard AWS S3 compatible API. See MinIO docs.
IAM (Identity & Access Management)
Endpoint: https://api.riotpiao.com/
Headers:
X-Service: iam
List roles:
curl -X GET https://api.riotpiao.com/roles \
-H "X-Service: iam"
Get user:
curl -X GET https://api.riotpiao.com/users/alice \
-H "X-Service: iam"
Create user:
curl -X POST https://api.riotpiao.com/users \
-H "X-Service: iam" \
-H "Content-Type: application/json" \
-d "{
\"username\": \"bob\",
\"email\": \"[email protected]\",
\"password\": \"secure-password\"
}"
Assign role to user:
curl -X POST https://api.riotpiao.com/users/bob/roles \
-H "X-Service: iam" \
-H "Content-Type: application/json" \
-d "{\"role\": \"admin\"}"
Full documentation: Service-specific (depends on IAM backend).
Workflow (Temporal)
Endpoint: temporal-frontend.temporal.svc.cluster.local:7233
Protocol: gRPC only
Note: HTTP requests return 501 Not Implemented
Use Temporal SDK directly:
import "go.temporal.io/sdk/client"
c, _ := client.Dial(client.Options{HostPort: "temporal-frontend.temporal.svc.cluster.local:7233"})
defer c.Close()
// Start workflow
run, _ := c.ExecuteWorkflow(ctx, opts, YourWorkflow, args...)
var result YourWorkflowResult
run.Get(ctx, &result)
Full documentation: docs/TEMPORAL_USAGE.md
Error Handling
Standard Error Response
All services return errors in RFC 9457 Problem Details format:
{
"type": "https://api.riotpiao.com/problem/not-found",
"title": "Not Found",
"status": 404,
"detail": "Resource does not exist",
"instance": "/sqs/v1/queues/nonexistent"
}
Common Status Codes
| Code | Meaning | Example |
|---|---|---|
200 OK |
Success | Message sent, resource retrieved |
201 Created |
Resource created | Queue created, object uploaded |
204 No Content |
Success (no body) | Message deleted |
400 Bad Request |
Invalid input | Message body too large, invalid field |
401 Unauthorized |
Missing/invalid token | No Authorization header, token expired |
403 Forbidden |
Token valid but insufficient permissions | User lacks sqs:write permission |
404 Not Found |
Resource not found | Queue doesn't exist, object not found |
429 Too Many Requests |
Rate limit exceeded | Per-user budget exhausted |
502 Bad Gateway |
Upstream unreachable | Service is down or network issue |
501 Not Implemented |
Operation not supported | gRPC request via HTTP |
SQS-Specific Error Mapping
SQS errors (from kmsvc) map as follows:
| gRPC Code | HTTP Status | Message |
|---|---|---|
NotFound |
404 |
Queue or message not found |
AlreadyExists |
409 |
Queue already exists |
InvalidArgument |
400 |
Message body too large, invalid parameter |
Unauthenticated |
401 |
Missing Authorization header |
ResourceExhausted |
429 |
Message too large, quota exceeded |
Request/Response Examples
Example 1: Send SQS Message with Auth
#!/bin/bash
GATEWAY="https://api.riotpiao.com"
AUTHENTIK="https://authentik.riotpiao.com"
CLIENT_ID="sqs-client"
CLIENT_SECRET="secret123"
QUEUE="agent-worker-queue"
# Get token
TOKEN=$(curl -s -X POST ${AUTHENTIK}/application/o/token/ \
-d "grant_type=client_credentials&client_id=${CLIENT_ID}&client_secret=${CLIENT_SECRET}&scope=openid" \
| jq -r '.access_token')
# Send message
BODY=$(echo "process this task" | base64)
curl -X POST ${GATEWAY}/ \
-H "X-Service: sqs" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"messageBody\": \"$BODY\"}" | jq .
Example 2: Receive & Process Queue
#!/bin/bash
GATEWAY="https://api.riotpiao.com"
TOKEN="..."
QUEUE="agent-worker-queue"
MAX_MSGS=10
WAIT_SECS=20
while true; do
# Receive messages (long poll)
RESPONSE=$(curl -s -X GET "${GATEWAY}/?X-Service=sqs&queue=${QUEUE}&maxNumberOfMessages=${MAX_MSGS}&waitTimeSeconds=${WAIT_SECS}" \
-H "Authorization: Bearer $TOKEN")
MESSAGES=$(echo "$RESPONSE" | jq '.messages')
if [[ "$MESSAGES" == "null" ]]; then
echo "No messages (timeout)"
continue
fi
# Process each message
echo "$RESPONSE" | jq -r '.messages[] | @base64d' | while read -r MSG; do
echo "Processing: $MSG"
# Do work...
# Acknowledge message
RECEIPT=$(echo "$RESPONSE" | jq -r '.messages[0].receiptHandle')
curl -s -X DELETE ${GATEWAY}/ \
-H "X-Service: sqs" \
-H "Authorization: Bearer $TOKEN" \
-d "{\"receiptHandle\": \"$RECEIPT\"}"
done
done
Example 3: S3 Workflow (Upload & List)
#!/bin/bash
GATEWAY="https://api.riotpiao.com"
BUCKET="my-data"
# Upload file
echo "Uploading..."
curl -X PUT ${GATEWAY}/${BUCKET}/backup-$(date +%s).tar.gz \
-H "X-Service: s3" \
--data-binary @backup.tar.gz
# List objects
echo "Listing..."
curl -X GET "${GATEWAY}/?bucket=${BUCKET}&prefix=backup-" \
-H "X-Service: s3" | jq '.Contents[]'
Testing
Integration Tests
Run the full test suite:
./scripts/test-integration.sh
Run specific service tests:
GATEWAY_URL=https://api.riotpiao.com go test -tags integration -v -run TestSQS ./internal/serviceadapter
Local Testing
Start local gateway with test services:
# Terminal 1: Start gateway
CONFIG_PATH=k8s/configmap.yaml go run ./cmd/gateway
# Terminal 2: Run tests
./scripts/test-integration.sh
Canary Deployment
Test a single replica before rolling out:
./scripts/test-canary.sh
Debugging
Check Gateway Logs
kubectl -n api logs -l app=api-gateway --tail=100 -f
Port-Forward to Service
kubectl -n sqs port-forward svc/management-service 8080:8080
curl http://localhost:8080/v1/queues
Verify Service Availability
kubectl get svc -A | grep -E "management-service|poimen-memory|minio|temporal"
Test Direct Service Access
kubectl -n sqs exec -it deployment/management-service -- \
curl -s http://localhost:8080/v1/queues | jq .
Rate Limits & Quotas
| Service | Limit | Notes |
|---|---|---|
| SQS | Per-user budget (tokens) | Budget enforced per Authentik user |
| S3 | MinIO quotas | Set per bucket in MinIO config |
| Memory | Not yet enforced | Future: embeddings storage limits |
| Temporal | Workflow concurrency | Set in Temporal cluster config |
See docs/QUOTAS.md for detailed limits.