VindexDocs

API reference

Policies

Policies, their versions and the shipped presets.

List policies

GET/v1/policies

Request

cURL
curl "https://api.getvindex.com/v1/policies" \
  -H "Authorization: Bearer $VINDEX_KEY"

Response 200

Every policy of the tenant, newest first.

Example
{
  "data": [
    {
      "id": "pol_3f2a0c9e8b7d4c6a9f1e2d3c4b5a6978",
      "name": "adult-platform",
      "preset": "adult-platform",
      "current_version": 1,
      "default": true,
      "dry_run_version": null,
      "created_at": "2026-09-17T08:51:06.000Z"
    }
  ]
}

Errors

  • 400Invalid request (malformed JSON, or the body/query failed validation).
  • 401Missing, malformed, unknown or revoked API key.
  • 429Rate limit exceeded for this API key. See Retry-After.

Create a policy from a preset or a document

POST/v1/policies

Creates the policy with version 1 published. The tenant's first policy becomes its default. Starter includes one policy.

Body

  • namestring

    Defaults to the preset's or document's name. 1–120 chars

  • presetstring

    Start from a preset (GET /v1/presets). Exactly one of preset and policy.

  • policyPolicyDocument
  • policy.version1required
  • policy.namestringrequired
  • policy.checksmap of PolicyCheckRulerequired

    Per check id (minors_sexual, adult, real_person, copyrighted_ip). minors_sexual is required and pinned: act 0.5, review 0.3, on_act block.

  • policy.checks.{key}.enabledboolean
  • policy.checks.{key}.actnumberrequired

    0–1

  • policy.checks.{key}.reviewnumberrequired

    0–1

  • policy.checks.{key}.on_actActionrequired
  • policy.checks.{key}.on_reviewActionrequired
  • policy.adultobjectrequired

    Highest adult level (1–5) allowed before checks.adult.on_act applies. Interim fixed 0.2-wide bands over the adult score, pending issue #10.

  • policy.adult.max_levelintegerrequired

    1–5

  • policy.youth_coded_adult"review" | "block"required
  • policy.webhooksobject[]required
  • policy.webhooks[].urlstringrequired
  • policy.webhooks[].events"block" | "review" | "allow" | "tag" | "review.verdict"[]required
  • policy.webhooks[].secretstringrequired

    HMAC-SHA256 signing secret, at least 16 characters. Write-only: reads return "redacted", and sending "redacted" back keeps the stored secret for that url.

  • policy.tagsmap of objectrequired
  • policy.tags.{key}.descriptionstring
  • defaultboolean

    Make this the tenant's default policy. A tenant's first policy always becomes the default.

Request

cURL
curl -X POST "https://api.getvindex.com/v1/policies" \
  -H "Authorization: Bearer $VINDEX_KEY" \
  -H "Content-Type: application/json" \
  -d '{"preset":"adult-platform"}'

Response 201

Created.

Example
{
  "id": "pol_3f2a0c9e8b7d4c6a9f1e2d3c4b5a6978",
  "name": "adult-platform",
  "preset": "adult-platform",
  "current_version": 1,
  "default": true,
  "dry_run_version": null,
  "created_at": "2026-09-17T08:51:06.000Z",
  "policy": {
    "version": 1,
    "name": "adult-platform",
    "checks": {
      "minors_sexual": {
        "act": 0.5,
        "review": 0.3,
        "on_act": {
          "type": "block"
        },
        "on_review": {
          "type": "review"
        }
      },
      "adult": {
        "act": 0.7,
        "review": 0.35,
        "on_act": {
          "type": "tag",
          "tag": "adult"
        },
        "on_review": {
          "type": "tag",
          "tag": "adult-review"
        }
      },
      "real_person": {
        "act": 0.5,
        "review": 0.3,
        "on_act": {
          "type": "review"
        },
        "on_review": {
          "type": "tag",
          "tag": "real-person"
        }
      },
      "copyrighted_ip": {
        "act": 0.5,
        "review": 0.3,
        "on_act": {
          "type": "tag",
          "tag": "ip"
        },
        "on_review": {
          "type": "tag",
          "tag": "ip-review"
        }
      }
    },
    "adult": {
      "max_level": 5
    },
    "youth_coded_adult": "review",
    "webhooks": [],
    "tags": {
      "adult": {
        "description": "NSFW: nudity or sexual content, auto-tagged, not blocked"
      },
      "adult-review": {
        "description": "borderline NSFW, below the adult act threshold"
      },
      "real-person": {
        "description": "a specific real, identifiable person is depicted"
      },
      "ip": {
        "description": "references copyrighted or trademarked material"
      },
      "ip-review": {
        "description": "borderline IP reference, below the act threshold"
      }
    }
  },
  "versions": [
    {
      "version": 1,
      "current": true,
      "created_at": "2026-09-17T08:51:06.000Z",
      "created_by": null
    }
  ]
}

