HELIX Verify
Deterministic, auditable verification for generative output. Submit structured facts and a rule set; receive a signed pass/fail verdict with the reason for every rule. Verdicts are reproducible and tamper-evident.
How it works
HELIX verifies facts against rules. You describe what a piece of content contains as structured facts, you describe the constraints it must satisfy, and HELIX returns a verdict together with a signed certificate. It is a checker, not a generator: it does not produce or alter content, and it does not evaluate your content directly. It evaluates the facts you or your extraction step provide about that content.
There are two request paths:
| Endpoint | Input | Use when |
|---|---|---|
/v1/check | pre-extracted facts + rules | Your own system already knows what the content contains. Deterministic, no extraction step. |
/v1/verify | raw text + a named extractor + rules | You want HELIX to derive the facts from text on your behalf (for example, PII detection). |
Authentication
Send your API key in the X-API-Key header on every request. All traffic is served
over HTTPS; plaintext HTTP is not offered.
X-API-Key: your-api-key
Requests without a valid key are rejected with 401 before any processing occurs.
Keys are issued per partner and can be revoked independently.
Quickstart
Confirm connectivity:
curl https://verify.kuriakeplayground.online/v1/health
# {"status":"ok","engine_version":"1.0.0","deterministic":true,"configured":true}
Submit your first check:
curl -X POST https://verify.kuriakeplayground.online/v1/check \
-H "X-API-Key: your-api-key" -H "Content-Type: application/json" \
-d '{
"ruleset_id": "brand-safety",
"ruleset_version": "1.0",
"rules": [
{"id":"one_product","kind":"count","subject":"product","value":1},
{"id":"no_text","kind":"absent","target":"text"}
],
"observation": {"counts": {"product": 2}, "contains": ["text"]}
}'
Guide: verifying text
Submit raw text to /v1/verify and name an extractor. The built-in
pii-regex-v1 extractor identifies contact information in the text; your rules
decide what is permitted.
curl -X POST https://verify.kuriakeplayground.online/v1/verify \
-H "X-API-Key: your-api-key" -H "Content-Type: application/json" \
-d '{
"extractor": "pii-regex-v1",
"content": "Questions? Email support@acme.com",
"rules": [
{"id":"no_email","kind":"absent","target":"email"},
{"id":"no_phone","kind":"absent","target":"phone"}
]
}'
# -> verdict: "fail", violation no_email: 'email' present but must be absent
pii-regex-v1support [at] acme [dot] com, homoglyph domains, spaced-out digits) and formats
outside those classes (for example international dialling formats) will not match. Where you
need semantic or adversarial detection, run your own classifier and submit its findings to
/v1/check, where the determinism guarantee applies to the rule evaluation
rather than to the detection step.Guide: verifying images
HELIX judges facts about an image, not the pixels themselves. There is no image upload endpoint. The intended flow:
- Your generation model produces an image.
- Your vision step (object detector, OCR, classifier, or similar) produces an
observation - for example
{"counts":{"product":1}, "contains":["logo"]}. - You submit that observation to /v1/check together with your policy.
- Use
verdictto gate or route the content; retaincertificatefor your audit trail.
Example policy: exactly one product, no visible text, brand mark required.
{
"ruleset_id": "brand-safety", "ruleset_version": "1.0",
"rules": [
{"id":"one_product","kind":"count","subject":"product","value":1},
{"id":"no_text","kind":"absent","target":"text"},
{"id":"has_logo","kind":"present","target":"logo"}
],
"observation": {"counts":{"product":1}, "contains":["logo"]}
}
A runnable example, including a sample vision step, is provided in the evaluation kit.
Certificates
Every response includes a signed certificate. Treat it as your compliance record and store it in full.
| Field | Meaning |
|---|---|
verification_id | Unique identifier for this verification, for your own audit log. |
input_sha256 | Hash of the exact inputs evaluated. Identical inputs produce an identical hash. |
signature | HMAC-SHA256 over the verdict and metadata, proving the certificate was issued by this service and has not been altered. |
ruleset_id / ruleset_version | The policy identifier and version that produced this verdict. |
extraction | Which extractor produced the facts (none for /v1/check), and whether that extractor is deterministic. |
issued_at | UTC timestamp of issuance, ISO 8601. |
Two calls with identical inputs will always produce the same input_sha256; each
still receives its own verification_id and issued_at, since each call is
a distinct, independently signed event.
Reference
POST /v1/check
Verify pre-extracted facts against rules. Fully deterministic; does not invoke any extraction step.
Request body
| Field | Type | Notes |
|---|---|---|
rules | array | 1 to 200 rules. See rule vocabulary. |
observation | object | The facts to evaluate. See observation object. |
ruleset_id | string | Optional label identifying your policy. |
ruleset_version | string | Optional version of that policy. |
Response
{
"verdict": "fail",
"passed": 1, "total": 2,
"results": [
{"id":"one_product","kind":"count","ok":false,"reason":"need 1 'product'; observed 2"},
{"id":"no_text","kind":"absent","ok":true,"reason":"'text' absent as required"}
],
"violations": [ "...the failing rules..." ],
"certificate": { "verification_id":"vrf_...", "signature":"...", "..." : "..." }
}
POST /v1/verify
Extract facts from raw text using a named extractor, then verify those facts against rules in a single call.
| Field | Type | Notes |
|---|---|---|
extractor | string | An identifier returned by /v1/extractors, for example pii-regex-v1. |
content | string | The text to inspect. Maximum 64 KB. |
rules | array | Same format as /v1/check. |
The response shape matches /v1/check. The certificate's
extraction.deterministic field is true for rule-based extractors and
false for model-based ones, so a verdict's reproducibility is always explicit
rather than assumed.
POST /v1/certificates/verify
Confirm that a previously issued verdict is authentic and unaltered. Post the stored
response back verbatim; results and violations are accepted but are
not part of the signature.
curl -X POST https://verify.kuriakeplayground.online/v1/certificates/verify \
-H "X-API-Key: your-api-key" -H "Content-Type: application/json" \
-d @stored-response.json
# {"valid": true, "verification_id": "vrf_..."}
| Field | Type | Notes |
|---|---|---|
verdict | string | pass or fail, exactly as issued. |
passed / total | integer | As issued. |
certificate | object | The complete certificate object, unmodified. |
Returns {"valid": false} if any signed field has been changed. Comparison is
constant-time. A false result is a definitive answer, not an error, so the status
code is 200 in both cases.
GET /v1/extractors
List extractors available to /v1/verify, and whether each is deterministic.
Requires authentication.
{"extractors":[
{"id":"pii-regex-v1","deterministic":true},
{"id":"llm-classifier-v1","deterministic":false}
]}
GET /v1/health
Liveness probe. Does not require authentication, performs no verification, and is not
rate limited. HEAD is supported alongside GET for uptime monitors.
{"status":"ok","engine_version":"1.0.0","deterministic":true,"configured":true}
Rule vocabulary
Rules are drawn from a closed, fixed set of kinds; there is no expression language and no
facility for arbitrary logic. Every rule carries an id that you choose (letters,
digits, _ - ., maximum 128 characters) so results can be mapped back to your policy.
| kind | fields | passes when |
|---|---|---|
count | subject, value | counts[subject] == value |
absent | target | target not present in contains |
present | target | target present in contains |
equals | field, value | fields[field] == value |
one_of | field, values | fields[field] is a member of values |
Observation object
The structured facts produced by your extractor or vision step:
| Key | Type | Example |
|---|---|---|
counts | object, name to integer | {"product": 1} |
contains | array of tokens | ["logo","neon"] |
fields | object, name to string | {"style":"photoreal"} |
Any field not listed above is rejected by the schema rather than silently ignored, so
malformed observations fail fast with a 422.
Integers are validated strictly: "1" and true are rejected with a
422 rather than coerced to 1. Identifiers have surrounding whitespace
trimmed before the pattern is applied, so "product " and "product" are
the same identifier and produce the same input_sha256.
reason stringsreason quotes the identifiers and values from your request so a
failure is self-explanatory in a log. Values you supply are therefore reflected back in the
response. They are correctly JSON-encoded, but if you render reason into an HTML
dashboard, escape it as you would any other untrusted string.Errors
Every error response has the same shape, {"error": "..."}, regardless of which
layer produced it - including errors raised at the edge before the request reaches the
application. This is safe to log verbatim: no stack traces, file paths, or other internal detail
are ever included in a response body.
| Status | Meaning |
|---|---|
401 | Missing or invalid API key. |
400 | Unknown extractor named in a /v1/verify request. |
413 | Request body exceeds the size limit. Rejected before parsing. |
422 | Request failed schema validation - unknown rule kind, unexpected field, invalid identifier, or too many rules. |
429 | Rate limit exceeded for this key. Back off and retry. |
500 | Unexpected server-side error. Not expected in normal operation; report the verification_id if one is present, or the approximate request time if not. |
503 | Service temporarily unavailable. Retry with backoff. |
Limits
- Request body: 64 KB maximum, enforced at the edge before the body is parsed. The cap
applies to chunked requests as well as those declaring a
Content-Length. - Rules per request: 200 maximum.
- Identifiers (
id,subject,target,field): pattern^[A-Za-z0-9_\-.]+$, 128 characters maximum. - Per-key request rate: fixed per your onboarding agreement. On
429, back off and retry; sustained excess is not queued.
Versioning
The API is versioned in the URL path (/v1/...). Within a major version, fields
are only ever added, never removed or repurposed; treat unrecognized response fields as
forward-compatible and ignore them rather than rejecting the response. A breaking change will be
introduced under a new path prefix (/v2/...), never in place.
Security and privacy
- Stateless. No request content, facts, or verdicts are persisted by the service.
- No image ingestion. There is no endpoint that accepts image data; only derived facts are submitted.
- Signed verdicts. Every certificate is tamper-evident (HMAC-SHA256); altering any field invalidates the signature.
- Deterministic core. Given identical facts and rules, the verdict is always identical.
- All traffic is served over HTTPS. API keys are issued per partner and can be revoked without affecting other keys.
Evaluation kit
A small, self-contained script bundle that exercises this API end to end for both text and
image verification, including a reference vision step for the image example, so the full flow can
be inspected without writing integration code first. Set your endpoint URL and API key as
environment variables, then run text_test.py and image_test.py. Provided
separately alongside your API key.