Get started
Quickstart
Send the prompt before you generate anything. Vindex checks it against your policy and answers allow, review or block. That call is the whole integration.
Five lines
Create a test key in the dashboard, under API keys. It starts with vx_test_. Put it in the first line, then run all five:
export VINDEX_KEY=vx_test_...
curl https://api.getvindex.com/v1/check \
-H "Authorization: Bearer $VINDEX_KEY" \
-H "Content-Type: application/json" \
-d '{"input": {"prompt": "a lighthouse at dusk, oil painting"}}'That's a real decision against your default policy, logged in the dashboard under test mode.
The response
{
"id": "dec_8c1187e9ea1a4b04a5adb40f19868d19",
"outcome": "allow",
"tags": [],
"checks": {
"minors_sexual": {
"score": 0.0085,
"review_score": 0.01,
"fired": []
},
"adult": {
"score": 0.01,
"review_score": 0.01,
"fired": []
},
"real_person": {
"score": 0.01,
"review_score": 0.01,
"fired": []
},
"copyrighted_ip": {
"score": 0.02,
"review_score": 0.02,
"fired": []
}
},
"policy": {
"id": "pol_cb805d8999bd453f8f2b0ffd04f05b59",
"version": 1
},
"engine_version": "2026.09",
"latency_ms": 383,
"dry_run": false,
"mode": "test",
"shadow_mode": false
}Line by line:
id: this decision. Fetch it again withGET /v1/decisions/{id}, or ask why it came out this way with/explain.outcome:allow,revieworblock. The one field your app has to act on (Decisions).tags: labels your policy attached, likeadult. A tag never blocks anything on its own.checks: one entry per check your policy runs (Checks).score: how likely, from 0 to 1, the prompt is what this check looks for. Compared with the policy's act line.review_score: compared with the review line. Usually the same number.fired: the signals that crossed their own line. Empty on a clean prompt.
policy: the policy and version that decided. Your default, because the request didn't name one.engine_version: an opaque id for the screening engine version that decided this.latency_ms: milliseconds from the request arriving to the decision.dry_run:false, so this decision counts (Dry-run).mode:test, because a test key made it (API keys & modes).shadow_mode:truewhile your workspace is in shadow mode, when nothing is acted on yet. Workspaces made in the dashboard start that way (Shadow mode).
In your code
curl https://api.getvindex.com/v1/check \
-H "Authorization: Bearer $VINDEX_KEY" \
-H "Content-Type: application/json" \
-d '{"input": {"prompt": "a lighthouse at dusk, oil painting"}}'// check.mjs · Node 18+ · VINDEX_KEY=vx_test_... node check.mjs
const res = await fetch("https://api.getvindex.com/v1/check", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.VINDEX_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ input: { prompt: "a lighthouse at dusk, oil painting" } }),
});
if (!res.ok) throw new Error(`Vindex ${res.status}: ${await res.text()}`);
const decision = await res.json();
console.log(decision.outcome); // "allow" | "review" | "block"# check.py · pip install requests · VINDEX_KEY=vx_test_... python check.py
import os
import requests
res = requests.post(
"https://api.getvindex.com/v1/check",
headers={"Authorization": f"Bearer {os.environ['VINDEX_KEY']}"},
json={"input": {"prompt": "a lighthouse at dusk, oil painting"}},
timeout=10,
)
res.raise_for_status()
decision = res.json()
print(decision["outcome"]) # "allow" | "review" | "block"Try it here
Paste your test key and a prompt of your own.
Try a prompt
No key: sample responseYES · allowSample · "a lighthouse at dusk, oil painting"
Allowed: no check reached its review line.
- Minors, sexual0.01nothing to do
- Adult content0.01nothing to do
- Real people0.01nothing to do
- Copyrighted IP0.02nothing to do
Response JSON
{
"id": "dec_8c1187e9ea1a4b04a5adb40f19868d19",
"outcome": "allow",
"tags": [],
"checks": {
"minors_sexual": {
"score": 0.0085,
"review_score": 0.01,
"fired": []
},
"adult": {
"score": 0.01,
"review_score": 0.01,
"fired": []
},
"real_person": {
"score": 0.01,
"review_score": 0.01,
"fired": []
},
"copyrighted_ip": {
"score": 0.02,
"review_score": 0.02,
"fired": []
}
},
"policy": {
"id": "pol_cb805d8999bd453f8f2b0ffd04f05b59",
"version": 1
},
"engine_version": "2026.09",
"latency_ms": 383,
"dry_run": false,
"mode": "test",
"shadow_mode": false
}If it fails
401 unauthorized: the key is missing, mistyped or revoked.422 no_default_policy: the workspace has no policy yet. Create one from a preset withPOST /v1/policiesand{"preset": "adult-platform"}(Policies & presets).503 screening_unavailable: the screening engine couldn't be reached, so nothing was decided. Retry after theRetry-Afterheader's seconds (Rate limits & errors).