Errors

  • 400Invalid request (malformed JSON, or the body/query failed validation).
  • 401Missing, malformed, unknown or revoked API key.
  • 402The plan's policies are all used (plan_required, limit: policies), or the plan has ended (subscription_inactive).
  • 422The document failed policy validation (invalid_policy, with issues), or the preset doesn't exist.
  • 429Rate limit exceeded for this API key. See Retry-After.

Get a policy, its current document and its versions

GET/v1/policies/{id}

Parameters

  • idstringpathrequired

    Policy id 1–64 chars

Request

cURL
curl "https://api.getvindex.com/v1/policies/$POLICY_ID" \
  -H "Authorization: Bearer $VINDEX_KEY"

Response 200

The policy.

Example
{
  "id": "pol_3f2a0c9e8b7d4c6a9f1e2d3c4b5a6978",
  "name": "adult-platform",
  "preset": "adult-platform",
  "current_version": 1,
  "default": true,
  "dry_run_version": null,
  "created_at": "2026-09-17T08:51:06.000Z",
  "policy": {
    "version": 1,
    "name": "adult-platform",
    "checks": {
      "minors_sexual": {
        "act": 0.5,
        "review": 0.3,
        "on_act": {
          "type": "block"
        },
        "on_review": {
          "type": "review"
        }
      },
      "adult": {
        "act": 0.7,
        "review": 0.35,
        "on_act": {
          "type": "tag",
          "tag": "adult"
        },
        "on_review": {
          "type": "tag",
          "tag": "adult-review"
        }
      },
      "real_person": {
        "act": 0.5,
        "review": 0.3,
        "on_act": {
          "type": "review"
        },
        "on_review": {
          "type": "tag",
          "tag": "real-person"
        }
      },
      "copyrighted_ip": {
        "act": 0.5,
        "review": 0.3,
        "on_act": {
          "type": "tag",
          "tag": "ip"
        },
        "on_review": {
          "type": "tag",
          "tag": "ip-review"
        }
      }
    },
    "adult": {
      "max_level": 5
    },
    "youth_coded_adult": "review",
    "webhooks": [],
    "tags": {
      "adult": {
        "description": "NSFW: nudity or sexual content, auto-tagged, not blocked"
      },
      "adult-review": {
        "description": "borderline NSFW, below the adult act threshold"
      },
      "real-person": {
        "description": "a specific real, identifiable person is depicted"
      },
      "ip": {
        "description": "references copyrighted or trademarked material"
      },
      "ip-review": {
        "description": "borderline IP reference, below the act threshold"
      }
    }
  },
  "versions": [
    {
      "version": 1,
      "current": true,
      "created_at": "2026-09-17T08:51:06.000Z",
      "created_by": null
    }
  ]
}

Errors

  • 400Invalid request (malformed JSON, or the body/query failed validation).
  • 401Missing, malformed, unknown or revoked API key.
  • 404No such policy (or version) for this tenant.
  • 429Rate limit exceeded for this API key. See Retry-After.

