Skip to content

API Reference

Overview

Manage Identifiers and Omni Policies programmatically through the Metadata Service (MDS) REST APIs.

Availability

The Policy Authoring API is evolving and is not yet a finalized public contract. For endpoint details and integration guidance, contact your Privacera representative.


Authentication

All Metadata Service (MDS) API calls in this reference — Identifiers, Omni Policies, and the enforcement endpoints below — must be authenticated. On Self-Managed, send a bearer token in the Authorization header. On Data Plane and PrivaceraCloud, use an API key in the request URL. Requests without valid credentials, or on Self-Managed with a token that doesn't carry the required scope, are rejected.

Generating a token

Tokens are generated from the Privacera Portal.

  1. In the Portal, go to Settings > Token Management.
  2. Click Generate Token.
  3. Fill in the fields:

    Field Required Description
    Token Name Yes A name to identify this token later
    Scope Yes Select MDS
    MDS Scopes Yes One or more scopes — see table below
    Description No Free-text notes
    Expiry Yes, unless Never expire is checked When the token stops working
  4. Click Generate Token and copy the generated token for use in API requests.

MDS Scopes

Scope Claim Allows
Metadata Write METADATA_WRITE Create, update, and delete metadata — and read (write includes read)
Metadata Read METADATA_READ Read-only access to metadata
Metadata Read (Unrestricted) METADATA_READ_UNRESTRICTED Read-only access, without row/column-level restrictions applied

For any endpoint that creates, updates, or deletes data — including every enforcement endpoint in this reference — generate the token with Metadata Write.

Using the token

Pass it as a bearer token on every request:

HTTP
1
2
3
POST <MDS-URL>/api/v2/metadata/omni-policies/enforcement/grant-access/resources
Authorization: Bearer <token>
Content-Type: application/json

Verifying it works

Status Meaning
200 / 201 / 204 Token is valid and authorized
401 Unauthorized Token is missing, invalid, or expired — generate a new one
403 Forbidden Token is valid but lacks the required scope — regenerate with Metadata Write

Generating an API key

API calls are authenticated with an API key that is part of the request URL. You do not send an Authorization header.

  1. In the Privacera Portal, go to Settings > API Keys.
  2. Click GENERATE API KEY.
  3. Enter the purpose, and choose whether the key never expires or expires at a specific date and time.
  4. Click GENERATE API KEY, then copy the API key from the Generated API Key dialog and save it. The full key is shown only once.
  5. In the API Key Info dialog, click COPY URL next to the Ranger Admin URL.
  6. The copied URL contains the placeholder __API_KEY__. Replace it with the API key you saved in step 4.

After the replacement, the URL has this form. In it, <api-key> is your API key:

Text Only
https://<apiserver-host>/api/<api-key>

Using the API key

Add /omni-metadata and the API path from this reference after the copied URL. In the examples in this reference, use this URL in place of <MDS-URL>:

Text Only
https://<apiserver-host>/api/<api-key>/omni-metadata

For example, to list identifiers:

HTTP
GET https://<apiserver-host>/api/<api-key>/omni-metadata/api/v1/metadata/identifiers

Verifying it works

Status Meaning
200 The request succeeded
400 The API key is not valid or has expired — generate a new key

Generating an API key

API calls are authenticated with an API key that is part of the request URL. You do not send an Authorization header.

  1. In the Privacera Portal, go to Settings > API Keys.
  2. Click GENERATE API KEY.
  3. Enter the purpose, and choose whether the key never expires or expires at a specific date and time.
  4. Click GENERATE API KEY, then copy the API key from the Generated API Key dialog and save it. The full key is shown only once.
  5. In the API Key Info dialog, click COPY URL next to the Ranger Admin URL.
  6. The copied URL contains the placeholder __API_KEY__. Replace it with the API key you saved in step 4.

After the replacement, the URL has this form. In it, <api-key> is your API key:

Text Only
https://<apiserver-host>/api/<api-key>

Using the API key

Add /omni-metadata and the API path from this reference after the copied URL. In the examples in this reference, use this URL in place of <MDS-URL>:

Text Only
https://<apiserver-host>/api/<api-key>/omni-metadata

For example, to list identifiers:

HTTP
GET https://<apiserver-host>/api/<api-key>/omni-metadata/api/v1/metadata/identifiers

Verifying it works

Status Meaning
200 The request succeeded
400 The API key is not valid or has expired — generate a new key

Identifier APIs

An Identifier is a reusable, named selection of users, columns, or rows. Create identifiers first, then reference the returned id when authoring policies.

Base path: /api/v1/metadata/identifiers

Operation Method Path
Create POST /api/v1/metadata/identifiers
List / search GET /api/v1/metadata/identifiers
Get by ID GET /api/v1/metadata/identifiers/{id}
Update PUT /api/v1/metadata/identifiers/{id}
Delete DELETE /api/v1/metadata/identifiers/{id}

Common request body fields

Used by Create and Update.

Field Required Description
name Yes Unique identifier name
type Yes USER_IDENTIFIER, COLUMN_IDENTIFIER, or RECORD_IDENTIFIER
description No Human-readable description
status No Status (for example, ACTIVE). Defaults to ACTIVE when omitted
identifiers Yes Non-empty array of definition blocks

Each item in identifiers:

Field Required Description
description No Description of this definition block
controllers Yes One or more controller rules

Each controller:

Field Required Description
type_service Yes Name of the service this rule applies to. Use ALL for User and Column identifiers; for Record identifiers, the Ranger service name from Data Catalog (for example, privacera_snowflake, privacera_bigquery, privacera_databricks_unity_catalog)
query Yes Filter expression (same syntax as the UI)

