> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cortex.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Bulk accept entity data verifications

> Let owners accept verification for all of their entities in one run, instead of one entity at a time

export const RecipeBadges = ({badges = []}) => {
  const map = {
    "recipe": {
      label: "Recipe",
      color: "#A86400"
    },
    "ai-excellence": {
      label: "AI excellence",
      color: "#653EE8"
    },
    "production-readiness": {
      label: "Production readiness",
      color: "#226686"
    },
    "incident-mgmt": {
      label: "Incident management",
      color: "#86198F"
    },
    "migrations": {
      label: "Migrations",
      color: "#0E7C66"
    },
    "compliance": {
      label: "Compliance",
      color: "#475569"
    },
    "dora": {
      label: "DORA metrics",
      color: "#1D4ED8"
    },
    "security": {
      label: "Security",
      color: "#B42318"
    },
    "operational-readiness": {
      label: "Operational readiness",
      color: "#B54708"
    },
    "dev-onboarding": {
      label: "Developer onboarding",
      color: "#C11574"
    }
  };
  const items = badges.map(key => map[key]).filter(Boolean);
  if (items.length === 0) return null;
  return <div className="not-prose flex flex-wrap gap-2 mb-6">
      {items.map(b => <span key={b.label} className="rounded-lg px-2 py-1 text-xs font-medium" style={{
    backgroundColor: b.color,
    color: b.textColor || "#FFFFFF"
  }}>
          {b.label}
        </span>)}
    </div>;
};

<RecipeBadges badges={["recipe", "compliance"]} />

This guide explains how to use a Workflow to let entity owners accept verification for many entities at once during a [verification period](/configure/settings/entity-settings/verification).

By default, owners verify entities one at a time from each entity's page. With this Workflow, an owner picks an open verification period, selects the entities they own, and marks all of them as verified correct in a single run.

<Tip>
  Link to this Workflow in your verification period's **Verification instructions**, for example: *"To bulk accept the entities you own, run the Bulk Entity Verification workflow: \[link]"*. Owners can then choose to verify one entity from its entity page, or open the Workflow to accept several at once.
</Tip>

## Create a Workflow to bulk accept entity verifications

### Prerequisites

Before getting started:

* You must have the `Edit Workflows` [permission](/configure/settings/managing-users/permissioning) to create the Workflow, and the `Execute Workflow runs` permission to run it.
* To verify entities, at least one verification period must be open. If none are open, the run ends with a "No open verification periods found" message and nothing is verified.
* The person running the Workflow must own the entities they verify, and hold any roles the verification period requires.

### Step 1: Create the Workflow

You can create a Workflow in the Cortex UI or via the Cortex CLI.

