Concepts
Policies & presets
A policy is your content rules as one JSON document: for each check, two lines and an action for each. Every workspace has a default policy, and a check uses it unless the request names another.
The shape
One check's rule, from the adult-platform preset:
"adult": {
"act": 0.7,
"review": 0.35,
"on_act": { "type": "tag", "tag": "adult" },
"on_review": { "type": "tag", "tag": "adult-review" }
}actandreview: the two lines, from 0 to 1, withreviewat or belowact(Checks).on_actandon_review: what happens at each line.{"type": "block"},{"type": "review"},{"type": "allow"}, or{"type": "tag", "tag": "…"}, which allows and labels.enabled:falseswitches a check off and keeps its lines for later. Optional; checks are on by default.
Around the checks, the document has:
adult.max_level: the highest adult level allowed, 1 to 5. Anything above takes the adult check'son_act(the adult scale).youth_coded_adult:"review"or"block", for someone stated to be an adult but presented young.webhooks: who to call, for which outcomes (Webhooks).tags: the tags this policy may apply, with a description each. Once you list any, every tag action has to use one of them.version(always1, the document format) andname.
Presets
Four starting points, one per kind of platform. Each cell is the act line and its action, then the review line and its action. These come straight from the preset files the API loads.
| Check | adult-platform | chat-assistant | stock-imagery | family-app |
|---|---|---|---|---|
| Minors, sexualminors_sexual | ≥ 0.50 block≥ 0.30 review | ≥ 0.50 block≥ 0.30 block | ≥ 0.50 block≥ 0.30 block | ≥ 0.50 block≥ 0.30 block |
| Adult contentadult | ≥ 0.70 tag adult≥ 0.35 tag adult-review | ≥ 0.50 block≥ 0.30 review | ≥ 0.50 block≥ 0.30 review | ≥ 0.35 block≥ 0.20 review |
| Real peoplereal_person | ≥ 0.50 review≥ 0.30 tag real-person | off | ≥ 0.50 block≥ 0.30 review | ≥ 0.30 review≥ 0.15 tag real-person |
| Copyrighted IPcopyrighted_ip | ≥ 0.50 tag ip≥ 0.30 tag ip-review | off | ≥ 0.40 block≥ 0.20 review | ≥ 0.30 review≥ 0.15 tag ip |
| Adult level allowedadult.max_level | up to 5 of 5 | up to 1 of 5 | up to 2 of 5 | up to 1 of 5 |
| Youth-coded adultsyouth_coded_adult | review | block | block | block |
adult-platform: adults are adults. Adult content is tagged, never blocked; real people go to review.chat-assistant: no adult content. Real people and copyrighted characters aren't checked.stock-imagery: anything that could be a licensing or likeness problem is blocked or reviewed.family-app: the lowest lines. Adult content is blocked at 0.35.
Start from one with POST /v1/policies and {"preset": "family-app"}. GET /v1/presets returns all four in full.
What no policy can change
The API refuses a document that breaks any of these, with 422 invalid_policy and one line per problem in issues:
minors_sexualis in every policy, enabled, withact0.50 blocking andreview0.30 reviewing or blocking.- At
adult.max_level5, the adult check may tag or review, not block. - A tag action uses a tag from
tags, if the policy lists any. - A webhook has an
https://URL on a public domain name (not an IP address,localhost, a.localor.internalname,*.workers.devor a Vindex address), at least one event, and a secret of 16 characters or more. Publishing checks the version again, so a version saved before a rule existed can't go live.
{
"type": "https://api.getvindex.com/problems/invalid_policy",
"title": "Invalid policy",
"status": 422,
"detail": "The policy document failed validation.",
"code": "invalid_policy",
"issues": [
"checks.minors_sexual.act: must be 0.5 — not overridable",
"checks.adult.on_act: must not be {type: \"block\"} when adult.max_level is 5 — use tag or review"
]
}Versions
A policy changes by adding a version, never by editing one. Every decision records the policy.id and policy.version that made it.
# 1. A new version: validated and stored, not live yet.
curl -X POST "https://api.getvindex.com/v1/policies/$POLICY_ID/versions" \
-H "Authorization: Bearer $VINDEX_KEY" \
-H "Content-Type: application/json" \
-d @policy.json
# 2. Try it on real prompts without enforcing anything.
curl https://api.getvindex.com/v1/check \
-H "Authorization: Bearer $VINDEX_KEY" \
-H "Content-Type: application/json" \
-H "X-Vindex-Dry-Run: true" \
-d '{"input": {"prompt": "a lighthouse at dusk, oil painting"}, "policy": "'"$POLICY_ID"'", "policy_version": 2}'
# 3. Publish it.
curl -X POST "https://api.getvindex.com/v1/policies/$POLICY_ID/publish" \
-H "Authorization: Bearer $VINDEX_KEY" \
-H "Content-Type: application/json" \
-d '{"version": 2}'A published version reaches every check within about a minute, five at most. Publishing an older version rolls back.
GET /v1/policies/{id} returns the current document and every version. Webhook secrets read back as "redacted", and sending "redacted" in a new version keeps the stored secret.
Default policy
A workspace's first policy becomes its default. POST /v1/policies/{id}/default switches it; so does "default": true when creating one. To screen against another policy, name it in the check: "policy": "pol_…".