Skip to Content
GovernanceAccess Policies

Access Policies

Access Policies provide row-level access control in Zeotap. An access policy defines filter criteria that are automatically applied to all queries when a member of a specific group accesses data. This ensures that team members only see the data they are authorized to see — without requiring separate models or warehouse views.

How Access Policies Work

When an access policy is active for a user (via their group membership), Zeotap automatically narrows every query that runs on behalf of that user to the rows its criteria permit. This applies to:

  • Model previews — SQL query results in the model editor
  • Audience builder — Filter counts, estimation, and preview
  • Computed attribute evaluation — Computed attribute evaluation scoped to the access policy
  • Sync execution — Only rows matching the access policy are synced to destinations

The filtering is transparent and automatic. Users do not need to add anything to their queries — the platform applies the policy’s criteria before the query runs, so restricted rows are never read out of the warehouse.

Use Cases

Use CaseAccess Policy CriteriaAssigned To
Regional data accessregion equals EMEAEMEA team group
Country-specific compliancecountry_code equals DEGermany operations group
Partner data isolationpartner_id equals partner_abcPartner ABC group
Business unit separationbusiness_unit equals enterpriseEnterprise sales group
Test data isolationenvironment equals stagingQA team group
Customer tier restrictiontier in ["gold", "platinum"]Premium support group

Creating an Access Policy

Via the UI

  1. Navigate to Governance > Access Policies in the sidebar
  2. Click Add Access Policy
  3. Fill in the access policy configuration:
FieldDescriptionExample
CategoryThe category the policy belongs to. Policies are created inside a category, so pick or create one first.”Region”, “Brand”
NameDescriptive name for the access policy”EMEA Region Only”
DescriptionExplanation of what the access policy restricts”Limits data access to EMEA region customers”
Parent modelThe model the policy applies to. A policy only affects queries against this model.”Customers”
FilterThe criteria a row must match to be visible, built with the same filter builder as an audienceregion equals EMEA
  1. Click Save

Via the API

A policy belongs to a category and a model, and its condition is a filter tree in the same format as an audience filter:

curl -X POST "$API_BASE_URL/api/v1/workspaces/$WORKSPACE_ID/subsets" \ -H "Authorization: Bearer $API_TOKEN" \ -H "X-Workspace-ID: $WORKSPACE_ID" \ -H "Content-Type: application/json" \ -d '{ "name": "EMEA Region Only", "description": "Limits data access to EMEA region customers", "category_id": "880e8400-e29b-41d4-a716-446655440000", "parent_model_id": "770e8400-e29b-41d4-a716-446655440000", "filter_tree": { "type": "condition", "condition_type": "property", "column": "region", "operator": "equals", "value": "EMEA" } }'

Category IDs come from GET /api/v1/workspaces/{id}/subset-categories.

Filter Criteria

Access policy criteria are filter trees, not SQL text. You build them with the same visual filter builder used for audiences, and over the API they use the same filter tree structure. This is what lets a policy reach beyond simple column comparisons — a condition can traverse a relationship or reference a computed attribute, which a raw WHERE fragment could not express.

IntentCondition
Simple equalityregion equals EMEA
One of several valuescountry_code in ["US", "CA", "MX"]
Rangecreated_at on or after 2024-01-01
Combinedregion equals EMEA and customer_type equals enterprise
Presencepartner_id is not null
Patternemail ends with @mycompany.com

Important Notes on Filter Criteria

  • A policy names the parent model it applies to, and only affects queries against that model. A policy on the Customers model does not restrict queries against Orders, even for the same user.
  • Criteria must reference columns available on that model. Because the policy is bound to a specific model, the builder only offers columns that model actually exposes.
  • Criteria are combined into the query as an additional AND clause. They narrow what a query returns and never widen it, and they do not replace conditions the query already has.
  • A policy whose filter is empty contributes nothing and is skipped.

Categories

Categories group related access policies, and determine how multiple policies combine. A category is a resource in its own right — created, renamed and deleted like anything else — with a name, an optional description, and a Required flag.

CategoryExample Access PoliciesDescription
RegionNorth America, EMEA, APACRestrict data by geography
PartnerPartner A, Partner BIsolate data for external partners
ComplianceGDPR, CCPA, HIPAAEnforce regulatory requirements
Business UnitMarketing, Sales, SupportSeparate data by internal teams
TestingStaging, QAIsolate test or staging data

You define whatever categories make sense for your organization. Manage them under Governance > Access Policies, or over the API at /api/v1/workspaces/{id}/subset-categories.

Required Categories

