REST API
Use the REST API directly when you need server-side control, CI/CD integration, or a language without a native SDK.
Authentication
Every request requires an X-API-Key header. Server keys start
with sk_live_; client keys with pk_live_. API keys
must never be placed in the URL query string, query strings leak into
access logs, proxy caches, browser history and Referer headers,
so requests carrying a key in the URL are rejected with a
400.
X-API-Key: sk_live_xxx
Browser EventSource can't set custom headers, so for SSE
(GET /v1/stream) exchange your key for a single-use, 60-second
ticket and put that on the URL instead:
# 1. mint a ticket (header-authenticated)
curl -X POST https://shipsilently-cf.workers.dev/v1/stream/ticket \
-H "X-API-Key: sk_live_xxx"
# → { "ticket": "…", "expiresIn": 60 }
# 2. open the stream with the ticket (single-use)
new EventSource("https://shipsilently-cf.workers.dev/v1/stream?ticket=…")Base URL
https://shipsilently-cf.workers.devPOST /v1/evaluate
Evaluate a single flag for a user context.
curl -X POST https://shipsilently-cf.workers.dev/v1/evaluate \
-H "X-API-Key: $SHIPSILENTLY_KEY" \
-H "Content-Type: application/json" \
-d '{
"flagKey": "new-checkout-v2",
"context": { "userId": "u_123", "plan": "pro" }
}' const res = await fetch('https://shipsilently-cf.workers.dev/v1/evaluate', {
method: 'POST',
headers: {
'X-API-Key': process.env.SHIPSILENTLY_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
flagKey: 'new-checkout-v2',
context: { userId: 'u_123', plan: 'pro' },
}),
});
const result = await res.json(); import os, requests
res = requests.post(
"https://shipsilently-cf.workers.dev/v1/evaluate",
headers={"X-API-Key": os.environ["SHIPSILENTLY_KEY"]},
json={
"flagKey": "new-checkout-v2",
"context": {"userId": "u_123", "plan": "pro"},
},
)
result = res.json() body := `{"flagKey":"new-checkout-v2","context":{"userId":"u_123","plan":"pro"}}`
req, _ := http.NewRequest("POST",
"https://shipsilently-cf.workers.dev/v1/evaluate",
strings.NewReader(body))
req.Header.Set("X-API-Key", os.Getenv("SHIPSILENTLY_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close() Response
{
"flagKey": "new-checkout-v2",
"value": true,
"reason": "rollout",
"ruleId": "rule_4f2a"
}POST /v1/evaluate/batch
Returns every flag for a context in one call.
curl -X POST https://shipsilently-cf.workers.dev/v1/evaluate/batch \
-H "X-API-Key: $SHIPSILENTLY_KEY" \
-H "Content-Type: application/json" \
-d '{ "context": { "userId": "u_123" } }'GET /v1/stream
Server-Sent Events stream. Emits a payload whenever a flag changes; sends a keepalive every 30s so proxies don't drop the connection.
curl -N https://shipsilently-cf.workers.dev/v1/stream \
-H "X-API-Key: $SHIPSILENTLY_KEY"Errors
400: request body failed validation.401: missing or invalid API key.403: key doesn't have permission for this resource.404: flag or environment not found.429: rate limit. TheRetry-Afterheader tells you when to retry.