> For the complete documentation index, see [llms.txt](https://docs.veza.com/4yItIzMvkpAvMVFAamTf/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.veza.com/4yItIzMvkpAvMVFAamTf/developers/api/management/owners/batchsetowners.md).

# Batch set owners

**Endpoint:** `POST {veza_url}/api/v1/batch_set_owners`\
**Authentication:** Bearer token (`admin`, `operator`, or `nhi_security_admin` role)

Assigns, adds, or removes owners across multiple entities in a single bulk operation. Unlike the private owners API, this endpoint queries existing owner state internally — callers do not need to fetch current ownership before making changes.

Owner updates are applied asynchronously and typically reflect within a few seconds.

***

## Minimal Working Example

Assign one owner to one entity:

```bash
curl -X POST "https://your-tenant.veza.com/api/v1/batch_set_owners" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "batches": [
      {
        "entity_type": "AwsIamUser",
        "entity_ids": ["aws-iam-user-abc123"],
        "assigned_owners": {
          "owners": [
            {
              "entity_id": "okta-user-xyz789",
              "entity_type": "OktaUser"
            }
          ]
        }
      }
    ]
  }'
```

A `200 OK` with an empty body indicates success.

***

## Request Structure

### Top-Level

| Field     | Type             | Required | Description                                                                                                                                                       |
| --------- | ---------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `batches` | array of `Batch` | Yes      | One or more batches of entity updates. All batches are validated before any are applied. Maximum 1,000 total entities and 1,000 unique owners across all batches. |

### Batch Object

Each batch targets a set of entities of the same type and applies the same owner operation to all of them.

| Field                        | Type               | Required | Description                                                                                                                                                               |
| ---------------------------- | ------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `entity_type`                | string             | Yes      | Type of the entities in this batch (e.g., `AwsIamUser`). All entities must be the same type.                                                                              |
| `entity_ids`                 | array of string    | Yes      | Veza entity IDs to update. All entities in the batch receive the same owner operation.                                                                                    |
| `assigned_owners`            | `OwnersAssignment` | No       | Owners to assign. Replaces the entity's manually-assigned owners. Permanently removed owners are not re-added even if listed here. Omit (not empty) to skip.              |
| `added_owners`               | array of `Owner`   | No       | Owners to add. Applied after `assigned_owners`. Un-removes any owner that was previously permanently removed.                                                             |
| `removed_owners_incremental` | array of `Owner`   | No       | Owners to permanently remove from the entity regardless of source. Applied after `assigned_owners` and `added_owners`. Appended to any existing permanently-removed list. |
| `removed_owners_update`      | `OwnersAssignment` | No       | Owners to permanently remove. Replaces the existing permanently-removed list (overrides `removed_owners_incremental`). Omit (not empty) to skip.                          |

### OwnersAssignment Object

| Field    | Type             | Description                                                                                                                                                                            |
| -------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `owners` | array of `Owner` | The owners for this assignment. An empty array assigns with no owners (clears existing). To skip the operation entirely, omit the parent field instead of passing an empty assignment. |

### Owner Object

Each owner is resolved in one of two ways:

* **By ID** — provide `entity_id` + `entity_type` for a direct lookup.
* **By external property** — provide `external_id` + `external_property_name` + `entity_type` to match an entity whose named property equals the given value.

An owner that cannot be resolved to a single existing entity returns an invalid argument error.

**Example — resolve by external property:**

```json
{
  "entity_type": "OktaUser",
  "external_property_name": "email",
  "external_id": "owner@example.com"
}
```

This finds the `OktaUser` whose `email` property equals `owner@example.com`.

| Field                    | Type   | Required    | Description                                                                                                                                                                                                                        |
| ------------------------ | ------ | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `entity_id`              | string | Conditional | ID of the owner entity. If provided, the owner is resolved by `(entity_type, entity_id)`. Omit to resolve by external property instead.                                                                                            |
| `entity_type`            | string | Yes         | Type of the owner (e.g., `OktaUser`). Required for all lookups.                                                                                                                                                                    |
| `primary`                | bool   | No          | Reserved. Must **not** be set in input. Setting it to `true` returns an invalid argument error.                                                                                                                                    |
| `external_id`            | string | Conditional | Value to match when resolving the owner by external property. Used only when `entity_id` is omitted. Must be paired with `external_property_name`.                                                                                 |
| `external_property_name` | string | Conditional | Name of the entity property to match `external_id` against (e.g., `email`, `idp_unique_id`). Used only when `entity_id` is omitted. If your tenant has a Global IdP configured, this defaults to the configured identity property. |
| `entity_name`            | string | No          | Optional display name for the owner.                                                                                                                                                                                               |

***

## Update Strategies

The four owner operation fields interact in a defined precedence order. All operations in a batch are applied together to each entity:

| Strategy                 | Field                        | Precedence | Effect                                                                                                                            |
| ------------------------ | ---------------------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------- |
| **Assign**               | `assigned_owners`            | 1st        | Replaces all manually-assigned owners. Does not un-remove permanently-removed owners.                                             |
| **Add**                  | `added_owners`               | 2nd        | Appends owners. If an owner was permanently removed, this un-removes them.                                                        |
| **Remove (incremental)** | `removed_owners_incremental` | 3rd        | Permanently removes owners regardless of source. Appended to any existing permanently-removed list.                               |
| **Remove (replace)**     | `removed_owners_update`      | 4th        | Permanently removes owners. Replaces the entire permanently-removed list. Overrides `removed_owners_incremental` if both are set. |

> **Note on permanently removed owners:** When an owner is added to the permanently-removed list (via `removed_owners_incremental` or `removed_owners_update`), they will not reappear even if an enrichment rule or `assigned_owners` would otherwise include them — unless `added_owners` explicitly un-removes them.

***

## Common Use Cases

### 1. Assign owners to many entities at once

Use `assigned_owners` to set a definitive owner list across many entities. Existing manually-assigned owners are replaced; enrichment-sourced owners are unaffected.

```json
{
  "batches": [
    {
      "entity_type": "AwsS3Bucket",
      "entity_ids": ["bucket-1", "bucket-2", "bucket-3"],
      "assigned_owners": {
        "owners": [{"entity_id": "okta-user-xyz", "entity_type": "OktaUser"}]
      }
    }
  ]
}
```

### 2. Add owners without clearing existing

Use `added_owners` to append owners without disturbing what's already there.

```json
{
  "batches": [
    {
      "entity_type": "VirtualMachine",
      "entity_ids": ["vm-abc"],
      "added_owners": [
        {"external_id": "ops-team@example.com", "entity_type": "OktaUser", "external_property_name": "email"}
      ]
    }
  ]
}
```

### 3. Permanently block an enriched owner from returning

Use `removed_owners_incremental` to prevent a specific owner from being re-added by enrichment rules on the next sync.

```json
{
  "batches": [
    {
      "entity_type": "AwsIamRole",
      "entity_ids": ["role-xyz"],
      "removed_owners_incremental": [
        {"entity_id": "okta-user-former", "entity_type": "OktaUser"}
      ]
    }
  ]
}
```

### 4. Mixed batch across entity types

Target different entity types in separate batches within a single request.

```json
{
  "batches": [
    {
      "entity_type": "AwsIamUser",
      "entity_ids": ["iam-user-1", "iam-user-2"],
      "assigned_owners": {
        "owners": [{"entity_id": "okta-user-xyz", "entity_type": "OktaUser"}]
      }
    },
    {
      "entity_type": "GithubRepo",
      "entity_ids": ["repo-abc"],
      "added_owners": [
        {"external_id": "dev-lead@example.com", "entity_type": "OktaUser", "external_property_name": "email"}
      ]
    }
  ]
}
```

***

## Limits

| Constraint                        | Limit |
| --------------------------------- | ----- |
| Total entities across all batches | 1,000 |
| Unique owners across all batches  | 1,000 |

***

## Common Errors

**400: Unknown or unprovisioned `entity_type`**

The owner's `entity_type` is not a known node type in the graph — the integration may not be provisioned, or the type string is incorrect.

```json
{
  "code": "InvalidArgument",
  "message": "Invalid Arguments",
  "details": [{"field_violations": [{"field": "types", "description": "Must supply at least one valid type"}]}]
}
```

Fix: Verify the integration for that owner type is provisioned in Veza. Check the exact `entity_type` string via Graph Search or `GET /api/v1/providers/custom`.

**400: Owner type not allowed as an owner**

The `entity_type` provided is a resource type (e.g., `AwsS3Bucket`), not a user or identity type.

```json
{
  "code": "InvalidArgument",
  "details": [{"field_violations": [{"field": "entity_type", "description": "issue with entity {external_id}: owner not of an allowed type"}]}]
}
```

Fix: Use an identity provider user type. See [Owner Type Reference](#owner-type-reference).

**400: Owner not found**

The `external_id` value does not match any entity in Veza. Verify that `external_property_name` refers to a property that exists on the owner entity type, and that `external_id` matches an actual value for that property. Check entity properties via Graph Search.

***

## Owner Type Reference

**Native identity providers:**

| Identity Provider       | `entity_type`         |
| ----------------------- | --------------------- |
| Okta                    | `OktaUser`            |
| Azure AD                | `AzureADUser`         |
| Active Directory        | `ActiveDirectoryUser` |
| Ping Identity           | `PingOneUser`         |
| OneLogin                | `OneLoginUser`        |
| AWS IAM Identity Center | `AwsSsoUser`          |
| Google Workspace        | `GoogleWorkspaceUser` |

**OAA custom providers:**

| OAA Template                     | `entity_type`                  |
| -------------------------------- | ------------------------------ |
| Custom IdP (`identity_provider`) | `OAA.{idp_type}.IDPUser`       |
| HRIS (`hris`)                    | `OAA.{hris_type}.HRISEmployee` |

The `{idp_type}` and `{hris_type}` values come from the `idp_type` or `hris_type` field in your OAA payload.

> **OAA HRIS employees:** To use property-based lookup for HRIS employee owners, set `external_property_name` to a property that exists on the HRIS entity (e.g., `employee_number` or `personal_email`). The default `idp_unique_id` property may not exist on HRIS entities.

**Finding your custom type:**

* **UI:** Access Visibility → Graph → search for a user → View Details → copy the `entity_type`
* **API:** `GET /api/v1/providers/custom`

***

## Verification

After the API returns, verify ownership changes via:

1. **Graph Search:** Access Visibility → Graph → find entity → Entity Owners section
2. **Query Builder (VQL):**

   ```
   SHOW AwsIamUser
   WHERE entity_id = "your-entity-id"
   ```
3. **NHI Dashboard:** NHI Security → Accounts → Entity Owner column


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.veza.com/4yItIzMvkpAvMVFAamTf/developers/api/management/owners/batchsetowners.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
