SharePoint (Graph API) Integration with Adobe Workfront — Step-by-Step Guide
The modern, supported method. This guide uses the new SharePoint (Graph API) integration introduced in Workfront 22.3 (July 2022). It replaces the legacy ACS-based integration which was fully retired on April 2, 2026.
Why Graph API Instead of the Legacy Method?
Legacy (SharePoint) ❌
New (SharePoint Graph API) ✅
Auth method
Azure ACS via appregnew.aspx
OAuth 2.0 via Microsoft Entra ID
Status
Retired April 2, 2026
Fully supported — no retirement date
Admin setup required
Yes — complex, multiple pages
No — zero admin config needed
Per-user auth
No
Yes — each user signs in once
Permissions model
App-only, tenant/site scope
Delegated — user's own SharePoint access
Least privilege
Difficult to enforce
Built-in — users only see what they already have
New document linking
❌ Not possible
✅ Fully supported
How It Works — The Simple Version
Admin enables SharePoint (Graph API) in Workfront once
↓
Each user signs into their Microsoft account from Workfront
↓
Workfront uses OAuth2 to get an access token on their behalf
↓
User can now browse, link, and upload SharePoint documents
↓
Users only see files they already have access to in SharePoint
🔐 Least Privilege built-in: Permissions are delegated — the integration never gets more access than the individual user already has in SharePoint. No admin grants, no XML, no FullControl required.
What You Need Before You Start
Requirement
Who
Workfront System Administrator access
You (admin doing the setup)
Microsoft 365 account with SharePoint Online access
Each user
SharePoint Online (not on-premises)
Your org's Microsoft tenant
Workfront license: Standard or Plan
Your users
Workfront access level: Edit access to Documents
Your users
⚠️ This integration works with SharePoint Online only. On-premises SharePoint is not supported.
Part 1 — Admin Setup (One-Time, Done Once for All Users)
This part takes about 2 minutes. You do it once and all users benefit.
Step 1 — Log into Workfront as System Administrator
Open your browser and go to:
https://[your-tenant].my.workfront.com
Log in with your Workfront System Administrator credentials.
Step 2 — Go to Setup
Click the Main Menu icon (grid/waffle icon) in the top-right corner of the screen.
Click Setup (the gear icon).
Step 3 — Enable SharePoint (Graph API) in Cloud Providers
In the left panel, click Documents.
Under Documents, click Cloud Providers.
You will see a list of document integrations. Find SharePoint (Graph API) and make sure its checkbox is checked/enabled.
⚠️ If you also have the old SharePoint (legacy) integration listed, keep it enabled only if you have existing documents linked through it that users still need to access. For all new document linking, users must use SharePoint (Graph API).
Click Save.
✅ Admin setup is complete. That is all the admin needs to do.
Part 2 — User Setup (Each User Does This Once)
Every user must connect their own Microsoft account to Workfront the first time they use the integration. This is a one-time step per user.
Step 4 — Go to the Documents Area
Users can connect SharePoint from any place in Workfront that has a Documents tab. For example:
Open any Project → click the Documents tab
Or go to the main Documents area from the Main Menu
Step 5 — Click Add New → From SharePoint (Graph API)
Click the Add New button.
In the dropdown, click From SharePoint (Graph API).
If you do not see this option, ask your Workfront administrator to complete Part 1 (Step 3) above.
Step 6 — Sign into Your Microsoft Account
A Microsoft login popup or redirect will appear.
Enter your Microsoft 365 / work email and password.
Complete any MFA (Multi-Factor Authentication) prompt if your organisation requires it.
Step 7 — Review and Accept Permissions
The first time you connect, Workfront will ask for permission to access your SharePoint. You will see a screen titled "Permissions requested" listing what Workfront needs:
Permission Workfront Requests
Why It Needs It
Have full access to your files
To link and upload documents on your behalf
Read items in all site collections
To let you browse and navigate SharePoint sites
Edit or delete items in all site collections
To create assets; delete is only used to clean up failed link attempts
Maintain access to data you have given it access to
To generate a refresh token so you stay logged in
Sign in and read your profile
To act on your behalf through the OAuth2 flow
🔐 These are delegated permissions — Workfront can only access what you personally can access in SharePoint. It cannot see anything beyond your own SharePoint permissions.
Click Accept (or Yes / Allow depending on what the screen shows).
⚠️ If you see "Approval Required" instead of "Permissions requested" — this means your organisation's Microsoft admin has restricted app consent. In that case, use the page to submit an approval request to your Microsoft 365 admin. Once the admin approves, come back and repeat from Step 5.
Step 8 — Browse and Select Files from SharePoint
After accepting, the SharePoint file picker will open inside Workfront. You can now:
Browse your SharePoint sites and document libraries
Use the search bar to find files by name
Select one or multiple files or folders
Click Link to attach them to Workfront
✅ The selected files are now linked to Workfront. A SharePoint icon will appear next to them in the Documents tab.
ℹ️ Files remain stored in SharePoint. Workfront only holds a link — not a copy of the file.
Part 3 — Day-to-Day Usage
Once set up, here is how users work with the integration every day.
Linking a Document from SharePoint to Workfront
Go to the Documents tab of any Project, Task, or Issue.
Click Add New → From SharePoint (Graph API).
Browse or search for the file.
Select the file(s) → click Link.
Sending a Document from Workfront to SharePoint
Select a document already in Workfront.
Click the More menu (three dots) → Send to → SharePoint (Graph API).
Browse to the SharePoint folder where you want to save it.
Click Save.
The document is now stored in SharePoint and linked back to Workfront. Any updates in SharePoint will reflect in Workfront.
Linking a Folder from SharePoint
Go to the Documents tab.
Click Add New → From SharePoint (Graph API).
Browse to the folder you want to link.
Select the folder → click Link.
⚠️ Linked folders sync their contents. If someone adds, removes, or edits files in SharePoint, those changes appear in Workfront automatically. However, the sync uses the credentials of the user who originally linked the folder — so if that user leaves the organisation, the folder must be re-linked by another user.
Important Limitations to Know
Limitation
Detail
One SharePoint instance per user
A user can connect to only one SharePoint tenant. They cannot connect to a second SharePoint even if they have access to it.
No global/service account
Each user must authenticate individually. There is no way to set up a single shared account for all users.
SharePoint Online only
On-premises SharePoint is not supported.
File size limit
Single file: 5 GB max. Multiple files at once: 1 GB total.
Folder ownership risk
If the user who linked a folder loses SharePoint access or leaves the org, that folder becomes inaccessible in Workfront until re-linked.
New Documents area
This integration is not available in the new Adobe cloud storage Documents area. It works in the classic Documents tab only.
Troubleshooting
Problem
Fix
"From SharePoint (Graph API)" not visible in Add New
Admin has not enabled it — complete Part 1, Step 3
"Approval Required" screen appears
Microsoft admin needs to approve the Workfront app in their Entra ID tenant — submit the request from that screen
User can see some sites but not others
Users only see what they have permission to in SharePoint — check their SharePoint site access
Linked folder content not loading
The user who linked the folder may have lost access — re-link the folder with an active user who has access
MFA prompt keeps repeating
Check if your org's Conditional Access policies require re-authentication — contact your Microsoft 365 admin
File linked but cannot open
Verify the user has at least View access to that file in SharePoint
Comparison: What Each Role Does
Role
Action
When
Workfront Admin
Enable SharePoint (Graph API) in Cloud Providers
Once, before users start
Microsoft 365 Admin
Approve the Workfront app (only if org restricts app consent)
Once, if "Approval Required" screen appears
Each User
Sign into Microsoft account from Workfront
Once per user
Each User
Link/browse/upload documents
Every time they need a SharePoint file
Security Overview
All communication between Workfront and SharePoint is over HTTPS.
Workfront uses OAuth 2.0 — no passwords are stored by Workfront.
Permissions are delegated — Workfront acts on behalf of the signed-in user, never beyond their access.
Users can revoke access at any time from their Microsoft account's app permissions page at https://myapps.microsoft.com.
Workfront does not store or copy SharePoint files. Only thumbnails for preview are cached.
SharePoint Integration with Adobe Workfront — Step-by-Step Setup Guide
Who is this for? Anyone setting up the legacy SharePoint integration in Workfront from scratch. No prior experience needed — follow every step exactly as written.
What You Will Need Before You Start
Item
Where to Get It
SharePoint Online admin or site admin access
Your IT/Microsoft 365 admin
Adobe Workfront admin access
Your Workfront administrator
Your SharePoint tenant URL
Example: https://[your-tenant].sharepoint.com
Overview of the 3 Phases
Phase 1 → Go to SharePoint → Register the App → Get Client ID & Client Secret
Phase 2 → Go to Workfront → Fill in the Integration Form
Phase 3 → Verify & Test
Phase 1: Generate Client ID and Client Secret in SharePoint
This is the most important phase. You will visit a special SharePoint page to create an "App Registration" that gives Workfront permission to talk to SharePoint.
Step 1 — Open the App Registration Page in SharePoint
Open your browser (Chrome or Edge recommended).
In the address bar, type your SharePoint URL and add /_layouts/15/appregnew.aspx at the end.
Replace [your-tenant] with your actual SharePoint domain name.
Press Enter. You will see a form titled "App Information" or "New App".
⚠️ If you see an error like "Sorry, you don't have access" — contact your Microsoft 365 Global Administrator. Only tenant admins can access this page.
Step 2 — Fill in the App Registration Form
You will see fields on the page. Fill them in exactly as described below:
Field
What to Enter
Client Id
Click the Generate button next to this field. A GUID (long code) will auto-fill.
Client Secret
Click the Generate button next to this field. A secret code will auto-fill.
Title
Type any name. Example: Workfront SharePoint App
App Domain
Type exactly: my.workfront.com
Redirect URI
Type exactly: https://oauth.my.workfront.com/oauth2/redirect
📋 CRITICAL: Before clicking Create, copy and save the Client ID and Client Secret to Notepad or a secure location. You will NOT be able to see the Client Secret again after leaving this page.
Step 3 — Click Create
After filling all fields, scroll down and click Create.
You will see a confirmation message: "The app identifier has been successfully created."
The page will also display the Client ID and Client Secret one final time — copy both values now if you haven't already.
Step 4 — Grant Permissions to the App in SharePoint
Choose one of the three permission models below based on your organisation's requirement.
🔵 Option A — Tenant-Wide Access (All Site Collections)
Use this when Workfront needs access to all site collections across the entire SharePoint tenant.
Repeat from step 1 for each additional site collection.
✅ Each site collection is granted independently using the same Client ID.
Comparison Table — Which Option Should You Use?
Option A — Tenant
Option B — Single Site
Option C — Multiple Sites
Access Scope
All site collections
One site collection
Selected site collections
URL Used
-admin.sharepoint.com appinv.aspx
sites/[Name] appinv.aspx
sites/[Name] appinv.aspx (repeated)
XML Scope Value
content/tenant
content/sitecollection
content/sitecollection
Steps Required
One time
One time
Once per site
Best For
Full enterprise rollout
Single team or department
Controlled multi-team rollout
Security Level
Broad
Tight
Balanced
Phase 2: Configure the Integration in Adobe Workfront
Now you will go to Workfront and fill in the form.
Step 5 — Log into Workfront as Administrator
Open your browser and go to your Workfront URL:
https://[your-tenant].my.workfront.com
Log in with your Workfront administrator credentials.
Step 6 — Navigate to SharePoint Integration Settings
Click the Main Menu icon (grid/waffle icon) in the top-right corner of Workfront.
Click Setup (gear icon).
In the left panel, click Documents.
Under Documents, click SharePoint Integration.
Click the + Add SharePoint Integration button (or New Integration if shown).
The SharePoint Integration form will open — this is the form shown in the screenshots.
Step 7 — Fill in the SharePoint Integration Form
The form has 4 sections in the left menu. Fill them in order:
Section 1: SharePoint Instance Name
Field
What to Enter
Name
A friendly label for this integration. Example: SharePoint Online Integration
Click Next or go to the next section.
Section 2: SharePoint Info
Field
What to Enter
SharePoint Host Instance
Your SharePoint URL without https://. Example: [your-tenant].sharepoint.com
Azure Access Domain
Your SharePoint URL without https://. Example: [your-tenant].sharepoint.com
Site Collections Authentication
Type [your-tenant].sharepoint.com (same as above)
Section 3: Connection Info
This is where you enter the credentials from Phase 1.
Field
What to Enter
SharePoint Client ID
Paste the Client ID you copied in Step 2
SharePoint Client Secret
Paste the Client Secret you copied in Step 2
Workfront SharePoint AppDomain
Pre-filled: my.workfront.com — do not change
Workfront SharePoint Redirect URI
Pre-filled: https://oauth.my.workfront.com/oauth2/redirect — do not change
⚠️ Important: The Client Secret must be exactly 44 characters long. If it's shorter, go back to the SharePoint appregnew.aspx page and generate a new one. You may need to try 2–3 times until a 44-character secret is generated.
Section 4: Visible Site Collections
This section lists the SharePoint site collections that will be accessible inside Workfront.
If you chose Option A (tenant-wide) — leave this as default; all sites will appear automatically.
If you chose Option B or C (specific sites) — add only those site collection URLs here to match the permissions you granted.
Step 8 — Click Confirm
Review all fields one more time.
Click the Confirm button (blue button, bottom-right).
Workfront will test the connection. If successful, the integration will be saved.
Step 9 — Enable the Integration in Cloud Providers Settings
Go back to Setup → Documents → Cloud Providers.
Make sure both SharePoint and SharePoint (Graph API) checkboxes are enabled (checked).
Click Save.
Phase 3: Verify the Integration
Step 10 — Test from a Document Area
Go to any Project or Task in Workfront.
Click the Documents tab.
Click Add New → From SharePoint.
You should see your SharePoint sites listed and be able to browse folders.
✅ If you can browse SharePoint files — the integration is working correctly!
Troubleshooting
Problem
Fix
"App not trusted" error
Go back to appinv.aspx and click Trust It again
Client Secret not accepted / 44 character error
Go to appregnew.aspx, generate a new Client Secret, and update it in Workfront
"Sorry, only tenant administrators can access"
Ask your Microsoft 365 Global Admin to perform Steps 1–4
Cannot see SharePoint sites in Workfront
Ensure your account has View access to those site collections in SharePoint
Previously linked documents not accessible
A user with SharePoint access must re-link the folder from the Documents tab
Site not visible after Option B/C
Confirm the appinv.aspx step was completed on that specific site URL, not the admin URL
Quick Reference — Values Summary
Value
Where It Comes From
Client ID
Generated at appregnew.aspx (SharePoint)
Client Secret
Generated at appregnew.aspx (SharePoint)
SharePoint Host Instance
Your SharePoint domain (e.g. [your-tenant].sharepoint.com)
AppDomain
Pre-filled in Workfront: my.workfront.com
Redirect URI
Pre-filled in Workfront: https://oauth.my.workfront.com/oauth2/redirect
Note: The Client Secret generated via appregnew.aspx expires after 1 year. Set a calendar reminder to renew it before expiry to avoid losing access to linked documents.
Send Emails via Microsoft Graph API Using PowerShell and App Registration
Microsoft Graph API is the unified gateway to Microsoft 365 data and services. One of the most common automation scenarios is sending emails programmatically — without relying on a logged-in user, Outlook, or SMTP. In this post, we'll walk through how to register an Azure AD app, grant it the right permissions, and use a single end-to-end PowerShell script to send emails and query SharePoint via Graph API using client credentials (app-only auth).
Why Use Graph API for Sending Emails?
No user sign-in required — works great for background jobs, bots, and automation flows
Works from anywhere — PowerShell scripts, Power Automate Desktop, Azure Functions, etc.
Scalable and auditable — full control over sending identity and logging
Step 1: Register an App in Microsoft Entra ID (Azure AD)
Before writing any code, you need an app registration that represents your script or automation.
Navigate to Microsoft Entra ID → App registrations → New registration
Give it a meaningful name (e.g., GraphAPI-MailSender)
Leave Redirect URI blank — not needed for client credentials flow
Click Register
Once created, note down:
Application (client) ID → used as $clientId in the script
Directory (tenant) ID → used in the token endpoint URL
Step 2: Create a Client Secret
Go to Certificates & secrets → New client secret
Add a description and set an expiry (e.g., 12 months)
Copy the Value immediately — it won't be shown again
Store it securely (Azure Key Vault is recommended for production)
Step 3: Grant API Permissions
Your app needs the following Application permissions (not Delegated):
Permission
Purpose
Mail.Send
Send email as any mailbox in the tenant
Sites.Read.All
Read SharePoint site data
Steps:
Go to API permissions → Add a permission → Microsoft Graph → Application permissions
Add Mail.Send and Sites.Read.All
Click Grant admin consent — required for application permissions
⚠️ Mail.Send as an application permission allows sending mail as any user in the tenant. Use application access policies to restrict it to specific mailboxes in production.
Step 4: Full PowerShell Script
The script below handles everything in sequence:
Acquires a token using client credentials
Sends an email via Graph API
Reuses the token to query the SharePoint root site
# ============================================================
# Microsoft Graph API — Send Email + Query SharePoint Root Site
# Using App-Only (Client Credentials) Authentication
# ============================================================
# ── Configuration ──────────────────────────────────────────
$clientId = "<YOUR_CLIENT_ID>" # Application (client) ID
$clientSecret = "<YOUR_CLIENT_SECRET>" # Client secret value
$tenantId = "<YOUR_TENANT_ID>" # Directory (tenant) ID
$senderUPN = "sender@yourdomain.com" # Mailbox used to send email
$recipientUPN = "recipient@yourdomain.com" # Target recipient
# ── Part 1: Acquire Access Token ────────────────────────────
Write-Output "Acquiring access token..."
$tokenBody = @{
client_id = $clientId
client_secret = $clientSecret
scope = "https://graph.microsoft.com/.default"
grant_type = "client_credentials"
}
$tokenResponse = Invoke-RestMethod `
-Uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" `
-Method POST `
-Body $tokenBody
$token = $tokenResponse.access_token
Write-Output "Token acquired successfully."
# ── Part 2: Send Email via Graph API ────────────────────────
Write-Output "Sending email..."
$mailPayload = @{
message = @{
subject = "Test Email from Graph API"
body = @{
contentType = "Text"
content = "This is a test email sent via Microsoft Graph API using PowerShell with app-only authentication."
}
toRecipients = @(
@{
emailAddress = @{
address = $recipientUPN
}
}
)
}
} | ConvertTo-Json -Depth 10
$headers = @{
Authorization = "Bearer $token"
"Content-Type" = "application/json"
}
try {
Invoke-RestMethod `
-Uri "https://graph.microsoft.com/v1.0/users/$senderUPN/sendMail" `
-Method POST `
-Headers $headers `
-Body $mailPayload `
-ContentType "application/json"
Write-Output "✅ Email sent successfully to $recipientUPN"
}
catch {
Write-Error "❌ Failed to send email: $_"
}
# ── Part 3: Query SharePoint Root Site ──────────────────────
Write-Output "`nQuerying SharePoint root site..."
try {
$rootSite = Invoke-RestMethod `
-Uri "https://graph.microsoft.com/v1.0/sites/root" `
-Method GET `
-Headers $headers
Write-Output "✅ SharePoint root site retrieved:"
Write-Output ($rootSite | ConvertTo-Json -Depth 3)
}
catch {
Write-Error "❌ Failed to query SharePoint root site: $_"
}
How to Run the Script
Open PowerShell (or Windows PowerShell ISE / VS Code)
Replace the four placeholder values at the top of the script:
<YOUR_CLIENT_ID>
<YOUR_CLIENT_SECRET>
<YOUR_TENANT_ID>
sender@yourdomain.com and recipient@yourdomain.com
Certificate-based auth (New-SelfSignedCertificate) is more secure than secrets
Audit permissions
Review app registrations and permissions in Entra ID quarterly
Summary
In this post, we covered:
Registering an app in Microsoft Entra ID and creating a client secret
Granting Mail.Send and Sites.Read.All application permissions with admin consent
A complete PowerShell script that acquires a token, sends an email, and queries SharePoint — all using app-only auth
Error handling with try/catch per operation
Security recommendations for production use
This pattern is perfect for Power Automate Desktop flows, scheduled PowerShell jobs, or any scenario where no interactive user is present. The same token works across multiple Graph API endpoints — making it efficient to chain operations in a single script.
Part 2: End-to-End in Power Automate Desktop (PAD)
The same logic — get a token, send an email, query SharePoint — can run entirely inside a Power Automate Desktop flow without any external PowerShell script. PAD has built-in HTTP actions and a Run PowerShell script action, giving you two clean approaches.
Approach A: Using the "Run PowerShell Script" Action (Quickest Way)
This embeds the entire PowerShell script directly inside a PAD flow. Best when you already have the script and just want to automate it.
PAD Flow Structure
Flow: Send Email via Graph API
│
├── [1] Set Variable — clientId
├── [2] Set Variable — clientSecret
├── [3] Set Variable — tenantId
├── [4] Set Variable — senderUPN
├── [5] Set Variable — recipientUPN
├── [6] Run PowerShell Script
│ └── Script: (full script using %clientId%, %clientSecret%, etc.)
│ └── Output: PowershellOutput
├── [7] IF PowershellOutput contains "successfully"
│ └── Display Message — "Flow completed successfully"
│ ELSE
│ └── Display Message — "Flow encountered an error"
└── [8] (Optional) Write output to text file or log
Step-by-Step in PAD Designer
Step 1 — Set your variables
Add one Set variable action for each credential. Using variables (rather than hardcoding) keeps the script clean and makes future updates easy.
Variable Name
Value
clientId
Your Application (client) ID
clientSecret
Your client secret value
tenantId
Your Directory (tenant) ID
senderUPN
sender@yourdomain.com
recipientUPN
recipient@yourdomain.com
In PAD, go to Actions panel → Variables → Set variable, set Name and Value for each.
Step 2 — Add "Run PowerShell Script" action
Search for Run PowerShell script in the Actions panel (under Scripting). Paste the script below into the script body. PAD variables are referenced using %variableName% syntax inside the script block.
# ============================================================
# Graph API — Send Email + Query SharePoint Root Site
# Running inside Power Automate Desktop
# ============================================================
$clientId = "%clientId%"
$clientSecret = "%clientSecret%"
$tenantId = "%tenantId%"
$senderUPN = "%senderUPN%"
$recipientUPN = "%recipientUPN%"
# ── Part 1: Acquire Token ────────────────────────────────────
$tokenBody = @{
client_id = $clientId
client_secret = $clientSecret
scope = "https://graph.microsoft.com/.default"
grant_type = "client_credentials"
}
$tokenResponse = Invoke-RestMethod `
-Uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" `
-Method POST `
-Body $tokenBody
$token = $tokenResponse.access_token
# ── Part 2: Send Email ───────────────────────────────────────
$mailPayload = @{
message = @{
subject = "Test Email from Graph API via PAD"
body = @{
contentType = "Text"
content = "This email was sent via Microsoft Graph API running inside a Power Automate Desktop flow."
}
toRecipients = @(
@{ emailAddress = @{ address = $recipientUPN } }
)
}
} | ConvertTo-Json -Depth 10
$headers = @{
Authorization = "Bearer $token"
"Content-Type" = "application/json"
}
try {
Invoke-RestMethod `
-Uri "https://graph.microsoft.com/v1.0/users/$senderUPN/sendMail" `
-Method POST `
-Headers $headers `
-Body $mailPayload `
-ContentType "application/json"
Write-Output "Email sent successfully to $recipientUPN"
}
catch {
Write-Output "ERROR sending email: $_"
}
# ── Part 3: Query SharePoint Root Site ──────────────────────
try {
$rootSite = Invoke-RestMethod `
-Uri "https://graph.microsoft.com/v1.0/sites/root" `
-Method GET `
-Headers $headers
Write-Output "SharePoint root site: $($rootSite.webUrl)"
}
catch {
Write-Output "ERROR querying SharePoint: $_"
}
In the action settings:
Script to run → paste the script above
PowerShell script output → save to variable PowershellOutput
Script error output → save to variable ScriptError
Step 3 — Handle output with an IF condition
Add an If action:
First operand:%PowershellOutput%
Operator: Contains
Second operand:successfully
Inside the If block → add Display message: "✅ Email sent and SharePoint queried successfully"
Inside the Else block → add Display message: "❌ Flow error — check ScriptError variable"
Step 4 — (Optional) Log output to a file
Add a Write text to file action after the If block:
Text to write:%PowershellOutput%%NewLine%%ScriptError%
If file exists: Append
Approach B: Using PAD HTTP Actions (No PowerShell Required)
PAD has native HTTP actions under Web → Invoke web service that can call REST APIs directly — no PowerShell needed. This is the cleanest approach for PAD-native flows.
PAD Flow Structure
Flow: Send Email via Graph API (HTTP Native)
│
├── [1] Set Variable — clientId
├── [2] Set Variable — clientSecret
├── [3] Set Variable — tenantId
├── [4] Set Variable — senderUPN
├── [5] Set Variable — recipientUPN
│
├── [6] Invoke web service — POST token endpoint
│ └── Saves response → TokenResponse (JSON)
│
├── [7] Get JSON key — extract access_token
│ └── Saves → AccessToken
│
├── [8] Invoke web service — POST sendMail
│ └── Uses Bearer %AccessToken% in header
│ └── Saves response → MailResult
│
├── [9] Invoke web service — GET sites/root
│ └── Uses Bearer %AccessToken% in header
│ └── Saves response → SharePointResult
│
└── [10] Display message — show results
Request body (paste as-is, update addresses via variables):
{
"message": {
"subject": "Test Email from PAD via Graph API",
"body": {
"contentType": "Text",
"content": "This email was sent using Power Automate Desktop with Microsoft Graph API HTTP actions."
},
"toRecipients": [
{
"emailAddress": {
"address": "%recipientUPN%"
}
}
]
}
}
Step 5 — Query SharePoint Root Site (Invoke web service)
Recommendation: Use Approach A if you already have the PowerShell script. Use Approach B if you want a fully PAD-native flow with no external dependencies.
Tips for PAD Flows with Graph API
Store secrets in PAD Input variables marked as Sensitive — they are masked in logs and not stored in plain text in the flow definition
Add On block error handlers around each Invoke web service action to gracefully catch HTTP failures (401 Unauthorized, 403 Forbidden, etc.)
Token expiry: The client credentials token is valid for 1 hour. For long-running flows, re-acquire the token mid-flow if needed
Test in PAD debugger using the step-through (F10) to inspect each variable value before running end-to-end
All three entry points — standalone PowerShell, PAD via PowerShell action, and PAD via HTTP actions — use the exact same app registration, permissions, and token. The only difference is where and how the script runs.
$mailBody = @{
message = @{
subject = "Test Email from GraphAPI_Flow"
body = @{
contentType = "Text"
content = "This is a test email sent via Microsoft Graph API from Power Automate Desktop."
}
toRecipients = @(
@{ emailAddress = @{ address = "sreekanth@vkn2k.onmicrosoft.com" } }
)
}
} | ConvertTo-Json -Depth 10
A complete learning reference for Power Automate Desktop, covering concepts from beginner to expert level, plus 100 real-world scenarios with practical answers.
Part A — Concept Questions
Beginner (Q1–Q30)
#
Question
Short Answer
1
What is Power Automate Desktop (PAD)?
A low-code RPA tool from Microsoft used to automate repetitive desktop and web tasks by recording or building flows visually.
2
What is RPA?
Robotic Process Automation — software "robots" that mimic human actions on a UI to automate rule-based tasks.
3
Difference between Power Automate (cloud) and PAD?
Cloud flows run on triggers/connectors in the cloud; PAD runs on the desktop to automate UI, files, and legacy apps.
4
What is a desktop flow?
A sequence of actions built in PAD that automates a task on a Windows machine.
5
What are actions in PAD?
Pre-built building blocks (like "Click", "Read from Excel") that you drag into the flow designer.
6
What is the Actions pane?
The left-hand panel listing all available actions grouped by category.
7
What is a variable in PAD?
A named container that stores data (text, number, list, datatable, object) used during a flow.
8
How do you create a variable?
Use "Set variable" action, or variables are auto-produced as outputs of other actions.
Create a Dataverse Table With Every Common Column Type Using Power Automate
Create a Dataverse Table With Every Common Column Type Using Power Automate
If you have ever clicked through the maker portal to build a Dataverse table column by column, you know how slow it gets. There is a faster, repeatable way: send one HTTP request to the Dataverse Web API and let it build the whole table — primary column, choices, currency, dates, the lot — in a single shot.
In this post I will walk through a Power Automate cloud flow that does exactly that. It creates a demo table called Sample Product with one column of every common type, so you can see how each column type is defined in the Web API.
The idea in one line
Dataverse exposes a metadata endpoint. POST a JSON definition of your table to it, and Dataverse creates the table and all the columns you described.
POST https://yourorg.crm.dynamics.com/api/data/v9.2/EntityDefinitions
Replace yourorg with your own environment URL. You can find it in the Power Platform Admin Center under your environment's settings, or in the address bar when you open any model-driven app.
The flow at a glance
The flow has just two steps after the trigger:
Step
Action
What it does
Trigger
Manually trigger a flow
Lets you run it on demand with a button
1
Compose
Holds the full table definition as JSON
2
HTTP request
POSTs that JSON to the EntityDefinitions endpoint
Keeping the definition in a Compose action makes the flow easy to read and easy to tweak. The HTTP action just points at the Compose output.
Connector note: This example uses the HTTP with Microsoft Entra ID (preauthorized) connector (the "Invoke an HTTP request" action). It is a premium connector, but it handles authentication to Dataverse for you, so you do not have to manage tokens by hand.
Step 1 — Compose the table definition
The Compose action holds an EntityMetadata object. The top part describes the table itself; the Attributes array describes each column.
The internal name. new_ is the default publisher prefix — change it to match your own solution publisher.
DisplayName
The singular label shown in the UI ("Sample Product").
DisplayCollectionName
The plural label ("Sample Products").
OwnershipType
UserOwned means rows belong to a user or team. Use OrganizationOwned for shared reference data.
LanguageCode: 1033
The locale ID for English (United States). Use your own LCID if needed.
Why the double @@?
You will notice @@odata.type instead of @odata.type. This is a Power Automate quirk, not a Dataverse one. In Power Automate the @ symbol starts an expression, so to send a literal @ you have to double it. When the flow runs, @@odata.type is sent to Dataverse as @odata.type. If you copy this JSON somewhere outside Power Automate, drop one of the @ signs.
The column types, explained
Every column lives in the Attributes array and needs a matching @odata.type. Pick the wrong type and you get a 400 Bad Request. Here is each column type used in the demo table:
Column
@odata.type
Dataverse type
Notes
Product Name
StringAttributeMetadata
Single line of text
The primary name column. IsPrimaryName: true, MaxLength: 100. Every table needs exactly one.
If you forget IsPrimaryName: true, or include zero (or more than one) of them, the request fails. This is the most common mistake when building tables this way.
A choice column (single select)
A local choice set lives right inside the column definition. Each option needs a numeric Value and a label:
Set IsGlobal: true if you want a global choice set that other tables can reuse. The multi-select column ("Tags") follows the same shape — the only real difference is the @odata.type and that its AttributeType is reported as Virtual.
Step 2 — The HTTP request
The second action posts the Compose output to Dataverse:
On success Dataverse returns HTTP 204 No Content, with an OData-EntityId header pointing at your new table. No body comes back — the empty 204 is the success signal.
Two improvements worth adding
The base flow works, but two small additions make it production-friendly.
1. Put the table in a solution. As written, the new table lands in the Default Solution, which is an ALM anti-pattern — it makes the table hard to move between environments. Add this header to the HTTP action so the table is created inside your own unmanaged solution:
MSCRM.SolutionUniqueName: YourSolutionUniqueName
Use the solution's unique name, not its display name.
2. Read it back with a strong-consistency header. Metadata is cached, so if you immediately query the new table it might return a 404 because the cache has not caught up. When you read straight after creating, add:
Consistency: Strong
Wrap-up
With one Compose action and one HTTP request you can stand up a full Dataverse table — primary column, numbers, currency, dates, and both flavours of choice — without touching the maker portal. Because the whole definition is just JSON, you can version it, parameterise it, or drive it from a CSV or SharePoint list to build tables on demand.
The same EntityDefinitions endpoint also handles updates (PUT) and lets you add columns to an existing table later (POST to its Attributes collection), so this is a solid foundation for any metadata-as-code approach on the Power Platform.
Quick reference: column type to @odata.type
Column type you want
@odata.type to use
Single line of text
StringAttributeMetadata
Multiple lines of text
MemoAttributeMetadata
Whole number
IntegerAttributeMetadata
Big integer
BigIntAttributeMetadata
Decimal number
DecimalAttributeMetadata
Float
DoubleAttributeMetadata
Currency
MoneyAttributeMetadata
Yes/No
BooleanAttributeMetadata
Date and time
DateTimeAttributeMetadata
Choice (single)
PicklistAttributeMetadata
Choices (multi)
MultiSelectPicklistAttributeMetadata
Full flow JSON
Here is the complete flow, scrubbed of environment-specific values. Before you use it, replace two placeholders:
yourorg.crm.dynamics.com in the HTTP action URL with your own environment URL.
The connection details (connectionName, connectionReferenceLogicalName) will be set automatically when you add your own HTTP with Microsoft Entra ID connection — the placeholder values below are only there to keep the JSON valid.
Note: the @@odata.type double-@ is correct for this Power Automate definition (it is how the editor escapes a literal @). Keep it as-is when pasting into the flow editor's code view. If you ever send the body straight to Dataverse outside Power Automate, use a single @odata.type.