The gateway forwards your traffic; the control plane API on this page configures it. A change made through the API reaches the gateway within seconds.
Every request to your subdomain runs through the same pipeline: match a route by path and priority, apply its auth mode, spend a rate-limit token, check the response cache, then forward to a healthy origin in the route’s pool. The outcome (status, latency, cache hit, limit hit) is written to the request log, which is what the Traffic panel reads.
The control plane API lives under /api/v1. Every route requires a verified Clerk JWT. The tenant is resolved from the token; you never pass a tenant id. On your first authenticated call, a tenant is provisioned for you automatically.
# base URL
https://<your-control-plane-host>/api/v1
# every request
Authorization: Bearer <clerk session jwt>NEXT_PUBLIC_CLERK_JWT_TEMPLATE and the console mints the token with it.Two ways in. People use a Clerk session; the browser attaches Authorization: Bearer <jwt> automatically. Machines use an API key in the X-API-Key header, issued from the Keys panel with the scopes it needs.
# session (what the console sends)
curl https://<host>/api/v1/routes \
-H "Authorization: Bearer $CLERK_JWT"
# machine caller
curl https://<host>/api/v1/routes \
-H "X-API-Key: ve_live_..."An origin is a backend the gateway can forward to. Health checks run on the interval you set; a failing origin is taken out of rotation until it passes again.
curl -X POST https://<host>/api/v1/origins \
-H "Authorization: Bearer $CLERK_JWT" \
-H "Content-Type: application/json" \
-d '{
"name": "orders-api",
"url": "https://orders.internal.example.com",
"health_check_path": "/health",
"health_check_interval": 30,
"timeout_seconds": 5,
"max_retries": 3,
"weight": 1
}'A route binds a path pattern to an origin and carries its policy: methods, priority, auth mode, rate limit, cache. Higher priority wins when patterns overlap.
The gateway tries your active routes from the highest priority down and takes the first one whose path and method both match. Edit the table or the request to check a setup before you create it:
Build the create call. The summary under the form says what the gateway will do with it.
What this route does
curl -X POST https://<host>/api/v1/routes \
-H "Authorization: Bearer $CLERK_JWT" \
-H "Content-Type: application/json" \
-d '{
"origin_id": "<origin uuid>",
"name": "orders",
"path_pattern": "/api/orders/*",
"methods": [
"GET",
"POST"
],
"priority": 10,
"auth_mode": "jwt_required",
"load_balancing": "weighted",
"is_active": true,
"rate_limit_enabled": true,
"rate_limit_requests_per_second": 50,
"rate_limit_burst": 20,
"rate_limit_key_strategy": "tenant_user",
"cache_enabled": false
}'Beyond its primary origin, a route can load-balance across a pool. Members are health-checked like any origin. The route’s load_balancing picks how a request is assigned: weighted (default, random by origin weight), round_robin,least_conn (fewest in-flight requests), or ip_hash (a client IP sticks to one origin).
Keys authenticate machine callers. The secret is returned once, on creation. Scopes are read, write, admin; expiry is optional.
curl -X POST https://<host>/api/v1/api-keys \
-H "Authorization: Bearer $CLERK_JWT" \
-H "Content-Type: application/json" \
-d '{ "name": "ci-deploy", "scopes": ["read","write"], "expires_at": "2026-12-31T23:59:59Z" }'
# -> { ..., "key": "ve_live_xxx" } (shown once)A rollup of the request log for a time window. Buckets are hourly for 1h and 24h, daily beyond that.
curl "https://<host>/api/v1/analytics?window=24h" \
-H "Authorization: Bearer $CLERK_JWT"
{
"window": "24h",
"generated_at": "2026-08-29T12:00:00Z",
"totals": {
"total_requests": 48210,
"error_rate": 0.012,
"cache_hit_rate": 0.41,
"rate_limited_count": 88,
"avg_latency_ms": 37.4,
"p95_latency_ms": 121.0
},
"series": [ { "ts": "...", "count": 2010, "avg_latency_ms": 35.1, "error_count": 12 } ],
"status_breakdown": { "200": 46110, "404": 900, "500": 210 },
"top_routes": [ { "path": "/api/orders/*", "count": 12005, "avg_latency_ms": 41.2, "error_count": 30 } ]
}Set per route, in auth_mode. Pick one to see what a caller has to send:
A valid Clerk JWT must be present.
curl https://<host>/api/v1/routes \
-H "Authorization: Bearer $JWT" # requiredmissing it: 401 Unauthorized
What the gateway itself answers with, as opposed to responses your origin sends back. Every one of these is also written to the request log, so it shows up in Traffic.
A response served from the cache carries X-Cache: HIT.