Add a new (unpublished) version

POST/v1/policies/{id}/versions

Validates the document and stores it as the next version. It takes effect only once published.

Parameters

  • idstringpathrequired

    Policy id 1–64 chars

Body

  • version1required
  • namestringrequired
  • checksmap of PolicyCheckRulerequired

    Per check id (minors_sexual, adult, real_person, copyrighted_ip). minors_sexual is required and pinned: act 0.5, review 0.3, on_act block.

  • checks.{key}.enabledboolean
  • checks.{key}.actnumberrequired

    0–1

  • checks.{key}.reviewnumberrequired

    0–1

  • checks.{key}.on_actActionrequired
  • checks.{key}.on_reviewActionrequired
  • adultobjectrequired

    Highest adult level (1–5) allowed before checks.adult.on_act applies. Interim fixed 0.2-wide bands over the adult score, pending issue #10.

  • adult.max_levelintegerrequired

    1–5

  • youth_coded_adult"review" | "block"required
  • webhooksobject[]required
  • webhooks[].urlstringrequired
  • webhooks[].events"block" | "review" | "allow" | "tag" | "review.verdict"[]required
  • webhooks[].secretstringrequired

    HMAC-SHA256 signing secret, at least 16 characters. Write-only: reads return "redacted", and sending "redacted" back keeps the stored secret for that url.

  • tagsmap of objectrequired
  • tags.{key}.descriptionstring

Request

cURL
curl -X POST "https://api.getvindex.com/v1/policies/$POLICY_ID/versions" \
  -H "Authorization: Bearer $VINDEX_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "version": 1,
  "name": "adult-platform",
  "checks": {
    "minors_sexual": {
      "act": 0.5,
      "review": 0.3,
      "on_act": {
        "type": "block"
      },
      "on_review": {
        "type": "review"
      }
    },
    "adult": {
      "act": 0.7,
      "review": 0.35,
      "on_act": {
        "type": "tag",
        "tag": "adult"
      },
      "on_review": {
        "type": "tag",
        "tag": "adult-review"
      }
    },
    "real_person": {
      "act": 0.5,
      "review": 0.3,
      "on_act": {
        "type": "review"
      },
      "on_review": {
        "type": "tag",
        "tag": "real-person"
      }
    },
    "copyrighted_ip": {
      "act": 0.5,
      "review": 0.3,
      "on_act": {
        "type": "tag",
        "tag": "ip"
      },
      "on_review": {
        "type": "tag",
        "tag": "ip-review"
      }
    }
  },
  "adult": {
    "max_level": 5
  },
  "youth_coded_adult": "review",
  "webhooks": [],
  "tags": {
    "adult": {
      "description": "NSFW: nudity or sexual content, auto-tagged, not blocked"
    },
    "adult-review": {
      "description": "borderline NSFW, below the adult act threshold"
    },
    "real-person": {
      "description": "a specific real, identifiable person is depicted"
    },
    "ip": {
      "description": "references copyrighted or trademarked material"
    },
    "ip-review": {
      "description": "borderline IP reference, below the act threshold"
    }
  }
}'

Response 201

The new version.