Marking a category Required changes the default for anyone it does not cover: a member who has no policy from a required category sees no rows at all, rather than seeing everything.

This is the difference between an opt-in and an opt-out model, and it is the setting that makes access policies a real boundary:

  • No required categories — a member with no policies assigned has unrestricted access. Policies only ever narrow access for the people who have them.
  • At least one required category — a member must hold a policy in every required category to see anything. Someone who is added to the workspace but not yet placed in the right group sees an empty result rather than the whole table.

The same rule applies per model: if a member holds policies but none of them apply to the model being queried, and any category is required, the query returns nothing.

Turn on Required only once the groups and policies that grant access are in place. Marking a category required takes effect immediately, and anyone not yet covered by a policy in it will find previews, audience counts and sync results empty until they are.

How Categories Affect Access Policy Combination

When a member has multiple access policies from the same category, they are combined with OR logic (they see data matching any of the policies in that category).

When a member has access policies from different categories, the categories are combined with AND logic (they see data matching policies from all categories).

Example:

A member has:

  • “EMEA” and “APAC” access policies in the Region category
  • “Marketing” access policy in the Business Unit category

The effective filter is:

(region = 'EMEA' OR region = 'APAC') AND (business_unit = 'marketing')

This means the member sees EMEA and APAC marketing data only.

Assigning Access Policies to Groups

Access policies are assigned to groups, not individual users. This makes management scalable — instead of assigning access policies to each user, you assign them to groups, and all members of the group inherit the access policy.

There are two places to make the assignment. They act on the same data, so use whichever matches the question you are answering.

From the access policy (policy-first)

Use this when you are authoring policies and want to see, at a glance, which groups each one reaches.

  1. Navigate to Governance > Access Policies
  2. Expand the category containing the policy
  3. Each policy lists its assigned groups as chips. Click Assign group to grant it to another group, or the × on a chip to revoke it — changes save immediately.

A policy assigned to no group applies to nobody. The category header shows an unassigned count so a policy that was created but never granted does not sit unnoticed — a newly created policy appears in its category with the picker ready, so granting it is the next click.

From the group (group-first)

Use this when you are onboarding a team and want to review everything one group can see.

  1. Navigate to Governance > RBAC > Groups
  2. Click on the group you want to modify
  3. In the Access Policies section, click Edit Filters
  4. Select the access policy/policies to assign
  5. Click Save

Via the API

Replace the full set of policies on a group:

curl -X PUT "$API_BASE_URL/api/v1/workspaces/$WORKSPACE_ID/groups/$GROUP_ID/subsets" \ -H "Authorization: Bearer $API_TOKEN" \ -H "X-Workspace-ID: $WORKSPACE_ID" \ -H "Content-Type: application/json" \ -d '{ "subset_ids": ["sub_abc123", "sub_def456"] }'

Or grant and revoke one group at a time, from the policy’s side:

# List the groups a policy is granted to curl "$API_BASE_URL/api/v1/workspaces/$WORKSPACE_ID/subsets/$SUBSET_ID/assignments" \ -H "Authorization: Bearer $API_TOKEN" \ -H "X-Workspace-ID: $WORKSPACE_ID" # Grant the policy to a group curl -X POST "$API_BASE_URL/api/v1/workspaces/$WORKSPACE_ID/subsets/$SUBSET_ID/assignments" \ -H "Authorization: Bearer $API_TOKEN" \ -H "X-Workspace-ID: $WORKSPACE_ID" \ -H "Content-Type: application/json" \ -d '{"entity_type": "group", "entity_id": "grp_abc123"}' # Revoke it (assignment_id comes from the list call above) curl -X DELETE "$API_BASE_URL/api/v1/workspaces/$WORKSPACE_ID/subsets/$SUBSET_ID/assignments/$ASSIGNMENT_ID?type=group" \ -H "Authorization: Bearer $API_TOKEN" \ -H "X-Workspace-ID: $WORKSPACE_ID"

Every group assignment in a workspace, across all policies, is available in one call — this is what the Access Policies page uses to render its chips:

curl "$API_BASE_URL/api/v1/workspaces/$WORKSPACE_ID/subset-assignments" \ -H "Authorization: Bearer $API_TOKEN" \ -H "X-Workspace-ID: $WORKSPACE_ID"

Multiple Groups

When a user belongs to multiple groups with different access policies, the access policies from all groups are merged:

  • Access policies within the same category (across groups) are combined with OR
  • Access policies across different categories are combined with AND

