Skip to main content
You run a platform. Tenant A needs US Securities. Tenant B needs a different managed pack plus their own imported policy. Every call must run that tenant’s rules and nothing else.

Key allow-list vs validation_scope

The API key’s Rulepacks setting is the outer boundary. Create keys in Command (Settings → API → Keys) and set Rulepacks on each key. That allow-list caps which managed packs the key may use. validation_scope only narrows live enforcement to a subset of already-active rules, rule packs, and imports. It cannot broaden key permissions. If a request scopes to a pack the key does not allow, that pack is outside the key boundary. Discover pack ids with Rule Packs (GET /api/rulepacks/). Do not hard-code pack ids you have not confirmed for your account.

Two patterns

Pattern A — one API key per tenant. Mint a key per tenant and set Rulepacks on the key. Every call with that key stays inside that allow-list. Simplest isolation when tenants are few and stable. Pattern B — one key, scope per request. Keep a tenant table and pass validation_scope on every call. Best when tenants are many or change often. The shared key’s allow-list remains the outer boundary; per-request scope only narrows further. Activated custom rules from Import a Policy run for the account by default. For Pattern B, always pass validation_scope so a tenant does not pick up another tenant’s active imports.

Pattern A

Use the tenant’s key. Always pass validation_scope.imports on Pattern A too: the key Rulepacks allow-list does not isolate custom imports. Use that tenant’s import ids, or [] if the tenant has none.

Pattern B

One shared key. Look up the tenant’s activated import_id and pass validation_scope.imports on every call. Import ids come from Import a Policy, not invented fixtures. Set TENANT_IMPORT_ID. Live validation_scope.rulepacks currently fails closed (fallback_reason: rulepack_scope_unsupported). Use Pattern A (per-tenant keys) to isolate managed packs; use Pattern B for tenant-specific imported policies. Optional metadata is merged into the job (Enforce Content). Activity list filters are the documented query params on List Activity (from, to, status, agent_id, source, rule_id, search, cursor, limit) — do not assume arbitrary metadata keys are Activity filters.

Tenant-specific policies

A tenant’s own rulebook becomes an import_id through Import a Policy. Put that id in the tenant’s imports list. For either pattern, pass validation_scope.imports explicitly when multiple tenants share one ZeroDrift account. Calls then run the regulatory pack and tenant policy together when both are in scope.

Gotchas

  • Missing validation_scope.imports evaluates every active import on the account. Pass the tenant’s import ids (or []) on Pattern A and Pattern B.
  • validation_scope cannot widen the key. It only narrows within the key allow-list and already-active imports/rules.
  • Managed-pack request scope is not live. validation_scope.rulepacks currently returns status: "failed" with fallback_reason: rulepack_scope_unsupported. Isolate managed packs with Pattern A until that path is supported.
  • Resolve ids. List packs with GET /api/rulepacks/ (for example zd-us-securities). Set TENANT_IMPORT_ID for Pattern B.

Next

Rule Packs

List managed and custom packs; use returned ids in validation_scope.rulepacks.

Export Activity

Pull the verdict log for reporting and threshold tuning.