type_service rules

type_service is the service name for the controller rule.

  • USER_IDENTIFIER and COLUMN_IDENTIFIER must use type_service: "ALL" only.
  • RECORD_IDENTIFIER uses one controller per service. Set type_service to the Ranger service name shown in Data Governance > Data Browser > Data Catalog for your connector (for example, privacera_snowflake, privacera_bigquery, privacera_databricks_unity_catalog).
  • The API does not strictly validate type_service against a fixed list. If a rule does not apply as expected, open Data Browser and confirm the exact service name for your deployment.
  • Do not mix ALL with specific service types in the same identifier.
  • Blank type_service is normalized to ALL.

Request vs response field name

The request body uses identifiers (plural). The response body uses identifier (singular).

Creating an Identifier via API

Create a reusable Identifier (User, Column, or Record) that policies can reference.

API Endpoint:

HTTP
POST <MDS-URL>/api/v1/metadata/identifiers

Request Body: See common request body fields above.

Example Request (USER_IDENTIFIER):

JSON
{
  "name": "Employees",
  "description": "All employees",
  "type": "USER_IDENTIFIER",
  "identifiers": [
    {
      "description": "Employee user type",
      "controllers": [
        {
          "type_service": "ALL",
          "query": "USER.userType == 'EMPLOYEE'"
        }
      ]
    }
  ]
}

Example Request (RECORD_IDENTIFIER):

JSON
{
  "name": "Allowed Properties by Region Access",
  "description": "Properties matching the requesting user's region",
  "type": "RECORD_IDENTIFIER",
  "identifiers": [
    {
      "description": "Snowflake region filter",
      "controllers": [
        {
          "type_service": "privacera_snowflake",
          "query": "obj.region_name = '${{USER.region}}'"
        }
      ]
    }
  ]
}

Example Request (COLUMN_IDENTIFIER):

JSON
{
  "name": "Sensitive financial columns",
  "description": "Columns tagged SENSITIVE_FINANCIAL",
  "type": "COLUMN_IDENTIFIER",
  "identifiers": [
    {
      "controllers": [
        {
          "type_service": "ALL",
          "query": "HAS_TAG('SENSITIVE_FINANCIAL')"
        }
      ]
    }
  ]
}

HTTP Status Codes:

  • 201 Created: Identifier created successfully
  • 400 Bad Request: Validation error (missing name, invalid type, blank query, invalid type_service)

Response Fields:

  • id: Identifier vertex ID — save this for policy authoring
  • name: Identifier name
  • type: USER_IDENTIFIER, COLUMN_IDENTIFIER, or RECORD_IDENTIFIER
  • description: Description
  • status: Status (for example, ACTIVE)
  • identifier: Array of definition blocks
    • description: Description of the block
    • controllers: Array of rules
      • type_service: Service scope (ALL or a service name)
      • query: Filter expression
  • createdTime / updatedTime: Creation and last-update time as Unix epoch milliseconds
  • createdBy / updatedBy: Audit fields

On failed requests, the response may also include errorCode and message.

Example Response:

JSON
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "name": "Employees",
  "type": "USER_IDENTIFIER",
  "description": "All employees",
  "status": "ACTIVE",
  "identifier": [
    {
      "description": "Employee user type",
      "controllers": [
        {
          "type_service": "ALL",
          "query": "USER.userType == 'EMPLOYEE'"
        }
      ]
    }
  ],
  "createdTime": 1780294519989,
  "updatedTime": 1780294519989,
  "createdBy": "admin@example.com",
  "updatedBy": "admin@example.com"
}

Listing Identifiers via API

List and search identifiers. Use optional filters to narrow results by type or name, and use pagination parameters to retrieve additional pages.

API Endpoint:

HTTP
GET <MDS-URL>/api/v1/metadata/identifiers

Query Parameters:

  • types (optional): Filter by identifier type (USER_IDENTIFIER, COLUMN_IDENTIFIER, RECORD_IDENTIFIER). Repeat the parameter to include multiple types (OR logic). Example: types=USER_IDENTIFIER&types=RECORD_IDENTIFIER
  • search (optional): Case-insensitive name search
  • sortBy (optional): Sort field — name, type, createdat, updatedat (default: name)
  • sortOrder (optional): Sort direction — asc or desc (default: asc)
  • page (optional): Page number for pagination (zero-based, default: 0)
  • size (optional): Number of identifiers per page (default: 25, maximum: 1000)

Example Request:

HTTP
GET <MDS-URL>/api/v1/metadata/identifiers?types=USER_IDENTIFIER&search=Employee&sortBy=name&sortOrder=asc&page=0&size=25

Response Fields:

  • eventTime: Timestamp of the operation (epoch milliseconds)
  • status: Status of the operation (for example, SUCCESS)
  • totalCount: Total number of matching identifiers across all pages
  • number: Current page number (zero-based)
  • pageSize: Number of items returned on this page
  • totalPages: Total number of pages
  • hasNext: true when another page is available; increment page to fetch it
  • hasPrevious: true when a previous page is available
  • content: Array of identifier objects (same fields as the create response)
    • id: Identifier vertex ID
    • name: Identifier name
    • type: Identifier type
    • description: Description
    • status: Status
    • identifier: Array of definition blocks with controllers
    • createdTime / updatedTime: Creation and last-update time as Unix epoch milliseconds
    • createdBy / updatedBy: Audit fields
  • filters: Echo of filters applied for this request (for example, types, search)
  • sortBy: Field used for sorting
  • sortOrder: Sort direction

