API Reference
Base URL: http://localhost:8080 (default)
Authentication
When authentication is enabled (RLAAS_AUTH_ENABLED=true), all requests except exempt paths must include credentials.
API Key Mode
Set RLAAS_AUTH_MODE=apikey and provide keys via RLAAS_AUTH_API_KEYS.
X-Api-Key: your-secret-key
Alternatively, pass the key as a Bearer token:
Authorization: Bearer your-secret-key
JWT Mode
Set RLAAS_AUTH_MODE=jwt and provide the HMAC secret via RLAAS_AUTH_JWT_SECRET.
Authorization: Bearer <HS256-signed-JWT>
Mutating endpoints (POST, PUT, DELETE) require the configured admin role claim. Read endpoints accept the read-only role.
Exempt Paths
/healthz and /readyz are exempt by default so that Kubernetes probes work without credentials.
Operational Endpoints
GET /healthz
Liveness probe. Returns 200 OK with body ok when the process is alive.
GET /readyz
Readiness probe. Returns 200 OK with body ok after all routes are registered and the server is ready to accept traffic. Returns 503 Service Unavailable during startup and shutdown drain.
GET /metrics
Prometheus text exposition format. Exposes counters for decisions (total, allowed, denied, shadow), latency histogram, policy cache hit/miss, counter store errors, and per-tenant/policy dimensional counters.
Decision APIs
Core endpoints for rate-limit evaluation and concurrency control.
POST /rlaas/v1/check
Evaluate a rate-limit decision for a request context.
Request Body
{
"request_id": "req-1",
"org_id": "acme",
"tenant_id": "retail",
"signal_type": "http",
"operation": "charge",
"endpoint": "/v1/charge",
"method": "POST",
"user_id": "u1",
"tags": { "env": "production" }
}
Response (200 OK)
{
"allowed": true,
"action": "allow",
"reason": "within_limit",
"matched_policy_id": "payments-limit",
"remaining": 99,
"retry_after": 0,
"shadow_mode": false
}
signal_type. The engine matches the most specific policy based on provided fields.
POST /rlaas/v1/acquire
Acquire a concurrency lease. Use with concurrency limiter algorithm.
Request Body
{
"request_id": "req-2",
"org_id": "acme",
"signal_type": "http",
"operation": "heavy-query",
"user_id": "u1"
}
Response
{
"allowed": true,
"action": "allow",
"reason": "lease_acquired",
"remaining": 4
}
POST /rlaas/v1/release
Release a previously acquired concurrency lease.
Request Body
{
"request_id": "req-2",
"org_id": "acme",
"signal_type": "http",
"operation": "heavy-query",
"user_id": "u1"
}
Response
{
"allowed": true,
"action": "allow",
"reason": "lease_released"
}
Policy CRUD
GET /rlaas/v1/policies
List all policies.
Response
[
{
"policy_id": "payments-limit",
"name": "Payments limit",
"enabled": true,
"priority": 100,
"scope": { "org_id": "acme", "signal_type": "http", "operation": "charge" },
"algorithm": { "type": "fixed_window", "limit": 100, "window": "1m" },
"action": "deny",
"failure_mode": "fail_open",
"enforcement_mode": "enforce",
"rollout_percent": 100
}
]
POST /rlaas/v1/policies
Create a new policy.
Request Body
{
"policy_id": "payments-limit",
"name": "Payments limit",
"enabled": true,
"priority": 100,
"scope": {
"org_id": "acme",
"signal_type": "http",
"operation": "charge"
},
"algorithm": {
"type": "fixed_window",
"limit": 100,
"window": "1m"
},
"action": "deny",
"failure_mode": "fail_open",
"enforcement_mode": "enforce",
"rollout_percent": 100
}
GET /rlaas/v1/policies/{id}
Get a specific policy by ID.
PUT /rlaas/v1/policies/{id}
Update an existing policy. The full policy body is required.
DELETE /rlaas/v1/policies/{id}
Delete a policy by ID.
Policy Lifecycle APIs
POST /rlaas/v1/policies/validate
Validate a policy definition before deployment.
Request
{
"name": "Validation sample",
"enabled": true,
"scope": { "signal_type": "http", "operation": "charge" },
"algorithm": { "type": "fixed_window", "limit": 10, "window": "1m" },
"action": "deny",
"rollout_percent": 50
}
Response
{ "valid": true }
POST /rlaas/v1/policies/{id}/rollout
Update the rollout percentage for gradual enforcement.
{ "rollout_percent": 25 }
POST /rlaas/v1/policies/{id}/rollback
Roll back to a specific previous version.
{ "version": 1 }
GET /rlaas/v1/policies/{id}/audit
Get the audit trail for a policy — all changes with timestamps, action types, old/new values.
GET /rlaas/v1/policies/{id}/versions
Get all historical versions of a policy for review or rollback.
Analytics
GET /rlaas/v1/analytics/summary
Get a summary of decision events with tag aggregation.
Query Parameters
| Param | Type | Description |
|---|---|---|
top | integer | Return only top N entries (optional) |
Example
curl http://localhost:8080/rlaas/v1/analytics/summary?top=5
Sidecar / Agent Endpoints
Default port: :18080
| Method | Endpoint | Description |
|---|---|---|
| POST | /rlaas/v1/check | Local rate-limit decision (proxied to upstream) |
| GET | /healthz | Health check |
| GET | /rlaas/v1/agent/status | Agent status and metadata |
| POST | /rlaas/v1/agent/invalidate | Trigger cache invalidation |
gRPC Service
Proto definition: api/proto/rlaas.proto | Default port: :9090
service RateLimitService {
rpc CheckLimit(CheckLimitRequest) returns (CheckLimitResponse);
rpc Acquire(AcquireRequest) returns (AcquireResponse);
rpc Release(ReleaseRequest) returns (ReleaseResponse);
}
The gRPC service exposes the same decision logic as the HTTP API. Generate client stubs from the proto file for any language.
RequestContext Object
Sent as the body of decision API calls. All fields are optional except as noted.
| Field | Type | Description |
|---|---|---|
request_id | string | Unique request identifier |
org_id | string | Organization identifier |
tenant_id | string | Tenant identifier |
application | string | Application name |
service | string | Service name |
environment | string | Environment (prod, staging, dev) |
signal_type | string | http, grpc, log, trace, event, auth, job, custom |
operation | string | Operation name |
endpoint | string | Endpoint path |
method | string | HTTP method or gRPC method |
user_id | string | User identifier |
api_key | string | API key |
client_id | string | Client identifier |
source_ip | string | Source IP address |
region | string | Region identifier |
resource | string | Resource name |
severity | string | Log severity level |
span_name | string | Trace span name |
topic | string | Message topic |
consumer_group | string | Consumer group name |
job_type | string | Background job type |
quantity | int64 | Cost per request (default 1) |
tags | map<string,string> | Custom key-value tags |
Decision Object
Returned by decision API calls.
| Field | Type | Description |
|---|---|---|
allowed | bool | Whether the request is allowed |
action | string | allow, deny, delay, sample, drop, shadow_only, ... |
reason | string | Explanation (within_limit, limit_exceeded, ...) |
matched_policy_id | string | ID of the policy that matched |
remaining | int64 | Remaining quota in current window |
retry_after | duration | When to retry (for deny/delay) |
shadow_mode | bool | Whether this was a shadow-only evaluation |
metadata | map | Additional decision metadata |
Policy Object
Used for policy CRUD operations.
| Field | Type | Description |
|---|---|---|
policy_id | string | Unique policy identifier |
name | string | Human-readable name |
enabled | bool | Whether the policy is active |
priority | int | Higher = more important |
scope | PolicyScope | Matching dimensions |
algorithm | AlgorithmConfig | Algorithm type and config |
action | string | Action when limit exceeded |
failure_mode | string | fail_open or fail_closed |
enforcement_mode | string | enforce or shadow |
rollout_percent | int | 0–100, progressive rollout |
metadata | map | Extra metadata (match_expr, etc.) |
Error Format
All error responses return a JSON body with a descriptive message:
{
"error": "policy not found",
"status": 404
}