Data modeling
Row-level security
Security filters

Security filters

Security filters are the simplest way to ensure row-level security is applied globally across all your data models. You pass a filters array when requesting a security token, and Embeddable automatically applies those filters to every query in the dashboard session — with no changes to your data models required.

The key advantage is that enforcement is guaranteed: if a filter cannot be applied to a query (for example, because there is no join path to the filtered model), the query fails with an error rather than silently returning unfiltered data. This means non-technical team members can build models and dashboards freely without risking accidental data exposure.

Adding security filters

Pass a filters array in your Tokens API request:

fetch('https://api.<region>.embeddable.com/api/v1/security-token', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json',
    'Authorization': `Bearer ${apiKey}`
  },
  body: JSON.stringify({
    // ...
    filters: [{
      member: "customers.id",
      operator: "equals",
      values: ["5"],
    }]
  })
})

Filter fields

member

The model field to filter on. This can be a dimension or measure, referenced in <model>.<field> notation (e.g. customers.id, orders.region).

operator

How the field is compared to the values.

OperatorExplanation
equalsMember equals the given value(s).
notEqualsMember does not equal the given value(s).
containsCase-insensitive substring match.
notContainsInverse of contains.
startsWithPrefix match.
notStartsWithInverse of startsWith.
endsWithSuffix match.
notEndsWithInverse of endsWith.
gtGreater than a numeric value.
gteGreater than or equal to a numeric value.
ltLess than a numeric value.
lteLess than or equal to a numeric value.
inDateRangeTime member is within the given range.
notInDateRangeExcludes rows within the given range.
onTheDateMember is on the exact date provided.
beforeDateStrictly before the given timestamp.
beforeOrOnDateBefore or on the given timestamp.
afterDateStrictly after the given timestamp.
afterOrOnDateAfter or on the given timestamp.
setMember is NOT NULL (omit values).
notSetMember is NULL (omit values).

Authoritative list of operators is here (opens in a new tab).

values

What the field is compared against. Always an array. If the operator is set or notSet, omit this field.

Examples:

["123"]
["United States", "Germany"]
["2025-08-23"]
["2025-01-01", "2025-03-31"]

Testing your security filters

To try out different filter configurations in the no-code builder, define presets in your repo at src/presets/security-contexts.sc.yml (here (opens in a new tab)):

- name: Nike
  securityContext: {}
  filters:
    - member: customers.id
      operator: equals
      values: [ abc23478 ]
 
- name: Adidas
  securityContext: {}
  filters:
    - member: customers.id
      operator: equals
      values: [ 99 ]

Each entry appears under the "View as" dropdown in the builder:

Image 0

Switch between presets to verify each user only sees the rows their filter allows.

Other row-level security methods

  • SQL-based row-level security – the recommended approach if you want control of row-level (or table / schema-level) security at the model level.
  • Access Policies – a more scalable approach, when you have a lot of complex models, particularly powerful when combined with Views.