On failed requests, the response may also include errorCode and message.

Example Response:

JSON
{
  "eventTime": 1780294519989,
  "status": "SUCCESS",
  "totalCount": 1,
  "number": 0,
  "pageSize": 25,
  "totalPages": 1,
  "hasNext": false,
  "hasPrevious": false,
  "content": [
    {
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "name": "Employees",
      "type": "USER_IDENTIFIER",
      "description": "All employees",
      "status": "ACTIVE",
      "identifier": [
        {
          "controllers": [
            {
              "type_service": "ALL",
              "query": "USER.userType == 'EMPLOYEE'"
            }
          ]
        }
      ],
      "createdTime": 1780294519989,
      "updatedTime": 1780294519989
    }
  ],
  "filters": {
    "types": ["USER_IDENTIFIER"],
    "search": "Employee"
  },
  "sortBy": "name",
  "sortOrder": "asc"
}

Pagination:

When hasNext is true, more results are available. Request the next page by incrementing the page query parameter while keeping the same size and filters.

Retrieving an Identifier by ID via API

Retrieve a single identifier by its vertex ID.

API Endpoint:

HTTP
GET <MDS-URL>/api/v1/metadata/identifiers/{id}

Path Parameters:

  • id (required): Identifier vertex ID

Example Request:

HTTP
GET <MDS-URL>/api/v1/metadata/identifiers/a1b2c3d4-e5f6-7890-abcd-ef1234567890

HTTP Status Codes:

  • 200 OK: Identifier found
  • 400 Bad Request: Identifier ID is blank
  • 404 Not Found: No identifier with the given ID

Response Fields: Same as the create response.

Updating an Identifier via API

Update an existing identifier. If the number of affected policy resources exceeds the async threshold, the entity update and Ranger re-sync are queued as a background job.

API Endpoint:

HTTP
PUT <MDS-URL>/api/v1/metadata/identifiers/{id}

Path Parameters:

  • id (required): Identifier vertex ID

Request Body: Same structure as create. All required fields (name, type, identifiers) must be provided.

Example Request:

HTTP
PUT <MDS-URL>/api/v1/metadata/identifiers/a1b2c3d4-e5f6-7890-abcd-ef1234567890
Content-Type: application/json
JSON
{
  "name": "Employees",
  "description": "All employees",
  "type": "USER_IDENTIFIER",
  "identifiers": [
    {
      "controllers": [
        {
          "type_service": "ALL",
          "query": "USER.userType == 'EMPLOYEE'"
        }
      ]
    }
  ]
}

HTTP Status Codes:

  • 200 OK: Update and Ranger re-sync completed inline
  • 202 Accepted: Update queued as a background job
  • 400 Bad Request: Validation error
  • 404 Not Found: Identifier not found

Response Fields (inline update — 200): Same as the create response.

Response Fields (async update — 202):

  • job_id: Background job ID — poll the job endpoint for completion status
  • data: Snapshot of the identifier at the time the job was queued

Example Response (202 Accepted):

JSON
{
  "job_id": 42,
  "data": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "name": "Employees",
    "type": "USER_IDENTIFIER",
    "status": "ACTIVE",
    "identifier": [
      {
        "controllers": [
          {
            "type_service": "ALL",
            "query": "USER.userType == 'EMPLOYEE'"
          }
        ]
      }
    ]
  }
}

Impact of updates

Editing an identifier affects every policy that references it.

Deleting an Identifier via API

Delete an identifier. Deletion is rejected if the identifier is still referenced by one or more Omni Policies.

API Endpoint:

HTTP
DELETE <MDS-URL>/api/v1/metadata/identifiers/{id}

Path Parameters:

  • id (required): Identifier vertex ID

Example Request:

HTTP
DELETE <MDS-URL>/api/v1/metadata/identifiers/a1b2c3d4-e5f6-7890-abcd-ef1234567890

HTTP Status Codes:

  • 204 No Content: Identifier deleted successfully (no response body)
  • 202 Accepted: Delete queued as a background job — response body is { "job_id": <number>, "data": null }; poll the job endpoint for completion
  • 400 Bad Request: Identifier ID is blank
  • 404 Not Found: Identifier not found
  • 409 Conflict: Identifier is still referenced by one or more policies — remove it from all policies first

Identifier examples

The examples below use the Acme scenarios. Create these identifiers first, then use the returned id values when authoring policies.

USER_IDENTIFIER

Employees

Used by the Employee portfolio access policy. Selects all employees.

UI query: USER.userType == 'EMPLOYEE'

API Endpoint:

HTTP
POST <MDS-URL>/api/v1/metadata/identifiers

Example Request:

JSON
{
  "name": "Employees",
  "description": "All employees",
  "type": "USER_IDENTIFIER",
  "identifiers": [
    {
      "description": "Employee user type",
      "controllers": [
        {
          "type_service": "ALL",
          "query": "USER.userType == 'EMPLOYEE'"
        }
      ]
    }
  ]
}

Regional Managers

Used by the Allowed properties to view row-filter policy.

UI query: IS_IN_ROLE('manager')

JSON
{
  "name": "Regional Managers",
  "description": "Users with the manager role",
  "type": "USER_IDENTIFIER",
  "identifiers": [
    {
      "controllers": [
        {
          "type_service": "ALL",
          "query": "IS_IN_ROLE('manager')"
        }
      ]
    }
  ]
}

Identify Offshore users

Used by the Texas row-filter policies for offshore users.

UI query: USER.location == 'offshore'

