Microsoft Entra ID lets you run Access Reviews — periodic checks to validate
who should still have access to a resource. Normally a reviewer clicks Approve or Deny manually.
But there's a powerful twist: you can feed external data (HR systems, ITSM tools,
third-party Identity Governance) into the review engine so decisions happen automatically.
The plumbing that makes this work is customDataProvidedResourceUploadSession.
This article explains the full pipeline — what the API does, what changed in April 2026, how the session lifecycle works, and how everything fits together — with diagrams for every step.
All calls go to /beta. Breaking changes can happen without notice and there are no SLA guarantees. Always build fallback logic before shipping to production.
Big Picture — How the Pipeline Works
Before diving into API details, here's the full architecture from data source to final review decision:
What Is an Access Review? (Quick primer)
An Access Review in Entra ID is a scheduled process that asks: "Should this person still have this access?"
Without custom data, a human reviewer clicks Approve or Deny for each user. With customDataProvidedResourceUploadSession,
your system answers that question automatically by uploading a file that contains pre-computed decisions or signals.
Upload Session Lifecycle
Every upload session goes through a strict state machine. Understanding it prevents the most common failure — data that silently never gets processed.
active with data silently unprocessed.If you never send PATCH isUploadDone: true, the session stays active forever. The data never gets processed. There is no visible error. Always add the PATCH as your final step.
Step-by-Step: How to Use the API
-
Create the upload session
POST to your custom data provider's uploadSessions endpoint. Get back a sessionid.POST /beta/identityGovernance/accessReviews /customDataProviders/{providerId}/uploadSessions { "source": "MyHRSystem", // must match provider name "referenceId": "{reviewInstanceId}" // NEW April 2026 }
-
Upload your data file(s)
POST the file payload to the session. Repeat for multiple files. Each call appends data.POST /beta/.../uploadSessions/{sessionId}/upload // Body: your CSV / JSON with user decisions or signals // e.g. userId + recommended action (approve/deny)
-
Signal that upload is complete
PATCH the session — this is the trigger that moves the session tocompleteand starts Entra processing.PATCH /beta/.../uploadSessions/{sessionId} { "isUploadDone": true // ← CRITICAL. Never skip this. }
-
(Optional) Inspect uploaded files
Use the newfilesrelationship to debug what was actually received.GET /beta/.../uploadSessions/{sessionId}?$expand=files // Filter & sort within expand: ?$expand=files($filter=status eq 'processed';$orderby=createdDateTime desc)
What Changed in April 2026 NEW
referenceId solves multi-review correlation; files relationship finally makes upload debugging possible.Resource Properties Reference
| Property | Type | Filter | Sort | Notes |
|---|---|---|---|---|
id | String | ✗ | ✗ | Read-only GUID assigned at creation |
createdDateTime | DateTimeOffset | ✗ | ✓ | Useful for fetching latest session |
status | Enum | ✓ | ✗ | active · complete · expired |
isUploadDone | Boolean | ✗ | ✗ | MUST be PATCHed true to trigger processing |
source | String | ✗ | ✗ | Must exactly match your provider name |
referenceId NEW | String | ✓ | ✗ | Access Review instance ID — enables direct filtering |
type | String | ✗ | ✗ | Fixed value, set by the system |
data | Object | ✗ | ✗ | Context payload for the session |
stats | Object | ✗ | ✗ | Post-upload diagnostics (row counts, errors) |
files NEW | Collection | ✓ | ✓ | Relationship — use $expand=files to inspect uploads |
Permissions & Licensing
Use a custom scoped role with only the permissions your automation pipeline actually needs. Avoid Global Administrator for service accounts.
Why Build This?
Here are the real-world scenarios this unlocks:
Building in Production — Beta Caveats
Because the endpoint lives at /beta, design defensively. Version-pin your calls, catch 4xx/5xx explicitly, and have a fallback to manual review if the upload session fails. Monitor session status after each run so you catch expired states before they cause silent failures in a review cycle.
Quick Reference
| Thing to remember | Why it matters |
|---|---|
referenceId NEW | Set at creation → filter sessions by review instance ID. Essential for multi-review automation. |
$expand=files NEW | Inspect and debug exactly what was uploaded. Supports $filter and $orderby. |
PATCH isUploadDone: true | Without this, session stays active, data is never processed, no error thrown. Always do this last. |
/beta endpoint | No SLA. Breaking changes possible. Build fallback logic before shipping to prod. |
*.ReadWrite.All scope | Read.All returns 403. Your service principal needs write permissions. |