Example:

  • Group “EMEA Team” has access policy: region = 'EMEA'
  • Group “APAC Team” has access policy: region = 'APAC'
  • A user in both groups sees data where region = 'EMEA' OR region = 'APAC'

Role Exemptions

Members with the Owner or Admin role are exempt from access policy filtering — but only while they have no access policies of their own. The exemption is a default for unrestricted roles, not an override:

  • An Owner or Admin in no group carrying access policies sees all data, and is not blocked by a required category.
  • An Owner or Admin who is in a group carrying access policies is filtered by them like anyone else. If you need an administrator to see everything, keep them out of the groups that carry policies rather than relying on their role.

There is no workspace setting that changes this behaviour.

How Access Policies Are Applied

When a query is executed on behalf of a user:

  1. Zeotap resolves the user’s group memberships
  2. All access policies assigned to those groups are collected
  3. Policies that do not apply to the model being queried are discarded
  4. The remainder are grouped by category and combined (OR within category, AND across categories)
  5. If any category is required and the user holds no applicable policy in it, the query is restricted to no rows
  6. Otherwise the combined criteria are applied as an AND clause to the query

The SQL below shows the effect. The criteria themselves are filter trees, not text you write — Zeotap compiles them into your warehouse’s dialect.

Before access policy:

SELECT customer_id, email, region FROM customers WHERE lifetime_value > 100

After access policy (region = 'EMEA'):

SELECT customer_id, email, region FROM customers WHERE lifetime_value > 100 AND (region = 'EMEA')

After access policy (two categories):

SELECT customer_id, email, region, business_unit FROM customers WHERE lifetime_value > 100 AND (region = 'EMEA' OR region = 'APAC') AND (business_unit = 'marketing')

Managing Access Policies

Editing an Access Policy

Changes to an access policy’s criteria take effect immediately. All subsequent queries from members of groups holding that policy use the updated criteria. Results already computed — a stored audience size, a completed sync run — are not recalculated retroactively.

Suspending an Access Policy

An access policy has no enabled/disabled switch. To stop one applying, revoke it from the groups it is assigned to — a policy assigned to no group applies to nobody, while remaining available to re-assign later. The chips on the policy in Governance > Access Policies are the quickest way to do this.

Deleting an Access Policy

Deleting an access policy removes it from all groups. This action cannot be undone.

Check the effect before deleting when the policy’s category is required: removing someone’s only policy in a required category does not widen their access, it removes it entirely. Reassign the affected groups to another policy in that category first.

Reviewing Who Can See What

There is no per-query audit trail — Zeotap does not record each query a policy narrowed, or the before-and-after SQL. Review access by inspecting the assignments instead:

  • By policyGovernance > Access Policies lists each policy with the groups it is granted to, and flags policies granted to nobody.
  • By group — a group’s detail page lists every access policy it carries, which is the full picture of what its members can see.
  • By APIGET /api/v1/workspaces/{id}/subset-assignments returns every group assignment in the workspace in one call, which is the easiest form to snapshot for a periodic review.
  • As yourselfGET /api/v1/workspaces/{id}/subsets/me returns the policies in force for the calling user, which is the quickest way to confirm what a given account is actually subject to.

API Reference

Every path below is workspace-scoped — {id} is your workspace ID. See Base URL for your instance’s API base URL and Authentication for the required Authorization and X-Workspace-ID headers.

# List all access policies GET /api/v1/workspaces/{id}/subsets # Get a single access policy GET /api/v1/workspaces/{id}/subsets/{subsetId} # Create an access policy POST /api/v1/workspaces/{id}/subsets # Update an access policy PUT /api/v1/workspaces/{id}/subsets/{subsetId} # Delete an access policy DELETE /api/v1/workspaces/{id}/subsets/{subsetId} # The policies that apply to you in this workspace GET /api/v1/workspaces/{id}/subsets/me # Categories GET /api/v1/workspaces/{id}/subset-categories POST /api/v1/workspaces/{id}/subset-categories GET /api/v1/workspaces/{id}/subset-categories/{catId} PUT /api/v1/workspaces/{id}/subset-categories/{catId} DELETE /api/v1/workspaces/{id}/subset-categories/{catId}

Common Patterns

PatternConfiguration
Regional data isolationOne access policy per region in a “Regional” category, assigned to regional team groups
Partner data roomsOne access policy per partner with partner_id filter in a “Partner” category
Data sovereigntyAccess policies filtering by data_residency_country in a “Compliance” category
Tiered accessAccess policies filtering by customer tier in a “Tier” category
Department isolationAccess policies filtering by department in a “Business Unit” category

Next Steps

Last updated on