JSON
{
  "name": "Identify Offshore users",
  "description": "Users located offshore",
  "type": "USER_IDENTIFIER",
  "identifiers": [
    {
      "controllers": [
        {
          "type_service": "ALL",
          "query": "USER.location == 'offshore'"
        }
      ]
    }
  ]
}

COLUMN_IDENTIFIER

Sensitive financial columns

Used by the Redact sensitive data masking policy on REAL_ESTATE_TENANTS.

UI query: HAS_TAG('SENSITIVE_FINANCIAL')

API Endpoint:

HTTP
POST <MDS-URL>/api/v1/metadata/identifiers

Example Request:

JSON
{
  "name": "Sensitive financial columns",
  "description": "Columns tagged SENSITIVE_FINANCIAL",
  "type": "COLUMN_IDENTIFIER",
  "identifiers": [
    {
      "controllers": [
        {
          "type_service": "ALL",
          "query": "HAS_TAG('SENSITIVE_FINANCIAL')"
        }
      ]
    }
  ]
}

RECORD_IDENTIFIER

Allowed Properties by Region Access

Used by the Allowed properties to view row-filter policy. Regional managers see only properties in their region.

UI query: obj.region_name = '${{USER.region}}'

API Endpoint:

HTTP
POST <MDS-URL>/api/v1/metadata/identifiers

Example Request:

JSON
{
  "name": "Allowed Properties by Region Access",
  "description": "Properties matching the requesting user's region",
  "type": "RECORD_IDENTIFIER",
  "identifiers": [
    {
      "description": "Snowflake region filter",
      "controllers": [
        {
          "type_service": "privacera_snowflake",
          "query": "obj.region_name = '${{USER.region}}'"
        }
      ]
    }
  ]
}

Identify Texas data

Used by Restrict Texas data from offshore users. Resolves the STATE column by tag at query time.

UI query: obj.${{TAG_GET_CHILD_RES('STATE')}} = 'TX'

JSON
{
  "name": "Identify Texas data",
  "description": "Rows in Texas",
  "type": "RECORD_IDENTIFIER",
  "identifiers": [
    {
      "description": "Snowflake Texas filter",
      "controllers": [
        {
          "type_service": "privacera_snowflake",
          "query": "obj.${{TAG_GET_CHILD_RES('STATE')}} = 'TX'"
        }
      ]
    }
  ]
}

Used by Texas data for offshore users with consent.

UI query: obj.consent_given = 'true'

JSON
{
  "name": "Identify Data with consent",
  "description": "Rows where consent has been given",
  "type": "RECORD_IDENTIFIER",
  "identifiers": [
    {
      "controllers": [
        {
          "type_service": "privacera_snowflake",
          "query": "obj.consent_given = 'true'"
        }
      ]
    }
  ]
}

Omni Policy APIs (CRUD)

An Omni Policy controls who is governed, which data it applies to, and what action is taken. Create identifiers first, then reference their id values in the policy identifiers map and in whoQuery, dataQuery, and dataFiltersQuery. See Policies for the authoring model these operations manage.

Base path: /api/v1/metadata/omni-policies

Operation Method Path Success
Create POST /api/v1/metadata/omni-policies 201 or 202
Read (list) GET /api/v1/metadata/omni-policies 200
Read (one) GET /api/v1/metadata/omni-policies/{id} 200
Update PUT /api/v1/metadata/omni-policies/{id} 200 or 202
Patch metadata PATCH /api/v1/metadata/omni-policies/{id} 200
Activate PATCH /api/v1/metadata/omni-policies/{id}/activate 200 or 202
Deactivate PATCH /api/v1/metadata/omni-policies/{id}/deactivate 200 or 202
Delete DELETE /api/v1/metadata/omni-policies/{id} 200 or 202

Common request body fields

Used by Create and Update (OmniPolicyRequest).

Field Required Description
name Yes Unique policy name (max 255 characters)
type Yes ACCESS, MASKING, or RLF
description No Human-readable description
status No DRAFT, ACTIVE, or INACTIVE
actions Yes when ACTIVE Array of action definitions (for example, { "action": "DENY" } or { "action": "MASK", "masking": { "type": "MASK_HASH" } })
identifiers No Map of identifier vertex IDs by role (see below)
whoQuery No Identifier vertex ID (or expression of IDs) for the subject filter; must match a user_identifier in identifiers. Do not put the filter expression here — that lives on the Identifier.
dataQuery No Identifier vertex ID (or expression of IDs) for the column filter; must match a column_identifier in identifiers. Do not put the filter expression here — that lives on the Identifier.
dataFiltersQuery Yes when ACTIVE + RLF Identifier vertex ID (or expression of IDs) for the row filter; must match a record_identifier in identifiers. Do not put the filter expression here — that lives on the Identifier.
applyPolicy No Assets and principals the policy applies to
summary No Human-readable summary (does not trigger Ranger sync)

identifiers map keys:

Key Purpose
user_identifier User/principal matching — use the same ID in whoQuery
record_identifier Row-level filtering — use the same ID in dataFiltersQuery
column_identifier Column-level filtering — use the same ID in dataQuery

Each key holds an array of identifier vertex IDs from Create identifier responses. Put those same IDs in whoQuery, dataQuery, and dataFiltersQuery. At Ranger sync time, MDS replaces each ID with the Identifier's stored query. To combine multiple identifiers, join their IDs with AND or OR (for example, "<id1> AND <id2>").

applyPolicy object:

Field Description
assets Where the policy applies — array of { "type", "id" }
principals Who the policy governs — array of { "type", "name" }

Asset type values:

type id meaning
TAG Tag name (for example, CUSTOMER_DATA) — used as the vertex ID
DATA_PRODUCT Data-product vertex ID
RESOURCE Full resource path (for example, privacera_snowflake/db/schema/table). Other resource labels such as TABLE, SCHEMA, or DATABASE are also accepted

Principal type values: USER, GROUP, ROLE. Use GROUP with name public for everyone.

ACTIVE policy validation

When status is ACTIVE: - At least one action is required. - At least one principal in applyPolicy.principals or a user_identifier in identifiers is required. - RLF policies require dataFiltersQuery. - whoQuery requires user_identifier; dataQuery requires column_identifier.

Creating an Omni Policy via API

API Endpoint:

HTTP
POST <MDS-URL>/api/v1/metadata/omni-policies

Request Body: See common request body fields above.

Example Request:

JSON
{
  "name": "Restrict Texas data from offshore users",
  "type": "RLF",
  "status": "ACTIVE",
  "actions": [{ "action": "DENY" }],
  "identifiers": {
    "user_identifier": ["<offshore-users-id>"],
    "record_identifier": ["<texas-data-id>"]
  },
  "whoQuery": "<offshore-users-id>",
  "dataFiltersQuery": "<texas-data-id>",
  "applyPolicy": {
    "assets": [{ "type": "TAG", "id": "CUSTOMER_DATA" }]
  }
}

Replace <offshore-users-id> and <texas-data-id> (in both identifiers and the matching query fields) with the id values from Create identifier. This RLF example shows whoQuery and dataFiltersQuery. For dataQuery (column identifiers), see the MASKING example under Omni Policy examples. For ACCESS examples, see the same section.

HTTP Status Codes:

  • 201 Created: Policy created synchronously — response body is the full policy object
  • 202 Accepted: Policy creation queued as async job — response body is { "job_id": <number>, "data": null }; poll the job endpoint for completion
  • 400 Bad Request: Validation error

Response Fields:

  • id: Policy vertex ID
  • name: Policy name
  • type: ACCESS, MASKING, or RLF
  • description: Description
  • policyStatus: DRAFT, ACTIVE, or INACTIVE
  • actions: Array of action definitions
  • identifiers: Linked identifier objects (on single-fetch responses)
  • whoQuery / dataQuery / dataFiltersQuery: Identifier vertex IDs stored on the policy (MDS resolves them to Identifier queries during Ranger sync)
  • applyPolicy: Attached assets and principals
  • createdAt / updatedAt: Creation and last-update time as Unix epoch milliseconds (numeric; not an ISO datetime string)
  • createdBy / updatedBy: Audit fields
  • summary: Human-readable summary

Example Response:

JSON
{
  "id": "policy-001",
  "eventTime": 1780294519989,
  "status": "SUCCESS",
  "name": "Restrict Texas data from offshore users",
  "type": "RLF",
  "policyStatus": "ACTIVE",
  "actions": [{ "action": "DENY" }],
  "identifiers": [
    {
      "id": "<offshore-users-id>",
      "name": "Identify Offshore users",
      "type": "USER_IDENTIFIER"
    },
    {
      "id": "<texas-data-id>",
      "name": "Identify Texas data",
      "type": "RECORD_IDENTIFIER"
    }
  ],
  "whoQuery": "<offshore-users-id>",
  "dataFiltersQuery": "<texas-data-id>",
  "applyPolicy": {
    "assets": [{ "type": "TAG", "id": "CUSTOMER_DATA" }],
    "principals": []
  },
  "createdAt": 1780294519989,
  "updatedAt": 1780294519989
}

Listing Omni Policies via API

API Endpoint:

HTTP
GET <MDS-URL>/api/v1/metadata/omni-policies

Query Parameters:

  • search (optional): Search by policy name pattern
  • type (optional): Filter by type — ACCESS, MASKING, or RLF
  • status (optional): Filter by status — DRAFT, ACTIVE, or INACTIVE
  • sortBy (optional): name, type, createdat, updatedat (default: name)
  • sortOrder (optional): asc or desc (default: asc)
  • page (optional): Page number (zero-based, default: 0)
  • size (optional): Page size (default: 25, maximum: 1000)

Example Request:

HTTP
GET <MDS-URL>/api/v1/metadata/omni-policies?type=RLF&status=ACTIVE&page=0&size=25

Response Fields:

  • eventTime, status, totalCount, number, pageSize, totalPages, hasNext, hasPrevious
  • content: Array of policy summary objects (name, type, policyStatus, createdAt, updatedAt)
  • filters, sortBy, sortOrder

Retrieving an Omni Policy by ID via API

HTTP
GET <MDS-URL>/api/v1/metadata/omni-policies/{id}

HTTP Status Codes: 200 OK, 400 Bad Request, 404 Not Found

Response Fields: Full policy object including identifiers and applyPolicy.

Updating an Omni Policy via API

HTTP
PUT <MDS-URL>/api/v1/metadata/omni-policies/{id}

Request Body: Same structure as create.

HTTP Status Codes: 200 OK, 202 Accepted, 400 Bad Request, 404 Not Found

Response Fields (202): job_id, data (policy snapshot at queue time)

Patching Omni Policy metadata via API

Update only name, description, or summary. Does not trigger a Ranger sync.

HTTP
PATCH <MDS-URL>/api/v1/metadata/omni-policies/{id}
JSON
1
2
3
4
{
  "name": "Updated policy name",
  "description": "Updated description"
}

At least one of name, description, or summary must be provided.

HTTP Status Codes: 200 OK, 400 Bad Request, 404 Not Found

Activating and deactivating an Omni Policy via API

Activate (DRAFT → ACTIVE):

