Semaphor
Semantic Domains

Access Control

Control which semantic domains users can access when embedding dashboards

When embedding Semaphor in a multi-tenant application, you often need to control which semantic domains each user can access. The semanticDomainAccess parameter in the token request scopes domain visibility per user or tenant.

You set this when generating a project token via POST /api/v1/token.

Access Modes

The mode field determines how domains are filtered for the user.

ModeBehaviordomains field
allUser can access all semantic domains in the project (default)Not allowed
noneUser cannot access any semantic domainsNot allowed
includeUser can only access the listed domainsRequired (non-empty)
excludeUser can access all domains except the listed onesRequired (non-empty)

Behavior by Scenario

Default: All Domains

When semanticDomainAccess is omitted, the token defaults to { mode: 'all' }. The user sees every semantic domain in the project.

const requestBody = {
  type: 'project',
  projectId: PROJECT_ID,
  projectSecret: PROJECT_SECRET,
  endUserId: 'user_123',
  // semanticDomainAccess is omitted — defaults to { mode: 'all' }
};

Allow Only Specific Domains

With include mode, only the listed domains are accessible. Everything else is hidden.

const requestBody = {
  type: 'project',
  projectId: PROJECT_ID,
  projectSecret: PROJECT_SECRET,
  endUserId: 'user_123',
  semanticDomainAccess: {
    mode: 'include',
    domains: ['Sales Analytics', 'Marketing Data'],
  },
};

The user sees "Sales Analytics" and "Marketing Data" when creating cards or exploring data. All other domains are hidden.

Exclude Specific Domains

With exclude mode, all domains are accessible except the ones you list.

const requestBody = {
  type: 'project',
  projectId: PROJECT_ID,
  projectSecret: PROJECT_SECRET,
  endUserId: 'user_123',
  semanticDomainAccess: {
    mode: 'exclude',
    domains: ['Internal Admin'],
  },
};

The user sees all domains except "Internal Admin".

No Domain Access

With none mode, the user cannot access any semantic domains. They can still use dashboards with non-domain data sources (e.g., direct SQL cards).

const requestBody = {
  type: 'project',
  projectId: PROJECT_ID,
  projectSecret: PROJECT_SECRET,
  endUserId: 'user_123',
  semanticDomainAccess: { mode: 'none' },
};

Domain Identification

The domains array accepts both domain names and domain UUIDs. You can mix both in the same array.

semanticDomainAccess: {
  mode: 'include',
  domains: [
    'Sales Analytics',                              // by name
    '550e8400-e29b-41d4-a716-446655440001',         // by UUID
  ],
},

Domain names and UUIDs are resolved within the scope of the project specified in the token request. If a domain is not found, the API returns an error listing the unresolved domains.

Validation Rules

The API validates semanticDomainAccess and returns an error for invalid inputs.

ScenarioAPI Response
mode is not all, none, include, or excludesemanticDomainAccess.mode must be one of: 'all', 'none', 'include', 'exclude'.
mode: 'include' with empty or missing domainssemanticDomainAccess.domains is required and must be non-empty when mode is 'include'.
mode: 'exclude' with empty or missing domainssemanticDomainAccess.domains is required and must be non-empty when mode is 'exclude'.
mode: 'all' with domains providedsemanticDomainAccess.domains is not allowed when mode is 'all'.
mode: 'none' with domains providedsemanticDomainAccess.domains is not allowed when mode is 'none'.
Domain name or UUID not found in projectError listing the unresolved domains

Common Patterns

Per-Tenant Domain Scoping

Scope each tenant to their relevant domains.

async function getTokenForTenant(tenantId: string, tenantDomains: string[]) {
  const response = await fetch(TOKEN_URL, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      type: 'project',
      projectId: PROJECT_ID,
      projectSecret: PROJECT_SECRET,
      tenantId,
      endUserId: 'user_123',
      semanticDomainAccess: {
        mode: 'include',
        domains: tenantDomains,
      },
    }),
  });
  return response.json();
}

Role-Based Access

Grant broader access to power users while restricting viewers to a subset.

const semanticDomainAccess = user.role === 'POWER_USER'
  ? { mode: 'all' as const }
  : { mode: 'include' as const, domains: ['Sales Overview', 'Marketing Summary'] };
 
const requestBody = {
  type: 'project',
  projectId: PROJECT_ID,
  projectSecret: PROJECT_SECRET,
  endUserId: user.id,
  semanticDomainAccess,
};

Hide Internal Domains from External Users

Use exclude to keep internal-only domains out of customer-facing embeddings.

const requestBody = {
  type: 'project',
  projectId: PROJECT_ID,
  projectSecret: PROJECT_SECRET,
  endUserId: user.id,
  semanticDomainAccess: {
    mode: 'exclude',
    domains: ['Internal Admin', 'Engineering Metrics'],
  },
};

For the complete token API reference including all parameters, security policies, and UI configuration options, see Token Options.

On this page