Example
{
  "policy_id": "pol_3f2a0c9e8b7d4c6a9f1e2d3c4b5a6978",
  "version": 1,
  "current": true,
  "policy": {
    "version": 1,
    "name": "adult-platform",
    "checks": {
      "minors_sexual": {
        "act": 0.5,
        "review": 0.3,
        "on_act": {
          "type": "block"
        },
        "on_review": {
          "type": "review"
        }
      },
      "adult": {
        "act": 0.7,
        "review": 0.35,
        "on_act": {
          "type": "tag",
          "tag": "adult"
        },
        "on_review": {
          "type": "tag",
          "tag": "adult-review"
        }
      },
      "real_person": {
        "act": 0.5,
        "review": 0.3,
        "on_act": {
          "type": "review"
        },
        "on_review": {
          "type": "tag",
          "tag": "real-person"
        }
      },
      "copyrighted_ip": {
        "act": 0.5,
        "review": 0.3,
        "on_act": {
          "type": "tag",
          "tag": "ip"
        },
        "on_review": {
          "type": "tag",
          "tag": "ip-review"
        }
      }
    },
    "adult": {
      "max_level": 5
    },
    "youth_coded_adult": "review",
    "webhooks": [],
    "tags": {
      "adult": {
        "description": "NSFW: nudity or sexual content, auto-tagged, not blocked"
      },
      "adult-review": {
        "description": "borderline NSFW, below the adult act threshold"
      },
      "real-person": {
        "description": "a specific real, identifiable person is depicted"
      },
      "ip": {
        "description": "references copyrighted or trademarked material"
      },
      "ip-review": {
        "description": "borderline IP reference, below the act threshold"
      }
    }
  }
}

Errors

  • 400Invalid request (malformed JSON, or the body/query failed validation).
  • 401Missing, malformed, unknown or revoked API key.
  • 402The workspace's plan has ended, so it's read-only (subscription_inactive).
  • 404No such policy (or version) for this tenant.
  • 422The document failed policy validation (invalid_policy, with issues).
  • 429Rate limit exceeded for this API key. See Retry-After.

Publish a version

POST/v1/policies/{id}/publish

Makes the version current. Checks pick it up once the policy cache entry is gone everywhere: usually within ~60 s (KV is eventually consistent), at most 5 minutes if a check was caching the old version as you published.

Parameters

  • idstringpathrequired

    Policy id 1–64 chars

Body

  • versionintegerrequired

    ≥ 1

Request

cURL
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}'

Response 200

Published.

Example
{
  "id": "pol_3f2a0c9e8b7d4c6a9f1e2d3c4b5a6978",
  "name": "adult-platform",
  "preset": "adult-platform",
  "current_version": 1,
  "default": true,
  "dry_run_version": null,
  "created_at": "2026-09-17T08:51:06.000Z"
}

Errors

  • 400Invalid request (malformed JSON, or the body/query failed validation).
  • 401Missing, malformed, unknown or revoked API key.
  • 402The workspace's plan has ended, so it's read-only (subscription_inactive).
  • 404No such policy (or version) for this tenant.
  • 422The version no longer passes validation (invalid_policy, with issues), e.g. a webhook on plain http://. Save a fixed version and publish that.
  • 429Rate limit exceeded for this API key. See Retry-After.

Make a policy the tenant's default

POST/v1/policies/{id}/default

Parameters

  • idstringpathrequired

    Policy id 1–64 chars

Request

cURL
curl -X POST "https://api.getvindex.com/v1/policies/$POLICY_ID/default" \
  -H "Authorization: Bearer $VINDEX_KEY"

Response 200

Now the default.

Example
{
  "id": "pol_3f2a0c9e8b7d4c6a9f1e2d3c4b5a6978",
  "name": "adult-platform",
  "preset": "adult-platform",
  "current_version": 1,
  "default": true,
  "dry_run_version": null,
  "created_at": "2026-09-17T08:51:06.000Z"
}

Errors

  • 400Invalid request (malformed JSON, or the body/query failed validation).
  • 401Missing, malformed, unknown or revoked API key.
  • 402The workspace's plan has ended, so it's read-only (subscription_inactive).
  • 404No such policy (or version) for this tenant.
  • 429Rate limit exceeded for this API key. See Retry-After.

Get one version of a policy

GET/v1/policies/{id}/versions/{version}

Parameters

  • idstringpathrequired

    Policy id 1–64 chars

  • versionintegerpathrequired

    ≥ 1

Request

cURL
curl "https://api.getvindex.com/v1/policies/$POLICY_ID/versions/$VERSION" \
  -H "Authorization: Bearer $VINDEX_KEY"

Response 200

The version's document (webhook secrets redacted).

