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.

API version v1
Engine 1.0.0
Transport HTTPS only
Response format application/json

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:

EndpointInputUse when
/v1/checkpre-extracted facts + rulesYour own system already knows what the content contains. Deterministic, no extraction step.
/v1/verifyraw text + a named extractor + rulesYou want HELIX to derive the facts from text on your behalf (for example, PII detection).
Where do the facts come from?
For text, HELIX can extract them for you through /v1/verify. For images, your own vision model or pipeline produces the facts (object counts, detected text, brand marks, and so on) and you submit them to /v1/check. HELIX does not accept image uploads and never receives raw image data; only the facts your extraction step produced. See Verifying images.

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
Scope of pii-regex-v1
This extractor matches literal, well-formed patterns: conventional email addresses, 10-digit North American phone numbers, and US SSNs. It is deliberately pattern-based rather than model-based, which is what makes its verdicts reproducible and ReDoS-free - but it is a detector for accidental disclosure, not an adversary-resistant filter. Deliberately obfuscated content (support [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:

  1. Your generation model produces an image.
  2. Your vision step (object detector, OCR, classifier, or similar) produces an observation - for example {"counts":{"product":1}, "contains":["logo"]}.
  3. You submit that observation to /v1/check together with your policy.
  4. Use verdict to gate or route the content; retain certificate for your audit trail.
HELIX never receives the image itself, only the facts your vision step derived from it. Image content does not leave your environment.

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.

FieldMeaning
verification_idUnique identifier for this verification, for your own audit log.
input_sha256Hash of the exact inputs evaluated. Identical inputs produce an identical hash.
signatureHMAC-SHA256 over the verdict and metadata, proving the certificate was issued by this service and has not been altered.
ruleset_id / ruleset_versionThe policy identifier and version that produced this verdict.
extractionWhich extractor produced the facts (none for /v1/check), and whether that extractor is deterministic.
issued_atUTC 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.

How to check a stored certificate
Signatures are HMAC-SHA256, which is symmetric: verification requires the signing key, so a certificate cannot be validated offline by the holder. Post a stored response back to /v1/certificates/verify and the service performs the check and returns a boolean. Any alteration to the verdict, counts, or certificate fields causes verification to fail.

Reference

POST /v1/check

Verify pre-extracted facts against rules. Fully deterministic; does not invoke any extraction step.

Request body

FieldTypeNotes
rulesarray1 to 200 rules. See rule vocabulary.
observationobjectThe facts to evaluate. See observation object.
ruleset_idstringOptional label identifying your policy.
ruleset_versionstringOptional 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.

FieldTypeNotes
extractorstringAn identifier returned by /v1/extractors, for example pii-regex-v1.
contentstringThe text to inspect. Maximum 64 KB.
rulesarraySame 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_..."}
FieldTypeNotes
verdictstringpass or fail, exactly as issued.
passed / totalintegerAs issued.
certificateobjectThe 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.

kindfieldspasses when
countsubject, valuecounts[subject] == value
absenttargettarget not present in contains
presenttargettarget present in contains
equalsfield, valuefields[field] == value
one_offield, valuesfields[field] is a member of values

Observation object

The structured facts produced by your extractor or vision step:

KeyTypeExample
countsobject, name to integer{"product": 1}
containsarray of tokens["logo","neon"]
fieldsobject, 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.

Escaping in reason strings
Each result's reason 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.

StatusMeaning
401Missing or invalid API key.
400Unknown extractor named in a /v1/verify request.
413Request body exceeds the size limit. Rejected before parsing.
422Request failed schema validation - unknown rule kind, unexpected field, invalid identifier, or too many rules.
429Rate limit exceeded for this key. Back off and retry.
500Unexpected server-side error. Not expected in normal operation; report the verification_id if one is present, or the approximate request time if not.
503Service temporarily unavailable. Retry with backoff.

Limits

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

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.

HELIX Verify - API v1 - This document describes the public interface only.