HTTP
PATCH <MDS-URL>/api/v1/metadata/omni-policies/{id}/activate

Deactivate (ACTIVE → INACTIVE):

HTTP
PATCH <MDS-URL>/api/v1/metadata/omni-policies/{id}/deactivate

No request body. The policy must pass ACTIVE validation rules before activation succeeds.

HTTP Status Codes: 200 OK, 202 Accepted, 400 Bad Request, 404 Not Found

Deleting an Omni Policy via API

HTTP
DELETE <MDS-URL>/api/v1/metadata/omni-policies/{id}

HTTP Status Codes: 200 OK, 202 Accepted, 400 Bad Request, 404 Not Found


Omni Policy query APIs

Read-only endpoints for inspecting the assets and coverage of a policy.

Operation Method Path Success
Get assets for a policy GET /api/v1/metadata/omni-policies/{id}/assets 200
Get resource count for a policy GET /api/v1/metadata/omni-policies/{id}/summary 200
List policies by asset GET /api/v1/metadata/omni-policies/by-asset/{assetId} 200
Policy summary by identifier GET /api/v1/metadata/omni-policies/by-identifier/{identifierId}/summary 200

Get assets for a policy

Returns every asset attached to a policy via HAS_POLICY_ASSET edges, grouped by type.

HTTP
GET <MDS-URL>/api/v1/metadata/omni-policies/{id}/assets

Path Parameters:

  • id (required): Omni policy vertex ID

Response Fields:

  • policyId: Policy vertex ID
  • tags: Array of tag assets (name, vertex ID)
  • resources: Array of resource assets (vertex ID, resource path, type, service name)
  • dataProducts: Array of data-product assets (name, status, description, default tags)

All three lists are always present (empty when no assets of that type are attached).

HTTP Status Codes: 200 OK, 400 Bad Request, 404 Not Found

Get resource count for a policy

Returns the policy identity and the number of assets it governs.

HTTP
GET <MDS-URL>/api/v1/metadata/omni-policies/{id}/summary

Response Fields: policyId, policyName, policyType, policyStatus, resourceCount, userCount

List policies by asset

Returns policies linked to a given asset (via HAS_POLICY_ASSET). Use this endpoint to list every Omni policy that applies to a data product, tag, or resource.

HTTP
GET <MDS-URL>/api/v1/metadata/omni-policies/by-asset/{assetId}

Path Parameters:

  • assetId (required): Asset identifier — use the same id value as in applyPolicy.assets. Unlike the enforcement APIs, this endpoint has no {type} segment; pass the asset identifier directly.
Asset type {assetId} value Example
DATA_PRODUCT Data-product vertex ID dp-real-estate-portfolio
TAG Tag name (used as the vertex ID) CUSTOMER_DATA
RESOURCE Full resource path privacera_snowflake/PS_SF_DB/OMNI_SCHEMA/OMNI_TABLE_1

Query Parameters:

  • name (optional): Case-insensitive policy-name prefix filter
  • type (optional): ACCESS, MASKING, or RLF
  • sortBy (optional): name (default), type, createdAt, updatedAt, status
  • sortOrder (optional): asc or desc
  • page (optional): Zero-based page number (default: 0)
  • size (optional): Page size (default: 25)

Example Requests:

HTTP
GET <MDS-URL>/api/v1/metadata/omni-policies/by-asset/CUSTOMER_DATA?type=RLF&page=0&size=25
HTTP
GET <MDS-URL>/api/v1/metadata/omni-policies/by-asset/dp-real-estate-portfolio
HTTP
GET <MDS-URL>/api/v1/metadata/omni-policies/by-asset/privacera_snowflake/PS_SF_DB/OMNI_SCHEMA/OMNI_TABLE_1

URL encoding

When {assetId} contains slashes (resource paths), URL-encode the path segments in the request.

Response Fields:

  • eventTime, status, totalCount, number, pageSize, totalPages, hasNext, hasPrevious
  • content: Array of policy objects (same fields as the create response)
  • filters, sortBy, sortOrder

HTTP Status Codes: 200 OK, 400 Bad Request, 404 Not Found

Policy summary by identifier

Returns every policy referencing the identifier, each with its resource count, plus grand totals.

HTTP
GET <MDS-URL>/api/v1/metadata/omni-policies/by-identifier/{identifierId}/summary

Response Fields:

  • identifierId: Identifier vertex ID
  • policyCount: Number of policies referencing this identifier
  • totalResources / totalActiveResources: Distinct asset totals (all / ACTIVE only)
  • resourceCountByType / activeResourceCountByType: Per-type counts (for example, { "MASKING": 15, "RLF": 10 })
  • policies: Array of { policyId, policyName, policyType, policyStatus, resourceCount, userCount }

HTTP Status Codes: 200 OK, 400 Bad Request


Omni Policy enforcement APIs

Base path: /api/v1/metadata/omni-policies/enforcement

Grant or revoke Ranger policies on an asset, or manage direct access grants. The {type} path segment must be one of: tags, resources, data-products.

Operation Method Path Success
Grant policies POST /enforcement/grant/{type}/{assetId} 200
Revoke policies POST /enforcement/revoke/{type}/{assetId} 200
Grant access POST /enforcement/grant-access/{type}/{assetId} 200
Revoke access POST /enforcement/revoke-access/{type}/{assetId} 200
List grant-access GET /enforcement/grant-access/{type}/{assetId} 200

Grant / revoke policies

Push (grant) or remove (revoke) the Ranger policies defined by the supplied policy IDs on the asset.

