Authentication
All API requests require an API key passed via the X-API-Key header.
X-API-Key: your_api_key_here
Request an API key from the Get API Key page. Free tier keys are provisioned within 24 hours.
The GET /health endpoint does not require authentication.
Base URL
All endpoints are served from:
https://api.starksentinel.com
Health Check
GET /health
Returns the current status of the SENTINEL API. No authentication required.
Example Request
curl https://api.starksentinel.com/health
Example Response
{
"status": "healthy",
"version": "1.1.0",
"timestamp": "2026-04-02T12:00:00.000Z"
}
Response Fields
| Field | Type | Description |
|---|---|---|
status | string | Service status. "healthy" when operational. |
version | string | Current API version. |
timestamp | string | ISO 8601 server timestamp. |
Generate Proof
POST /v1/prove
Generates a STARK proof attesting that a set of behavioral observations stays within defined EWMA control limits. The proof is zero-knowledge: raw observations are used to compute the EWMA in-memory, then discarded. Only public inputs (observation count, final EWMA, control limits, pass/fail) are included in the proof envelope.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
observations | number[] | Yes | Array of behavioral metric values (integers). Minimum 1 observation. |
baseline_mean | number | Yes | Expected baseline mean for the EWMA calculation. |
ucl | number | Yes | Upper Control Limit. EWMA must stay below this value to pass. |
lcl | number | Yes | Lower Control Limit. EWMA must stay above this value to pass. |
Example Request
# Generate a STARK proof for 8 behavioral observations curl -X POST https://api.starksentinel.com/v1/prove \ -H "X-API-Key: $SENTINEL_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "observations": [95, 98, 92, 97, 100, 94, 96, 99], "baseline_mean": 96, "ucl": 110, "lcl": 80 }'
Example Response
{
"public_inputs": {
"num_observations": 8,
"baseline_mean": 96,
"final_ewma": 95,
"ucl": 110,
"lcl": 80,
"within_limits": true
},
"proof_bytes": "base64-encoded-stark-proof...",
"metadata": {
"generation_time_ms": 9,
"proof_size_bytes": 6761,
"security_level": 96
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
public_inputs.num_observations | number | Count of observations included in the proof. |
public_inputs.baseline_mean | number | The baseline mean used for EWMA seeding. |
public_inputs.final_ewma | number | Final EWMA value after processing all observations. |
public_inputs.ucl | number | Upper Control Limit used in the proof. |
public_inputs.lcl | number | Lower Control Limit used in the proof. |
public_inputs.within_limits | boolean | true if EWMA stayed within [lcl, ucl] for all observations. |
proof_bytes | string | Base64-encoded STARK proof. Pass this to /v1/verify. |
metadata.generation_time_ms | number | Time to generate the proof in milliseconds. |
metadata.proof_size_bytes | number | Size of the proof in bytes. |
metadata.security_level | number | Security level in bits (96-bit). |
Privacy Guarantee
Individual observation values are never included in the response. The proof attests to the statistical properties (EWMA within control limits) without revealing the underlying data. This is the Prove-Don't-Share architecture.
Verify Proof
POST /v1/verify
Verifies a previously generated STARK proof. Verification confirms that the proof was correctly generated and that the public inputs are authentic. Verification is always free and does not count against your monthly proof limit.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
proof_bytes | string | Yes | Base64-encoded STARK proof from the /v1/prove response. |
public_inputs | object | Yes | The public_inputs object from the prove response. |
Example Request
# Verify a previously generated proof curl -X POST https://api.starksentinel.com/v1/verify \ -H "X-API-Key: $SENTINEL_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "proof_bytes": "base64-encoded-stark-proof...", "public_inputs": { "num_observations": 8, "baseline_mean": 96, "final_ewma": 95, "ucl": 110, "lcl": 80, "within_limits": true } }'
Example Response
{
"valid": true,
"public_inputs": {
"num_observations": 8,
"baseline_mean": 96,
"final_ewma": 95,
"ucl": 110,
"lcl": 80,
"within_limits": true
},
"metadata": {
"verification_time_ms": 2
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
valid | boolean | true if the proof is cryptographically valid. |
public_inputs | object | Echo of the public inputs verified against the proof. |
metadata.verification_time_ms | number | Time to verify the proof in milliseconds. |
Client-Side Verification
For zero-trust verification, use the open-source WASM verifier. It runs entirely client-side — no network calls, no trust in SENTINEL required. See the Quickstart Guide for setup instructions.
Error Codes
SENTINEL uses standard HTTP status codes. Error responses include a JSON body with a message field.
| Code | Meaning | Common Cause |
|---|---|---|
400 | Bad Request | Missing or invalid fields in the request body. Check that observations is a non-empty array and ucl > lcl. |
401 | Unauthorized | Missing or invalid X-API-Key header. |
429 | Too Many Requests | Monthly proof limit exceeded for your tier. Upgrade your plan or wait for the next billing cycle. |
500 | Internal Server Error | Unexpected server error. Retry with exponential backoff. If persistent, contact support. |
Error Response Format
{
"error": "Bad Request",
"message": "observations must be a non-empty array of numbers"
}
Rate Limits
Rate limits are based on your plan tier and apply to proof generation only. Verification calls and health checks are unlimited.
| Tier | Proofs per Month | Requests per Second |
|---|---|---|
| Free | 100 | 5 |
| Pro | 5,000 | 50 |
| Enterprise | Unlimited | Custom |
When you exceed your monthly limit, subsequent /v1/prove calls return 429 Too Many Requests. Rate limit headers are included in every response:
X-RateLimit-Limit: 100 X-RateLimit-Remaining: 42 X-RateLimit-Reset: 2026-05-01T00:00:00Z