<Tabs>
  <Tab title="Cortex CLI">
    #### Add the Workflow via CLI

    You can use the [Cortex CLI](https://pypi.org/project/cortexapps-cli/) to add the example Workflow to your workspace. This allows you to quickly set up the example configuration then iterate on it for your own use case. Expand the tile below to learn more:

    <Accordion title="Import the Workflow via CLI">
      1. Save the Workflow example YAML file below:

      ```yaml theme={null} theme={null}
      name: Bulk Entity Verification
      tag: bulk-entity-verification
      description: Select entities you own and mark them all as verified correct for an open verification period in one step.
      isDraft: true
      isRunnableViaApi: false
      restrictActionCompletionToRunnerUser: true
      iconTag: CheckCircle
      filter:
        type: GLOBAL
      runRestrictionPolicies: []
      variables:
        - slug: result-message
          type: STRING
          defaultValue: ""
          description: Summary shown as the run response; set by whichever path the run takes.
      runResponseTemplate: "{{variables.result-message}}"
      failedRunResponseTemplate: Bulk verification failed. Check the failed step's output for details.
      actions:
        - name: Fetch open verification periods
          slug: fetch-periods
          isRootAction: true
          outgoingActions:
            - format-periods
          schema:
            type: HTTP_REQUEST
            httpMethod: GET
            url: /api/v1/verification-periods?isActive=true&pageSize=250&page=0
            integration: Cortex
            headers:
              Accept: application/json

        - name: Format periods for dropdown
          slug: format-periods
          isRootAction: false
          outgoingActions:
            - check-periods
          schema:
            type: JQ
            expression: >-
              .actions["fetch-periods"].outputs.body
              | (if type == "string" then fromjson else . end)
              | (.periods // [])
              | map("\(.name) (\(.cid))")

        - name: Any open periods?
          slug: check-periods
          isRootAction: false
          outgoingActions:
            - select-entities
            - no-periods-message
          schema:
            type: CONDITIONAL_BRANCH
            branches:
              - type: CONDITIONAL
                slug: has-open-periods
                name: Open periods found
                expression: size(actions["format-periods"].outputs.result) > 0
                outgoingAction: select-entities
            fallbackBranch:
              type: FALLBACK
              slug: no-open-periods
              name: No open periods
              outgoingAction: no-periods-message

        - name: Set 'no periods found' message
          slug: no-periods-message
          isRootAction: false
          outgoingActions: []
          schema:
            type: SET_VARIABLES
            variables:
              - slug: result-message
                source:
                  type: JAVASCRIPT
                  script: >-
                    return "No open verification periods found. Nothing was verified.
                    Ask an admin to open a verification period, then run this workflow again.";

        - name: Select entities to verify
          slug: select-entities
          isRootAction: false
          outgoingActions:
            - build-payload
          schema:
            type: USER_INPUT
            jsValidatorScript: ""
            inputOverrides:
              - type: OPTION
                inputKey: period
                outputVariable: actions.format-periods.outputs.result
            inputs:
              - type: SELECT_FIELD
                key: period
                name: Verification period
                description: Open verification periods in this workspace.
                required: true
                allowAdditionalOptions: false
                options: []
              - type: CORTEX_ENTITY_FIELD
                key: entities
                name: Entities to verify
                description: Choose the entities you own that you confirm are correct. Only entities you own are listed.
                required: true
                allowMultiple: true
                limitEntitiesToRunnerUserScope: true
                shouldDisplayOptionsAsHierarchy: false
                entityFilter: {}
              - type: TOGGLE_FIELD
                key: confirm
                name: I confirm these entities' details are correct
                required: true
                defaultValue: false

        - name: Build verification payload
          slug: build-payload
          isRootAction: false
          outgoingActions:
            - bulk-verify
          schema:
            type: JQ
            expression: |-
              .actions["select-entities"].outputs as $in
              | if ($in.confirm != true) then
                  error("Confirmation toggle was not turned on; nothing was verified.")
                else
                  ($in.period | capture("\\((?<cid>vp[0-9a-zA-Z]+)\\)$").cid) as $period
                  | ($in.entities
                      | if type == "array" then . else [.] end
                      | map(if type == "object" then (.tag // .cid) else . end)) as $tags
                  | {
                      count: ($tags | length),
                      periodCid: $period,
                      body: ({verifications: [$tags[] | {entity: ., periodCid: $period, status: "VERIFIED_CORRECT"}]} | tojson)
                    }
                end

        - name: Bulk verify
          slug: bulk-verify
          isRootAction: false
          outgoingActions:
            - result-summary
          schema:
            type: HTTP_REQUEST
            httpMethod: PUT
            url: /api/v1/verifications
            integration: Cortex
            headers:
              Content-Type: application/json
            payload: "{{{actions.build-payload.outputs.result.body}}}"

        - name: Set result summary
          slug: result-summary
          isRootAction: false
          outgoingActions: []
          schema:
            type: SET_VARIABLES
            variables:
              - slug: result-message
                source:
                  type: JAVASCRIPT
                  script: |-
                    const raw = actions["bulk-verify"].outputs.body;
                    let body = raw || {};
                    if (typeof raw === "string") { try { body = JSON.parse(raw); } catch (e) { body = { raw: raw }; } }
                    const sent = actions["build-payload"].outputs.result.count;
                    const period = actions["select-entities"].outputs.period;
                    const errors = Array.isArray(body.errors) ? body.errors : [];
                    const noun = (n) => n === 1 ? "entity" : "entities";
                    if (errors.length === 0) {
                      return `Verified ${sent} ${noun(sent)} as correct for ${period}.`;
                    }
                    const ok = Math.max(sent - errors.length, 0);
                    return `Submitted ${sent} ${noun(sent)} for ${period}: ${ok} verified, ${errors.length} failed.\n` + errors.map(e => "- " + (typeof e === "string" ? e : JSON.stringify(e))).join("\n");
      ```

      2. Use the [Cortex CLI](https://pypi.org/project/cortexapps-cli/) to run this command, using the path to your Workflow YAML file: `cortex workflows create -f <path-to-your-workflow.yaml>`
    </Accordion>
  </Tab>

  <Tab title="Cortex UI">
    #### Step 1.1: Create the Workflow and configure basic settings

    1. In Cortex, navigate to **Workflows**. In the upper right corner, click **+Create workflow**. Choose a blank Workflow.
    2. Follow the documentation to [configure the basic settings for your Workflow](/streamline/workflows/create#creating-a-workflow).
       * In this example, we use the name `Bulk Entity Verification`.
       * Leave the scope set to **Global**, so the Workflow isn't tied to a single entity.
    3. In the Workflow settings, add a variable:
       * **Slug**: `result-message`
       * **Type**: String
    4. Set the **Run response template** to `{{variables.result-message}}`.

    #### Step 1.2: Add blocks to the Workflow

    Add the following blocks to your Workflow:

    <AccordionGroup>
      <Accordion title="Fetch open verification periods">
        This block gets the verification periods that are open today.

        1. Click **+** in the center of the page. In the block library modal, choose **HTTP request**.
        2. In the block configuration side panel, enter a name and unique slug for this block.
           * In this example, we use the name `Fetch open verification periods` and the slug `fetch-periods`.
        3. Configure the block:
           * **HTTP method**: GET
           * **Integration**: Cortex
           * **URL**: `/api/v1/verification-periods?isActive=true&pageSize=250&page=0`
           * **Headers**: `Accept: application/json`
        4. At the bottom of the side panel, click **Save**.
      </Accordion>

      <Accordion title="Format periods for dropdown">
        This block turns each open period into a dropdown option such as `Q4 ownership review (vp0a1b2c3d4e5f6789)`, so users see the period name and the Workflow keeps its ID.

        1. Click **+** below the previous block. In the block library modal, choose **JQ**.
        2. In the side panel, enter a name and unique slug for the block.
           * In this example, we use the name `Format periods for dropdown` and the slug `format-periods`.
        3. Enter the following JQ expression:

        ```jq theme={null} theme={null}
        .actions["fetch-periods"].outputs.body
        | (if type == "string" then fromjson else . end)
        | (.periods // [])
        | map("\(.name) (\(.cid))")
        ```

        4. At the bottom of the side panel, click **Save**.
      </Accordion>

      <Accordion title="Any open periods?">
        This block stops the run with a clear message when no verification period is open.

        1. Click **+** below the previous block. In the block library modal, choose **Branch**.
        2. In the side panel, enter a name and unique slug for the block.
           * In this example, we use the name `Any open periods?` and the slug `check-periods`.
        3. Add a conditional branch:
           * **Name**: Open periods found
           * **Slug**: `has-open-periods`
           * **Expression**: `size(actions["format-periods"].outputs.result) > 0`
        4. Name the fallback branch `No open periods`, with the slug `no-open-periods`.
        5. At the bottom of the side panel, click **Save**.
      </Accordion>

      <Accordion title="Set 'no periods found' message">
        On the **No open periods** branch, this block sets the message the user sees.

        1. On the **No open periods** branch, click **+**. In the block library modal, choose **Set variables**.
        2. In the side panel, enter a name and unique slug for the block.
           * In this example, we use the name `Set 'no periods found' message` and the slug `no-periods-message`.
        3. Set the `result-message` variable using JavaScript:

        ```javascript theme={null} theme={null}
        return "No open verification periods found. Nothing was verified. Ask an admin to open a verification period, then run this workflow again.";
        ```

        4. At the bottom of the side panel, click **Save**.
      </Accordion>

      <Accordion title="Select entities to verify">
        On the **Open periods found** branch, this block collects the period, the entities, and a confirmation from the user.

        1. On the **Open periods found** branch, click **+**. In the block library modal, choose **User input**.
        2. In the side panel, enter a name and unique slug for the block.
           * In this example, we use the name `Select entities to verify` and the slug `select-entities`.
        3. Click **+Add user input**. Add the following:
           * **Name**: Verification period
           * **Key**: period
           * **Type**: Select
           * **Path to override value**: `actions.format-periods.outputs.result`
           * Click **Add input**.
        4. Click **+Add user input**. Add the following:
           * **Name**: Entities to verify
           * **Key**: entities
           * **Type**: Select
           * **Data source**: Cortex entity
           * Enable **Allow multiple**, and limit the options to entities the runner owns.
           * Click **Add input**.
        5. Click **+Add user input**. Add the following:
           * **Name**: I confirm these entities' details are correct
           * **Key**: confirm
           * **Type**: Toggle
           * Click **Add input**.
        6. At the bottom of the side panel, click **Save**.
      </Accordion>

      <Accordion title="Build verification payload">
        This block checks that the user turned on the confirmation toggle, reads the period ID from the selected option, and builds one request body for all of the selected entities.

        1. Click **+** below the previous block. In the block library modal, choose **JQ**.
        2. In the side panel, enter a name and unique slug for the block.
           * In this example, we use the name `Build verification payload` and the slug `build-payload`.
        3. Enter the following JQ expression:

        ```jq theme={null} theme={null}
        .actions["select-entities"].outputs as $in
        | if ($in.confirm != true) then
            error("Confirmation toggle was not turned on; nothing was verified.")
          else
            ($in.period | capture("\\((?<cid>vp[0-9a-zA-Z]+)\\)$").cid) as $period
            | ($in.entities
                | if type == "array" then . else [.] end
                | map(if type == "object" then (.tag // .cid) else . end)) as $tags
            | {
                count: ($tags | length),
                periodCid: $period,
                body: ({verifications: [$tags[] | {entity: ., periodCid: $period, status: "VERIFIED_CORRECT"}]} | tojson)
              }
          end
        ```

        4. At the bottom of the side panel, click **Save**.
      </Accordion>

      <Accordion title="Bulk verify">
        This block sends every selected entity to the [bulk verification endpoint](/api/rest/verifications#put-api-v1-verifications) in a single request.

        1. Click **+** below the previous block. In the block library modal, choose **HTTP request**.
        2. In the side panel, enter a name and unique slug for the block.
           * In this example, we use the name `Bulk verify` and the slug `bulk-verify`.
        3. Configure the block:
           * **HTTP method**: PUT
           * **Integration**: Cortex
           * **URL**: `/api/v1/verifications`
           * **Headers**: `Content-Type: application/json`
           * **Payload**: `{{{actions.build-payload.outputs.result.body}}}`
        4. At the bottom of the side panel, click **Save**.
      </Accordion>

      <Accordion title="Set result summary">
        This block sets the message the user sees after the bulk request. It reports how many entities were verified and lists any that failed.

        1. Click **+** below the previous block. In the block library modal, choose **Set variables**.
        2. In the side panel, enter a name and unique slug for the block.
           * In this example, we use the name `Set result summary` and the slug `result-summary`.
        3. Set the `result-message` variable using JavaScript:

        ```javascript theme={null} theme={null}
        const raw = actions["bulk-verify"].outputs.body;
        let body = raw || {};
        if (typeof raw === "string") { try { body = JSON.parse(raw); } catch (e) { body = { raw: raw }; } }
        const sent = actions["build-payload"].outputs.result.count;
        const period = actions["select-entities"].outputs.period;
        const errors = Array.isArray(body.errors) ? body.errors : [];
        const noun = (n) => n === 1 ? "entity" : "entities";
        if (errors.length === 0) {
          return `Verified ${sent} ${noun(sent)} as correct for ${period}.`;
        }
        const ok = Math.max(sent - errors.length, 0);
        return `Submitted ${sent} ${noun(sent)} for ${period}: ${ok} verified, ${errors.length} failed.\n` + errors.map(e => "- " + (typeof e === "string" ? e : JSON.stringify(e))).join("\n");
        ```

        4. At the bottom of the side panel, click **Save**.
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

### Step 2: Run the Workflow

In the list of Workflows, locate the "Bulk Entity Verification" Workflow and click **Run**.

When you run the Workflow, the following events happen:

1. The Workflow retrieves the verification periods that are open today and formats them as dropdown options.
2. If no period is open, the run ends with the message "No open verification periods found." Nothing is verified.
3. If at least one period is open, the Workflow pauses to collect a response from the user during the User input block. The user selects a verification period, selects one or more entities they own, and turns on the confirmation toggle.
4. The JQ block checks the confirmation toggle. If it is off, the run fails and nothing is verified. Otherwise, it builds a single request that marks each selected entity as `VERIFIED_CORRECT` for the selected period.
5. The HTTP request block sends the request to the bulk verification endpoint.
6. The Workflow sets the run response to a summary of the result, such as "Verified 3 entities as correct for Q4 ownership review (vp0a1b2c3d4e5f6789)."

<Note>
  The bulk verification endpoint evaluates each entity separately. It can return `200 OK` even when some entities were not recorded, for example because the user doesn't own them. Those entities appear under `errors` in the response, and the Workflow lists them in the run summary.
</Note>


## Related topics

- [Workflows](/guides/product-areas/workflows.md)
- [Verify services after AI-based auto-mapping](/guides/ai-excellence/verify-auto-mappings.md)
- [Verifications](/api/rest/verifications.md)