HTTP
POST <MDS-URL>/api/v1/metadata/omni-policies/enforcement/grant/{type}/{assetId}
POST <MDS-URL>/api/v1/metadata/omni-policies/enforcement/revoke/{type}/{assetId}

Request Body:

JSON
1
2
3
{
  "omniPolicyIds": ["<policy-id-1>", "<policy-id-2>"]
}

At least one policy ID is required.

Grant / revoke access

Create or delete GRANTS_PERMISSION_TO edges (asset → principals), then re-sync the Ranger ACCESS policy for the asset.

HTTP
POST <MDS-URL>/api/v1/metadata/omni-policies/enforcement/grant-access/{type}/{assetId}
POST <MDS-URL>/api/v1/metadata/omni-policies/enforcement/revoke-access/{type}/{assetId}

Grant access — request body:

JSON
1
2
3
4
5
6
7
8
{
  "permission": "READ",
  "principals": {
    "users": ["david"],
    "groups": [],
    "roles": []
  }
}

permission must be READ or WRITE. At least one of users, groups, or roles must be non-empty.

Revoke access — request body:

JSON
1
2
3
4
5
6
7
{
  "principals": {
    "users": ["david"],
    "groups": [],
    "roles": []
  }
}

Omit permission on revoke. At least one of users, groups, or roles must be non-empty.

HTTP Status Codes: 200 OK, 400 Bad Request, 404 Not Found

List grant-access

Returns a paginated list of principals granted access on the asset, each with its permission.

HTTP
GET <MDS-URL>/api/v1/metadata/omni-policies/enforcement/grant-access/{type}/{assetId}

Query Parameters: principalType (USER, GROUP, ROLE), search, sortBy (name, type, permission), sortOrder, page, size (max 200).

Grant / revoke access by resource path (v2)

Grants or revokes READ or WRITE access on a resource, identified by its service name and path, for one or more users, groups, or roles.

If the resource — or any part of the path leading to it — does not already exist, it is created automatically. For example, granting access on a table that has not been added yet also creates its parent schema or catalog first, if those do not exist either.

Base path: /api/v2/metadata/omni-policies/enforcement

Operation Method Path Description Success
Grant access POST /enforcement/grant-access/resources Grants READ or WRITE access on a resource to one or more users, groups, or roles 200
Revoke access POST /enforcement/revoke-access/resources Revokes previously granted access on a resource from one or more users, groups, or roles 200
HTTP
1
2
3
POST <MDS-URL>/api/v2/metadata/omni-policies/enforcement/grant-access/resources
Authorization: Bearer <token>
Content-Type: application/json
HTTP
1
2
3
POST <MDS-URL>/api/v2/metadata/omni-policies/enforcement/revoke-access/resources
Authorization: Bearer <token>
Content-Type: application/json

On Data Plane and PrivaceraCloud, omit the Authorization header and use the API-key URL, including /omni-metadata, in place of <MDS-URL>. See Authentication.

Grant access — request body

JSON
{
  "resource": {
    "serviceName": "privacera_databricks_unity_catalog",
    "resourcePath": "cat1/db1/table1",
    "serviceType": "DATABRICKS_UNITY_CATALOG",
    "resourceType": "TABLE"
  },
  "grant": {
    "permission": "READ",
    "principals": {
      "users": [],
      "groups": [],
      "roles": ["role1"]
    }
  }
}

resource:

Field Required Description
serviceName Yes Name of the service the resource belongs to — the data source connection already added in Privacera (for example, a Databricks or Snowflake instance)
resourcePath Yes Full path to the resource within the service (for example, cat1/db1/table1)
serviceType No The service's type (for example, DATABRICKS_UNITY_CATALOG)
resourceType Yes The type of the resource you are granting or revoking access to (for example, TABLE for a table, SCHEMA for a schema)

grant:

Field Required Description
permission Yes READ or WRITE
principals Yes At least one of users, groups, or roles must be non-empty
principals.users No Usernames to grant access to
principals.groups No Group names to grant access to
principals.roles No Role names to grant access to

Revoke access — request body

JSON
{
  "resource": {
    "serviceName": "privacera_databricks_unity_catalog",
    "resourcePath": "cat1/db1/table1",
    "serviceType": "DATABRICKS_UNITY_CATALOG",
    "resourceType": "TABLE"
  },
  "revoke": {
    "principals": {
      "users": [],
      "groups": [],
      "roles": ["role1"]
    }
  }
}

resource: same fields as above.

revoke:

Field Required Description
principals Yes Same shape as grant.principals above. At least one of users, groups, or roles must be non-empty

Behavior

Grant and revoke are incremental

Grant and revoke operations affect only the principals specified in the request.

Granting access to a principal does not change access for other principals that already have access to the resource. Similarly, revoking access for one principal does not affect any other principal.

You do not need to send the complete list of principals with each request.

One permission per grant request

A grant request applies one permission value to all principals in the request.

For example, to grant READ to role1 and WRITE to role2, make two requests:

JSON
1
2
3
4
5
6
{
  "permission": "READ",
  "principals": {
    "roles": ["role1"]
  }
}
JSON
1
2
3
4
5
6
{
  "permission": "WRITE",
  "principals": {
    "roles": ["role2"]
  }
}
One resource per request

The resource field accepts a single resource. To grant the same access to multiple resources, make one request for each resource.

For example, to grant READ access to role1 on table1 and table2, make one request per resource, changing only resourcePath:

  • cat1/db1/table1
  • cat1/db1/table2

HTTP status codes

Status Description
200 OK Request completed successfully.
400 Bad Request The request is invalid, such as a missing required field or invalid value.
403 Forbidden The caller is not authorized to perform the operation.

Masking function support API