Example
{
  "policy_id": "pol_3f2a0c9e8b7d4c6a9f1e2d3c4b5a6978",
  "version": 1,
  "current": true,
  "policy": {
    "version": 1,
    "name": "adult-platform",
    "checks": {
      "minors_sexual": {
        "act": 0.5,
        "review": 0.3,
        "on_act": {
          "type": "block"
        },
        "on_review": {
          "type": "review"
        }
      },
      "adult": {
        "act": 0.7,
        "review": 0.35,
        "on_act": {
          "type": "tag",
          "tag": "adult"
        },
        "on_review": {
          "type": "tag",
          "tag": "adult-review"
        }
      },
      "real_person": {
        "act": 0.5,
        "review": 0.3,
        "on_act": {
          "type": "review"
        },
        "on_review": {
          "type": "tag",
          "tag": "real-person"
        }
      },
      "copyrighted_ip": {
        "act": 0.5,
        "review": 0.3,
        "on_act": {
          "type": "tag",
          "tag": "ip"
        },
        "on_review": {
          "type": "tag",
          "tag": "ip-review"
        }
      }
    },
    "adult": {
      "max_level": 5
    },
    "youth_coded_adult": "review",
    "webhooks": [],
    "tags": {
      "adult": {
        "description": "NSFW: nudity or sexual content, auto-tagged, not blocked"
      },
      "adult-review": {
        "description": "borderline NSFW, below the adult act threshold"
      },
      "real-person": {
        "description": "a specific real, identifiable person is depicted"
      },
      "ip": {
        "description": "references copyrighted or trademarked material"
      },
      "ip-review": {
        "description": "borderline IP reference, below the act threshold"
      }
    }
  }
}

Errors

  • 400Invalid request (malformed JSON, or the body/query failed validation).
  • 401Missing, malformed, unknown or revoked API key.
  • 404No such policy (or version) for this tenant.
  • 429Rate limit exceeded for this API key. See Retry-After.

List preset policies

GET/v1/presets

Request

cURL
curl "https://api.getvindex.com/v1/presets" \
  -H "Authorization: Bearer $VINDEX_KEY"

Response 200

The shipped presets.

Example
{
  "data": [
    {
      "name": "adult-platform",
      "policy": {
        "version": 1,
        "name": "adult-platform",
        "checks": {
          "minors_sexual": {
            "act": 0.5,
            "review": 0.3,
            "on_act": {
              "type": "block"
            },
            "on_review": {
              "type": "review"
            }
          },
          "adult": {
            "act": 0.7,
            "review": 0.35,
            "on_act": {
              "type": "tag",
              "tag": "adult"
            },
            "on_review": {
              "type": "tag",
              "tag": "adult-review"
            }
          },
          "real_person": {
            "act": 0.5,
            "review": 0.3,
            "on_act": {
              "type": "review"
            },
            "on_review": {
              "type": "tag",
              "tag": "real-person"
            }
          },
          "copyrighted_ip": {
            "act": 0.5,
            "review": 0.3,
            "on_act": {
              "type": "tag",
              "tag": "ip"
            },
            "on_review": {
              "type": "tag",
              "tag": "ip-review"
            }
          }
        },
        "adult": {
          "max_level": 5
        },
        "youth_coded_adult": "review",
        "webhooks": [],
        "tags": {
          "adult": {
            "description": "NSFW: nudity or sexual content, auto-tagged, not blocked"
          },
          "adult-review": {
            "description": "borderline NSFW, below the adult act threshold"
          },
          "real-person": {
            "description": "a specific real, identifiable person is depicted"
          },
          "ip": {
            "description": "references copyrighted or trademarked material"
          },
          "ip-review": {
            "description": "borderline IP reference, below the act threshold"
          }
        }
      }
    }
  ]
}

Errors

  • 400Invalid request (malformed JSON, or the body/query failed validation).
  • 401Missing, malformed, unknown or revoked API key.
  • 429Rate limit exceeded for this API key. See Retry-After.