# DEXPRO AWF External Approvals — Setup Guide

> **Audience:** customers / admins installing and configuring the feature.
> 
> **Maintaining the Power Automate flow itself?** See [`POWERAUTOMATE-DEV-GUIDE.md`](https://docs.squeeze.one/link/1331) (DEXPRO developers / advanced admins).
> 
> **Building a non-Teams integration on top of the SharePoint list?** See [`SHAREPOINT-CONTRACT.md`](https://docs.squeeze.one/link/1332).
> 
> **Building a custom portal or app that calls BC directly?** See [`API-INTEGRATION-GUIDE.md`](https://docs.squeeze.one/link/1329) — no SharePoint setup needed.

## Overview

The DEXPRO Advanced Workflow (AWF) **External Approvals** feature lets approvers act on approval entries directly from Microsoft Teams — or from any other system that can read and write to a SharePoint list — without ever opening the Business Central web client. This lets organizations include managers, department heads, or other stakeholders in approval workflows from the tools they already use.

> **Licensing — customer/partner responsibility:** Acting on Business Central data still requires each approver to hold an appropriate paid Business Central user licence; a Microsoft 365 licence alone is not sufficient. DEXPRO makes no licensing representation — the customer and their Microsoft licensing partner are responsible for confirming the exact requirement with Microsoft. See [Prerequisites](#bkmrk-prerequisites) and the licensing note in [`API-INTEGRATION-GUIDE.md`](https://docs.squeeze.one/link/1329).

> **Integrating a non-Teams system?** The SharePoint list is the contract. See [`SHAREPOINT-CONTRACT.md`](https://docs.squeeze.one/link/1332) for the full integration reference, column definitions, state machine, and sample payloads. This setup guide focuses on the Teams / Power Automate reference implementation.
> 
> **Approving directly in SharePoint:** the list uses typed columns — `ApprovalStatus` is a dropdown, `ResponseDateTime` has a native date picker, `ResponseComment` is a multi-line text area. An approver with SharePoint access can open a pending item and approve it directly from the list edit form without Teams or Power Automate. BC's polling Job Queue picks it up on the next cycle.

### How It Works

When an approval entry is assigned to an external approver, Business Central writes the approval request to a **SharePoint list** via the Microsoft Graph API. A **Power Automate flow** detects the new list item and sends the approver a rich **Adaptive Card** in Microsoft Teams. The approver taps **Approve** or **Reject** directly in Teams, and Power Automate updates the SharePoint list item with the response. A **Job Queue** in Business Central polls the SharePoint list and processes the decisions through the workflow engine.

### Architecture

```
BC creates Approval Entry (external approver)
  │
  │  BC server-side (Graph API)
  ▼
SharePoint List: new item created
  │
  │  Power Automate trigger (Standard connector — free)
  ▼
"When an item is created" fires
  │
  ▼
Power Automate sends Adaptive Card to Teams
  │
  ▼
Approver taps Approve / Reject in Teams
  │
  │  Power Automate (Standard connector)
  ▼
SharePoint list item updated with response
  │
  │  BC Job Queue polls SharePoint list (Graph API)
  ▼
BC processes response → workflow advances
```

> **Licence benefit:** Both the SharePoint and Teams connectors are **Standard** (free) connectors in Power Automate, included with all Microsoft 365 business licences. No Power Automate Premium licence is required.

---

## Prerequisites

<table id="bkmrk-requirementdetailsbu"><thead><tr><th>Requirement</th><th>Details</th></tr></thead><tbody><tr><td>**Business Central**</td><td>DEXPRO AWF extension installed, BC 25 or later</td></tr><tr><td>**External approver BC licence**</td><td>Each external approver needs an appropriate **paid Business Central user licence** — acting on BC data (directly or via the SharePoint relay) is not covered by a Microsoft 365 licence alone (Microsoft multiplexing terms). A Team Member licence may suffice for approval-only use but is **not guaranteed** for custom/external scenarios. **DEXPRO makes no licensing representation** — the customer/partner must confirm the requirement with Microsoft</td></tr><tr><td>**Microsoft 365**</td><td>External approvers also need a Teams-capable M365 licence (Business Basic or higher) for the Teams card</td></tr><tr><td>**Power Automate**</td><td>Standard licence (included in M365) — no Premium required</td></tr><tr><td>**SharePoint site**</td><td>A SharePoint site for the approval list (existing or new)</td></tr><tr><td>**Entra App Registration**</td><td>Required for BC to read/write the SharePoint list via Graph API. Also used for Entra ID group resolution if needed</td></tr><tr><td>**BC service account**</td><td>A BC-licensed user with the **DXP AWF Admin** permission set. This user runs the Job Queue entries that poll SharePoint</td></tr></tbody></table>

---

## Step 1: Create an Entra ID App Registration

Business Central communicates with SharePoint and Microsoft Graph using OAuth2 client credentials. You need an App Registration in Microsoft Entra ID (formerly Azure AD).

> **Tip:** If you already have a DXP-related App Registration (e.g. from DXP Core), you can reuse it — just add the required permissions.

### 1.1 Register the Application

1. Go to the [Microsoft Entra admin center](https://entra.microsoft.com)
2. Navigate to **Identity** → **Applications** → **App registrations**
3. Click **New registration**
    - **Name:** `DEXPRO AWF Graph API` (or any descriptive name)
    - **Supported account types:** `Accounts in this organizational directory only` (single tenant)
    - **Redirect URI:** Leave blank (not needed for client credentials)
4. Click **Register**
5. On the app's **Overview** page, copy:
    - **Application (client) ID** — you will need this later
    - **Directory (tenant) ID** — you will need this later

### 1.2 Add API Permissions

1. In the app registration, navigate to **API permissions**
2. Click **Add a permission** → **Microsoft Graph** → **Application permissions**
3. Add the following permissions:

<table id="bkmrk-permissiontypepurpos"><thead><tr><th>Permission</th><th>Type</th><th>Purpose</th></tr></thead><tbody><tr><td>`Sites.ReadWrite.All`</td><td>Application</td><td>**Required.** Read/write list items, upload attachments, create sharing links.</td></tr><tr><td>`Sites.Manage.All`</td><td>Application</td><td>**Required.** Create the approval list and its columns (including typed columns like `AmountRaw` / `DueDateRaw`). Without this permission the initial setup fails with `403 accessDenied`.</td></tr><tr><td>`GroupMember.Read.All`</td><td>Application</td><td>*(Optional)* Resolve Entra ID Security Group members</td></tr><tr><td>`Group.Read.All`</td><td>Application</td><td>*(Optional)* List available Entra groups for lookup</td></tr></tbody></table>

1. Click **Add permissions**
2. Click **Grant admin consent for \[your organization\]** and confirm

> **Both `Sites.ReadWrite.All` and `Sites.Manage.All` are required** — the latter is needed to create the approval list and its columns. If only `Sites.ReadWrite.All` is granted, the wizard's SharePoint step will fail with `403 accessDenied` the first time you run it.
> 
> The `GroupMember.Read.All` and `Group.Read.All` permissions are only needed if you plan to use **Entra ID Security Groups** as external approver groups. You can skip them for manual groups or individual approvers.

### 1.3 Create a Client Secret

1. Navigate to **Certificates &amp; secrets**
2. Click **New client secret**
3. Set a description (e.g. `DEXPRO AWF`) and choose an expiry period
4. Click **Add**
5. **Copy the secret value immediately** — it will not be shown again

---

## Step 2: Run the Setup Wizard in Business Central

The setup wizard handles everything — OAuth2 configuration, SharePoint connection, list creation, and Job Queue setup — in a single guided flow. No manual OAuth2 or field configuration required.

### 2.1 Open AWF Setup

1. In Business Central, search for **AWF Setup** (Alt+Q) and open the page
2. Click **Setup External Approvals** in the action bar to launch the wizard

### 2.2 Wizard Steps

The wizard guides you through six steps:

<table id="bkmrk-stepwhat-happens1.-w"><thead><tr><th>Step</th><th>What Happens</th></tr></thead><tbody><tr><td>**1. Welcome**</td><td>Overview of prerequisites and what the wizard will configure</td></tr><tr><td>**2. Setup Type**</td><td>Choose what to configure: **Entra Group Sync** (resolve Entra groups to members for group approvals), **SharePoint Approvals** (Teams notification layer via Power Automate — requires a SharePoint site), or **Both**. When you pick **Entra Group Sync** only, the SharePoint Site step is skipped.</td></tr><tr><td>**3. Credentials**</td><td>Enter the **Tenant ID**, **Client ID**, and **Client Secret** from the Entra App Registration (Step 1) — *or* enable **Reuse an existing OAuth2 setup** to pick an existing DXP OAuth2 Setup code (e.g. one already created for DXP Core). The wizard creates the DXP OAuth2 Setup record automatically. On a re-run it defaults to the reuse option.</td></tr><tr><td>**4. Connection Test**</td><td>The wizard tests the OAuth2 credentials by requesting an access token. If the test fails, you can correct the credentials and retry.</td></tr><tr><td>**5. SharePoint Site**</td><td>Enter your **SharePoint Site URL** (e.g. `https://yourcompany.sharepoint.com/sites/approvals`) and optionally a custom **Approval List Name** (default: `DXP AWF Approvals`). The wizard resolves the site, creates the list if it does not exist, **or reuses an existing list with that name and adds any missing columns**, resolves the document library drive, and stores all internal IDs.</td></tr><tr><td>**6. Done**</td><td>Summary of what was configured. Click **Finish** to enable the feature and create the Job Queue entries.</td></tr></tbody></table>

On completion, the wizard:

- Creates a **DXP OAuth2 Setup** record with code `AWF` (credentials stored securely in Isolated Storage)
- Creates (or reuses) the SharePoint list **"DXP AWF Approvals"** with all required columns
- Sets the attachments folder to **"AWF-Attachments"** (used when Upload Attachments is enabled)
- Creates **Job Queue Entries** for:
    - **External Approval Polling** — polls the SharePoint list for responses (every 2 minutes)
    - **Entra Group Sync** — periodically refreshes Entra ID group memberships (every 4 hours)
- Toggles **SharePoint Approvals Enabled** to Yes

> **Re-running the wizard:** You can re-run the wizard at any time. It will load existing credentials and update the configuration. The SharePoint list is not duplicated — the wizard finds the existing list by name and, if the schema is outdated, adds any missing columns in place (no data loss).

### 2.2.1 Diagnose / Health Check

After the initial setup, the **AWF Setup** page exposes a **Diagnose SharePoint Approvals** action. It runs a non-destructive end-to-end check: OAuth2 token acquisition, SharePoint site / drive / list reachability, column schema, job queue status, and an overview of entries in error or older than seven days. Run it whenever a user reports a problem — the output tells you exactly which step is broken.

### 2.3 Upload Attachments Toggle

After the wizard completes, the **AWF Setup** page shows an **Upload Attachments** toggle in the External Approvals section. When enabled (default), document attachments from the source record are uploaded to SharePoint and a sharing link is included in the Teams Adaptive Card. Disable this if you don't want attachments shared with external approvers.

### 2.4 Manual Job Queue Setup (Alternative)

If you need to adjust Job Queue intervals or prefer to create them manually:

1. Search for **Job Queue Entries** and open it
2. Create a new entry:
    - **Object Type to Run:** Codeunit
    - **Object ID to Run:** `70954832` (DXP AWF Ext. Approval Poller)
    - **Recurring Job:** Yes
    - **No. of Minutes between Runs:** `2` (or your preferred polling interval)
    - **Status:** Ready
3. *(Optional)* Create a second entry for Entra group sync:
    - **Object Type to Run:** Codeunit
    - **Object ID to Run:** `70954833` (DXP AWF Entra Group Sync)
    - **Recurring Job:** Yes
    - **No. of Minutes between Runs:** `240` (4 hours)
    - **Status:** Ready

---

## Step 3: Create External Approvers

External approvers are people who participate in approval workflows from Teams or another system instead of the Business Central web client. Each approver needs an appropriate **paid Business Central user licence** (a Microsoft 365 licence alone is not sufficient; the customer/partner is responsible for confirming the exact requirement with Microsoft), plus a Microsoft 365 account with Teams access.

### 3.1 Open External Approvers

From the **AWF Setup** page, click **External Approvers** in the action bar. Alternatively, search for **External Approvers** in the BC search bar.

### 3.2 Create an Individual External Approver

1. On the **External Approvers** list page, click **New**
2. The **External Approver Card** opens. Fill in:

<table id="bkmrk-fielddescriptionexam"><thead><tr><th>Field</th><th>Description</th><th>Example</th></tr></thead><tbody><tr><td>**Code**</td><td>Unique identifier (Code\[20\])</td><td>`EXT-JOHN`</td></tr><tr><td>**Display Name**</td><td>Full name</td><td>`John Doe`</td></tr><tr><td>**Email**</td><td>The person's Microsoft 365 email or User Principal Name (UPN). Must match their Teams identity exactly.</td><td>`john.doe@company.com`</td></tr><tr><td>**Language Code**</td><td>*(Optional)* Language for the Teams card labels. If blank, the BC environment's default language is used.</td><td>`DEU` for German, `ENU` for English</td></tr><tr><td>**Entra Object ID**</td><td>*(Optional)* Automatically filled when synced from an Entra group. Not needed for manual setup.</td><td></td></tr></tbody></table>

### 3.3 Create an External Approver Group

Groups enable claim-based approvals — the approval request is sent to all members, and the first member to respond wins.

1. On the **AWF Setup** page, click **External Approver Groups** in the action bar
2. Click **New**
3. The **External Approver Group Card** opens. Fill in:

<table id="bkmrk-fielddescriptionexam-1"><thead><tr><th>Field</th><th>Description</th><th>Example</th></tr></thead><tbody><tr><td>**Code**</td><td>Unique identifier</td><td>`FINANCE-GROUP`</td></tr><tr><td>**Description**</td><td>Group description</td><td>`Finance Approvers`</td></tr></tbody></table>

1. In the **Members** subpage at the bottom, add each member:
    - **External Approver Code** — Lookup to select an existing external approver
    - **Email** — Member's email (populated from the approver record)
    - **Display Name** — Member's name

When a workflow assigns this group, **each member** receives their own external approval entry. The **first member** to approve or reject determines the outcome.

### 3.4 Create an Entra ID Group–Based Approver Group

Instead of manually managing members, you can link a group to a **Microsoft Entra ID Security Group**. The system resolves members directly from Entra via the Graph API.

> **Why not use BC's built-in Security Groups?** BC's Security Group system only returns users who already exist as BC users. External approvers by definition don't have BC accounts, so Entra group resolution must go directly through Graph API.

1. Create a new External Approver Group (see 3.3)
2. In the **Entra ID Synchronization** section, use the **assist (⋯) button** on the **Entra Group Name** field. This calls the Graph API and shows a picker of the security-enabled Entra groups; select the group and BC fills the (hidden) Entra Group ID automatically and runs a first sync.
3. To refresh later, click **Sync from Entra ID** in the action bar
    - The system calls the Graph API and populates the **Members** list with all direct members of the Entra group
    - The **Last Entra Sync** timestamp is updated
4. Review the members list to verify the correct people were found

> **Note:** Group members are also resolved **live at runtime** when approval entries are created for an Entra-linked group. The persisted member list is primarily for review purposes. An automatic Entra Group Sync Job (if configured in Step 2.2) keeps the member list up to date periodically.

---

## Step 4: Assign External Approvers to Workflow Stages

1. Open a **AWF Workflow Template** (search for "AWF Workflow Templates")
2. Open a stage or create a new stage
3. Set the **Assignee Type** field to one of:
    - **External Approver** — assigns to a single external person
    - **External Approver Group** — assigns to a group (each member gets their own entry)
4. In the **Assignee Code** field, look up and select the external approver or group

> **Important:** Stages with external approvers must have **rejection groups** enabled (validation is enforced). When the feature "Related Approvals" is enabled on a stage, the related rejection group setting must also be enabled.

---

## Step 5: Install the Power Automate Solution Package

The Teams approval automation is shipped as a **Power Platform solution package** — a `.zip` you import once. During import you bind the solution's two connection references to your tenant's SharePoint and Teams connections and configure the environment variables to point the flow at the SharePoint site and list the wizard created. Total time: 5–10 minutes.

> Want to build the flow by hand instead (e.g. for customisation, or to see exactly what it does step by step)? See [`POWERAUTOMATE-DEV-GUIDE.md`](https://docs.squeeze.one/link/1331). The package import path described here is what most customers will use; the dev guide is for DEXPRO maintainers and advanced admins.

The flow uses only **Standard connectors** (SharePoint + Teams) — no Power Automate Premium licence required.

### 5.1 Import the solution

1. Open &lt;https://make.powerapps.com&gt; and switch to the environment you want the flow to run in (top-right environment picker).
2. Left nav → **Solutions** → **Import solution**.
3. **Browse** and select the `DEXPROApprovalFlow_x.x.x.x.zip` package shipped with this release. Click **Next**.
4. Power Apps shows a summary of the solution contents (one cloud flow, two connection references). Click **Next**.
5. **Connection references** — bind each to a connection in your tenant:
    - **SharePoint DEXPROApprovalFlow-…** → pick (or create) a SharePoint connection authenticated as a user who can read/write the approval list.
    - **Microsoft Teams DEXPROApprovalFlow-…** → pick (or create) a Teams connection authenticated as a user who can post Flow-bot messages on behalf of itself.
6. **Environment variables** — set each to point at your SharePoint list:
    - **Sharepoint Site Address** — the full URL of your SharePoint site (e.g. `https://yourcompany.sharepoint.com/sites/approvals`). This is the same site URL you entered in the wizard.
    - **Sharepoint List Name** — the name of the list the wizard created (default: `DXP AWF Approvals`).
7. Click **Import**. Wait for "Solution imported successfully" (typically under a minute).

### 5.2 Update environment variable values (if needed)

The environment variables you set during import default to the DEXPRO sandbox site. If you used the import wizard to set them (Step 5.1, step 6), this step is already done.

If you need to change the values after import:

1. Open the imported solution → **Environment variables**.
2. Click **Sharepoint Site Address** → edit the **Current value** to your SharePoint site URL.
3. Click **Sharepoint List Name** → edit the **Current value** to your list name.

The flow uses these variables in all SharePoint actions — no manual rebinding of individual actions is needed.

### 5.3 Turn the flow on

1. Back in the solution view, open **Cloud flows** → **DEXPRO AWF Externe Genehmigung**.
2. The flow's status should read **On** after import. If it reads **Off**, click ⋯ → **Turn on**.

> **Note:** The flow is named `DEXPRO AWF Externe Genehmigung` in the solution. This is the name it appears under in your Power Automate environment.

### 5.4 What the approver sees

When BC creates an external approval entry, the approver receives an Adaptive Card from the Flow bot in their Teams **Chat** view. The card shows:

- The localised approval-request title and the workflow stage it belongs to.
- A FactSet with description, amount, due date, and requester.
- A **Details** section with the source record's key fields (e.g. for a Purchase Line: Type, No., Description, Quantity, Direct Unit Cost, Line Amount).
- A multi-line **Comment** input (when the approver can decide).
- Action buttons:
    - **Approve / Reject** — for individual approvers and single-member groups (BC auto-claims those at entry creation).
    - **Claim** — only on multi-member group approvals that haven't been claimed yet. Clicking Claim cancels the other group members' cards (PA writes Cancelled to their SP items) and posts a second card to the claimer with Approve / Reject.
    - **Approval Documents** — opens the SharePoint sharing link to attached documents (visible only when there are attachments).
    - **Open in Business Central** — deep link to the source record (visible only for tables BC has a registered card page for; useful for licensed approvers).

All button labels and placeholder text are pre-translated based on the External Approver's **Language Code** field. See **Step 3** for assigning a language to an approver.

> **Customising the card layout** — the card JSON (both the initial card and the post-claim card) lives inside the flow's *Post adaptive card and wait* actions. To change branding, fields, or layout, see [`POWERAUTOMATE-DEV-GUIDE.md`](https://docs.squeeze.one/link/1331) → *Reference: Card JSONs*.

---

## Step 6: Test the End-to-End Flow

1. In Business Central, open or create an **AWF Workflow Template**
2. Add or modify a stage:
    - **Assignee Type:** `External Approver` or `External Approver Group`
    - **Assignee Code:** Select the external approver you created
3. Trigger the workflow on a test document (e.g., create a Purchase Order and send it for approval)
4. Verify step by step:

<table id="bkmrk-stepwhat-to-checksha"><thead><tr><th>Step</th><th>What to Check</th></tr></thead><tbody><tr><td>**SharePoint list**</td><td>A new item should appear within seconds. Open the list in your browser and verify the item has the correct data (Title, ApproverEmail, Status = Pending, translated labels).</td></tr><tr><td>**Power Automate**</td><td>Go to [Power Automate](https://make.powerautomate.com) → **My flows** → click your flow → **Run history**. A new run should appear. Click it to inspect each step's inputs and outputs.</td></tr><tr><td>**Teams**</td><td>The external approver should receive an Adaptive Card in their Teams chat with the Flow bot. Verify the record description, amount, due date, and translated labels are correct.</td></tr><tr><td>**Approve/Reject**</td><td>Have the approver tap **Approve** or **Reject** (or, for an unclaimed multi-member group, **Claim** first → second card → Approve / Reject). Optionally enter a comment. The card should update after submission.</td></tr><tr><td>**SharePoint (after response)**</td><td>The list item's **ApprovalStatus** column should show `Approved` or `Rejected`. The ResponseComment and ResponseDateTime columns should be populated. For group approvals, **ClaimedBy** holds the email of whoever clicked Claim (or the auto-claimer for a single-member group).</td></tr><tr><td>**BC Job Queue**</td><td>Wait for the next polling cycle (default: every 2 minutes). The Job Queue processes the response. On the **External Approval Entries** page the entry's **Status** stays at the approver's decision (`Approved` / `Rejected`) and the **Processed** column flips to `Yes` with a **Processed DateTime**.</td></tr><tr><td>**BC Approval Entry**</td><td>Verify that the corresponding BC standard Approval Entry has been updated (Approved/Rejected) and the workflow has advanced to the next stage or completed.</td></tr></tbody></table>

---

## Multi-company installs

A single SharePoint list can be safely shared across multiple BC companies. BC writes the current company's name to `BCCompanyName` on every item, and each company's polling job queue only picks up items whose `BCCompanyName` matches its own — both server-side (via the Graph `$filter`) and client-side. You do **not** need a separate list per company.

If you prefer company isolation anyway, run the setup wizard in each company with a different list name (Step 2.2 now lets you name the list).

---

## SharePoint List Reference

The SharePoint list is created automatically by the setup wizard with the following columns. If you create the list manually, use these column names exactly.

### Data Columns

<table id="bkmrk-column-nametypedescr"><thead><tr><th>Column Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>`SchemaVersion`</td><td>Text</td><td>Integration contract version written by BC. Currently `1`.</td></tr><tr><td>`BCCompanyName`</td><td>Text</td><td>BC company that owns the entry. Used by the poller to separate companies sharing one list — see "Multi-company installs" below.</td></tr><tr><td>`Title`</td><td>Single line of text</td><td>Record description (built-in SharePoint column)</td></tr><tr><td>`BCEntryNo`</td><td>Text</td><td>BC external approval entry number (unique within `BCCompanyName`, not globally)</td></tr><tr><td>`BCApprovalEntryNo`</td><td>Text</td><td>BC standard Approval Entry No. that this external approval is bound to. Together with `BCInstanceID` and `GroupCode` it uniquely identifies the set of peer items the PA flow should cancel when one member claims.</td></tr><tr><td>`BCInstanceID`</td><td>Text</td><td>BC workflow instance ID (GUID, globally unique)</td></tr><tr><td>`Description`</td><td>Text</td><td>Document description (vendor/customer name, etc.)</td></tr><tr><td>`ApproverEmail`</td><td>Text</td><td>Target approver's email / UPN</td></tr><tr><td>`ApproverDisplayName`</td><td>Text</td><td>Target approver's display name</td></tr><tr><td>`ApprovalStatus`</td><td>Choice</td><td>Dropdown in SharePoint. Values: `Pending`, `Notified`, `Approved`, `Rejected`, `Claimed`, `Processed`, `Error`, `Cancelled`. Default: `Pending`.</td></tr><tr><td>`ResponseComment`</td><td>Multi-line text</td><td>Comment entered by the approver (multi-line area in SharePoint).</td></tr><tr><td>`ResponseDateTime`</td><td>Date/Time</td><td>Native SharePoint DateTime with picker; BC uses the current time if left blank.</td></tr><tr><td>`ClaimedBy`</td><td>Text</td><td>Email of the group member who claimed the entry</td></tr><tr><td>`AttachmentsUrl`</td><td>Text</td><td>SharePoint sharing link for document attachments</td></tr><tr><td>`BCDocumentUrl`</td><td>Text</td><td>Direct link to the source record in Business Central. Empty if BC couldn't determine a card page for the record's table.</td></tr><tr><td>`RecordDetails`</td><td>Multi-line text</td><td>Markdown rendering of the approved record's own fields — what the adaptive card shows below the FactSet so a Teams approver can see the document/line-level data.</td></tr><tr><td>`Processed`</td><td>Yes/No</td><td>Whether BC has processed this response</td></tr><tr><td>`IsGroupApproval`</td><td>Yes/No</td><td>Whether this is a group (claim-based) approval</td></tr><tr><td>`GroupCode`</td><td>Text</td><td>Approver group code</td></tr><tr><td>`Amount`</td><td>Text</td><td>Display-formatted approval amount</td></tr><tr><td>`AmountRaw`</td><td>Number</td><td>Machine-readable amount — use this for filters and calculations</td></tr><tr><td>`SenderName`</td><td>Text</td><td>BC user who requested the approval</td></tr><tr><td>`DueDate`</td><td>Text</td><td>Display-formatted due date</td></tr><tr><td>`DueDateRaw`</td><td>Date/Time</td><td>ISO 8601 UTC due date — use this for filters</td></tr><tr><td>`CreatedRaw`</td><td>Date/Time</td><td>ISO 8601 UTC creation timestamp</td></tr><tr><td>`StageName`</td><td>Text</td><td>Workflow stage description</td></tr></tbody></table>

### Pre-Translated Label Columns

These columns contain UI labels translated to the approver's language. They are set by BC when the list item is created and used by the Adaptive Card in Teams.

<table id="bkmrk-column-namedefault-%28"><thead><tr><th>Column Name</th><th>Default (English)</th><th>Description</th></tr></thead><tbody><tr><td>`LblTitle`</td><td>Approval Request</td><td>Card header title</td></tr><tr><td>`LblApprove`</td><td>Approve</td><td>Approve button text</td></tr><tr><td>`LblReject`</td><td>Reject</td><td>Reject button text</td></tr><tr><td>`LblComment`</td><td>Comment</td><td>Comment field label</td></tr><tr><td>`LblClaim`</td><td>Claim</td><td>Claim button text (group approvals)</td></tr><tr><td>`LblRelease`</td><td>Release</td><td>Release claim button text</td></tr><tr><td>`LblAmount`</td><td>Amount</td><td>Amount fact label</td></tr><tr><td>`LblSender`</td><td>Requested by</td><td>Sender fact label</td></tr><tr><td>`LblDueDate`</td><td>Due Date</td><td>Due date fact label</td></tr><tr><td>`LblStage`</td><td>Stage</td><td>Stage fact label</td></tr><tr><td>`LblDescription`</td><td>Description</td><td>Description fact label</td></tr><tr><td>`LblAttachments`</td><td>Approval Documents</td><td>Attachments button text</td></tr><tr><td>`LblOpenInBC`</td><td>Open in Business Central</td><td>Deep-link button text</td></tr><tr><td>`LblDetails`</td><td>Details</td><td>Section header above the rendered record details</td></tr><tr><td>`LblAlreadyClaimedByMsg`</td><td>This approval ({title}) has already been claimed by {claimer}. You can safely ignore this card.</td><td>Template for the "already claimed" Teams message. Placeholders `{title}` and `{claimer}` are substituted by the PA flow at runtime.</td></tr><tr><td>`LblAlreadyHandledMsg`</td><td>This approval ({title}) has already been handled by another approver or cancelled in Business Central. You can safely ignore the earlier card.</td><td>Template for the stale-card scope's Teams message. Placeholder `{title}` is substituted by the PA flow at runtime.</td></tr><tr><td>`LblClaimedSuccessMsg`</td><td>The approval entry "{title}" has been successfully processed.</td><td>Confirmation shown after the claimer submits their Approve or Reject decision on Card B (replaces the card in Teams chat). Placeholder `{title}` is substituted by the PA flow at runtime.</td></tr></tbody></table>

---

## Entra ID Group Resolution

### When to Use It

- You have a team of potential approvers managed as an Entra ID Security Group
- You want group membership to sync automatically rather than maintaining a manual list
- External approvers are added/removed in Entra, and you want BC to reflect those changes

### Setup

1. Ensure the App Registration has **`GroupMember.Read.All`** and **`Group.Read.All`** Application permissions with admin consent (see Step 1.2)
2. Create an External Approver Group in BC (see Step 3.4)
3. Enter the Entra Group ID and click **Sync from Entra ID**

### Sync Behaviour

<table id="bkmrk-contextwhen-members-"><thead><tr><th>Context</th><th>When Members Are Resolved</th></tr></thead><tbody><tr><td>**Manual sync**</td><td>Click "Sync from Entra ID" on the group card page</td></tr><tr><td>**Entra Group Sync**</td><td>The Entra Group Sync Job Queue entry runs periodically (if configured)</td></tr><tr><td>**Runtime**</td><td>When a workflow creates approval entries for an Entra-linked group, members are resolved live via Graph API to ensure the most current membership</td></tr></tbody></table>

> Only **direct members** of the security group are resolved. Nested groups are not expanded.

---

## Troubleshooting

<table id="bkmrk-issuepossible-causer"><thead><tr><th>Issue</th><th>Possible Cause</th><th>Resolution</th></tr></thead><tbody><tr><td>**SharePoint item not created**</td><td>OAuth2 setup incorrect or missing permissions</td><td>Verify the setup wizard completed successfully. The App Registration needs `Sites.ReadWrite.All` and `Sites.Manage.All` (Application) permissions with admin consent. Re-run the wizard from AWF Setup → **Setup External Approvals** to re-test.</td></tr><tr><td>**`403 accessDenied` during wizard / `Diagnose SharePoint Approvals`**</td><td>`Sites.Manage.All` not granted or admin consent not given</td><td>Open the App Registration, confirm both `Sites.ReadWrite.All` *and* `Sites.Manage.All` Application permissions are listed, then click **Grant admin consent**. Re-run the wizard.</td></tr><tr><td>**Flow not triggering**</td><td>SharePoint trigger misconfigured</td><td>Verify the trigger points to the correct site and list. Open the list in SharePoint to confirm items are being created.</td></tr><tr><td>**Job Queue not processing responses**</td><td>Job Queue not running</td><td>Check that the Job Queue Entry for codeunit `70954832` has **Recurring Job = Yes** and **Status = Ready**. Check the Job Queue Log Entries for errors.</td></tr><tr><td>**Adaptive Card not appearing in Teams**</td><td>Email mismatch</td><td>The `ApproverEmail` on the SharePoint item must exactly match the user's UPN or primary email in Microsoft 365. Verify in Entra admin center → Users.</td></tr><tr><td>**Card shows "This card isn't valid"**</td><td>JSON syntax error</td><td>Re-import the Power Platform solution package, or compare the card JSON against the reference in **POWERAUTOMATE-DEV-GUIDE.md**. Verify all `@{...}` expressions are intact. Test the static JSON in the [Adaptive Card Designer](https://adaptivecards.io/designer/).</td></tr><tr><td>**Labels appear in English instead of the expected language**</td><td>Language code not set on the approver</td><td>Set the **Language Code** field on the External Approver record (e.g., `DEU` for German). BC uses this to translate all labels before writing them to SharePoint.</td></tr><tr><td>**"401 Unauthorized" in Job Queue log**</td><td>OAuth2 credentials expired or incorrect</td><td>Re-run the setup wizard to verify credentials. If the client secret has expired, create a new one in the Entra admin center and re-enter it in the wizard.</td></tr><tr><td>**Duplicate cards sent**</td><td>Multiple flow runs for the same item</td><td>This shouldn't normally happen — each BC approval creates exactly one SharePoint item. If duplicates occur, check the Power Automate run history for concurrent triggers and add a **Trigger Conditions** expression on the trigger: `@equals(triggerOutputs()?['body/ApprovalStatus'], 'Pending')`</td></tr><tr><td>**Entra group shows 0 members**</td><td>Group empty, nested groups, or permission error</td><td>The Graph API `/members` endpoint only returns direct members. Ensure users are direct members of the security group. Verify `GroupMember.Read.All` permission is granted with admin consent.</td></tr><tr><td>**Approver responded but BC shows "Pending"**</td><td>Job Queue polling hasn't run yet</td><td>Wait for the next polling cycle. Check that the Job Queue entry is running (status Ready, not On Hold). Reduce the polling interval if faster processing is needed.</td></tr><tr><td>**"Permission denied" when running the polling Job Queue**</td><td>Service account missing permission set</td><td>Assign the **DXP AWF Admin** permission set to the BC user running the Job Queue entries.</td></tr><tr><td>**SharePoint list columns missing**</td><td>List created manually with wrong column names</td><td>Column names are case-sensitive and must match exactly (e.g., `BCEntryNo`, not `bcEntryNo`). The easiest fix: delete the list and let the setup wizard re-create it.</td></tr><tr><td>**Attachments link absent from the card**</td><td>No document attachments on the source record, or Upload Attachments is disabled</td><td>Verify the source document has at least one Document Attachment before triggering the workflow. Check that **Upload Attachments** is enabled in AWF Setup.</td></tr></tbody></table>

---

## Appendix: SharePoint List Columns Created by BC

When you use the **Setup External Approvals** wizard or the `CreateApprovalList` procedure, BC creates the SharePoint list via the Graph API with all columns pre-configured. The list uses a `genericList` template with a mix of typed columns: Text (most columns), Boolean (`Processed`, `IsGroupApproval`), Number (`AmountRaw`), DateTime (`ResponseDateTime`, `DueDateRaw`, `CreatedRaw`), Multi-line Text (`ResponseComment`, `RecordDetails`, message template columns), and Choice (`ApprovalStatus` — dropdown enforcing known states).

You do **not** need to create the list or its columns manually unless you have a specific reason to customize the list structure.