Returns each masking function with the service types that support it (and those that do not), plus services with no masking support at all. Use it to check compatibility before choosing a masking action.

HTTP
GET <MDS-URL>/api/v1/metadata/masking-functions/service-support

Response Fields:

  • masking_functions: Map of masking function → { "supported": [services], "not_supported": [services] }
  • services_without_masking_support: Services that support no masking functions

HTTP Status Codes: 200 OK


Omni Policy examples

The examples below use the Acme scenarios. Replace placeholder IDs with values from your environment and from the identifier examples above.

Policy name API type Action Identifiers used
Employee portfolio access ACCESS READ user_identifier
Allowed properties to view RLF ALLOW record_identifier (+ principals)
Restrict Texas data from offshore users RLF DENY user_identifier, record_identifier
Texas data for offshore users with consent RLF ALLOW user_identifier, record_identifier
Redact sensitive data MASKING MASK (MASK_NULL) column_identifier

ACCESS — Employee portfolio access

Goal: Let all employees read the REAL_ESTATE_PORTFOLIO data product, so a new hire is covered automatically. whoQuery is the Employees user identifier ID; applyPolicy.assets scopes the policy to the data product.

HTTP
POST <MDS-URL>/api/v1/metadata/omni-policies
JSON
{
  "name": "Employee portfolio access",
  "description": "Employees can read the property portfolio",
  "type": "ACCESS",
  "status": "ACTIVE",
  "actions": [{ "action": "READ" }],
  "identifiers": {
    "user_identifier": ["<employees-id>"]
  },
  "whoQuery": "<employees-id>",
  "applyPolicy": {
    "assets": [{ "type": "DATA_PRODUCT", "id": "<real-estate-portfolio-id>" }]
  }
}

RLF — Allowed properties to view

Goal: Regional managers (david, emily) see only rows for their own region. dataFiltersQuery is the Allowed Properties by Region Access record identifier ID (that Identifier holds the row filter expression).

HTTP
POST <MDS-URL>/api/v1/metadata/omni-policies
JSON
{
  "name": "Allowed properties to view",
  "type": "RLF",
  "status": "ACTIVE",
  "actions": [{ "action": "ALLOW" }],
  "identifiers": {
    "record_identifier": ["<region-access-id>"]
  },
  "dataFiltersQuery": "<region-access-id>",
  "applyPolicy": {
    "assets": [{ "type": "DATA_PRODUCT", "id": "<real-estate-portfolio-id>" }],
    "principals": [
      { "type": "USER", "name": "david" },
      { "type": "USER", "name": "emily" }
    ]
  }
}

RLF — Restrict Texas data from offshore users

Goal: Hide Texas customer rows from offshore users across all tables tagged CUSTOMER_DATA. The DENY action drops matching rows. whoQuery and dataFiltersQuery are the offshore-user and Texas-data identifier IDs.

HTTP
POST <MDS-URL>/api/v1/metadata/omni-policies
JSON
{
  "name": "Restrict Texas data from offshore users",
  "type": "RLF",
  "status": "ACTIVE",
  "actions": [{ "action": "DENY" }],
  "identifiers": {
    "user_identifier": ["<offshore-users-id>"],
    "record_identifier": ["<texas-data-id>"]
  },
  "whoQuery": "<offshore-users-id>",
  "dataFiltersQuery": "<texas-data-id>",
  "applyPolicy": {
    "assets": [{ "type": "TAG", "id": "CUSTOMER_DATA" }]
  }
}

Goal: Allow offshore users to see Texas rows, but only for customers who gave consent. Same scope as the previous policy; dataFiltersQuery is the consent record identifier ID.

HTTP
POST <MDS-URL>/api/v1/metadata/omni-policies
JSON
{
  "name": "Texas data for offshore users with consent",
  "type": "RLF",
  "status": "ACTIVE",
  "actions": [{ "action": "ALLOW" }],
  "identifiers": {
    "user_identifier": ["<offshore-users-id>"],
    "record_identifier": ["<consent-data-id>"]
  },
  "whoQuery": "<offshore-users-id>",
  "dataFiltersQuery": "<consent-data-id>",
  "applyPolicy": {
    "assets": [{ "type": "TAG", "id": "CUSTOMER_DATA" }]
  }
}

MASKING — Redact sensitive data

Goal: Mask sensitive financial columns for everyone (including data owners) on the REAL_ESTATE_TENANTS data product. MASK_NULL replaces values with NULL; dataQuery is the Sensitive financial columns column identifier ID. principals is GROUP public so it applies to all users.

HTTP
POST <MDS-URL>/api/v1/metadata/omni-policies
JSON
{
  "name": "Redact sensitive data",
  "description": "Mask sensitive financial columns for all users",
  "type": "MASKING",
  "status": "ACTIVE",
  "actions": [
    {
      "action": "MASK",
      "masking": { "type": "MASK_NULL" }
    }
  ],
  "identifiers": {
    "column_identifier": ["<sensitive-columns-id>"]
  },
  "dataQuery": "<sensitive-columns-id>",
  "applyPolicy": {
    "assets": [{ "type": "DATA_PRODUCT", "id": "<real-estate-tenants-id>" }],
    "principals": [{ "type": "GROUP", "name": "public" }]
  }
}

Draft-first workflow

JSON
1
2
3
4
5
{
  "name": "Employee portfolio access",
  "type": "ACCESS",
  "status": "DRAFT"
}

After adding actions, identifiers, and applyPolicy via PUT, activate:

HTTP
PATCH <MDS-URL>/api/v1/metadata/omni-policies/<policy-id>/activate