Skip to main content
Version: 1.21.0

Ownership API integration guide

This guide explains how to configure a service-principal caller and use the EasyLife 365 Identity ownership API to synchronize application, technical, and business owners programmatically instead of importing CSV files.

The API manages three ownership areas:

  • Application owners: owners stored directly on the Entra application registration or enterprise application. Users and service principals are supported.
  • Technical owners: EasyLife 365 Identity records. Version 1 accepts users only.
  • Business owners: EasyLife 365 Identity records. Version 1 accepts users only.

The API uses object IDs. It does not resolve display names, UPNs, or application IDs during a write.

Before you start​

You need:

  • An Entra tenant where the target applications exist.
  • Permission to register an application and grant tenant-wide admin consent, or an Entra administrator who can do those steps.
  • The EasyLife 365 Identity service principal available in the tenant, to add as an owner of the applications you want to manage (see step 2 below).

See Create Application Registration for how to register a calling application and request a token for the selected ring, and the reference pages below for the endpoint URLs, permissions, and request/response shapes.

Ownership API reference​

This guide walks through registering a service-principal caller and synchronizing ownership end to end. For the full permissions table, request and response body shapes, and worked examples for each operation, see:

For an app-only request, the API checks the EasyLife 365 Identity ownership prerequisite before it evaluates whether the request is deliberately removing EasyLife 365 Identity. If EasyLife 365 Identity is not already an owner, the request is refused; allowUnmanage does not bypass that prerequisite. Once the caller is authorized to perform the change, removing EasyLife 365 Identity without allowUnmanage: true is also refused.

1. Register the calling application and grant it permissions​

Follow Create Application Registration to register a service-principal caller — such as an Azure DevOps service connection, GitHub Actions workload, or scheduled integration — configure its credential, add an application permission, and grant tenant-wide admin consent.

Use the least-privilege permission required:

OperationPermission
Read ownership onlyIdentity.Ownership.Read.All
Read and change ownershipIdentity.Ownership.ReadWrite.All

Existing broad permission​

Identity.Config.ReadWrite.All also authorizes this API. Use it only when the calling application already requires broad Identity administration. Do not add it solely for ownership synchronization when Identity.Ownership.ReadWrite.All is sufficient.

2. Make the target application managed by EasyLife 365 Identity​

Application owners only

When an app-only request would make an effective change to Entra application owners, the EasyLife 365 Identity service principal must already be an owner of the target object. The API performs those writes with the EasyLife 365 Identity's Microsoft Graph permission Application.ReadWrite.OwnedBy, so this applies to application-owner adds, replacements, and removals. A request that includes applicationOwners but produces no application-owner change does not need this prerequisite. A delegated caller whose own Entra permissions authorize the owner change also does not need the EasyLife 365 Identity service principal to own the target. Changes that affect only technical owners or business owners do not require it either.

For each target application, add the matching-ring EasyLife 365 Identity service principal as an owner and confirm that it appears in the target object's owner list.

For an enterprise application, the target is the target application's service principal. Add the EasyLife 365 Identity service principal as an owner of that target service principal as follows:

  1. Identify the target enterprise application's Object ID. This is the target service principal object ID used as AppObjectId.
  2. Add the matching-ring EasyLife 365 Identity service principal as an owner through the Entra admin center or an approved administrative automation tool.
  3. Confirm that the EasyLife 365 Identity service principal appears in the owner list.

Do not add the calling automation application unless it is intentionally also an owner.

Enterprise application limitation

For an enterprise application target, the Entra admin center may allow only user accounts in the Add owners dialog. If the EasyLife 365 Identity service principal does not appear in the search results, the portal cannot complete this prerequisite. Ask an Entra administrator to add the EasyLife 365 Identity service principal through Microsoft Graph or an approved administrative automation tool, using the target service principal's Object ID and the matching ring's EasyLife 365 Identity service principal object ID.

Return to the target enterprise application's Owners page and confirm that the EasyLife 365 Identity service principal appears in the owner list. Confirm that you selected the service principal whose Object ID matches the EasyLife 365 Identity service principal for the same ring.

There are two different enterprise applications involved here:

  • The target enterprise application is the object whose owners the API will read or change.
  • The EasyLife 365 Identity enterprise application is the service principal that must already own the target so EasyLife 365 Identity can use Microsoft Graph's Application.ReadWrite.OwnedBy permission.

If Owners or Add owners is unavailable, your signed-in account may not have permission to manage enterprise-application owners. Ask an Entra administrator to perform this step. If the EasyLife 365 Identity application does not appear in search, confirm that you are in the correct tenant and that you selected the EasyLife 365 Identity service principal for the same ring as the API URL. The Object ID of the target service principal is also available under its Properties page; use that value in the ownership API URL, not its Application (client) ID.

The API uses the live owner list for this check. A scan or isManaged value can lag behind a recent owner change; the capabilities.identityIsOwner value returned by GET is the authoritative API result.

3. Identify the target object​

Use the target object's Entra Object ID, not its Application (client) ID. Use appRegistration for an app registration target or enterpriseApplication for an enterprise application target.

4. Request an access token​

Follow Create Application Registration → Request an app-only token to request a token for the selected ring, using the .default scope shown there. Send the resulting token as a bearer token on every ownership API request below.

5. Read the current ownership​

Send the access token as a bearer token. The type query parameter is required. Use the Get Application Ownership endpoint.

Check these fields before writing:

  • app.objectId confirms that the requested object was addressed.
  • app.type confirms whether the object is an app registration or enterprise application.
  • applicationOwners contains the live Entra owners, including service principals.
  • technicalOwners and businessOwners contain Identity's recorded owners.
  • capabilities.identityIsOwner must be true before an application-owner write can succeed.
  • capabilities.canWriteApplicationOwners, canWriteTechnicalOwners, and canWriteBusinessOwners describe the current write capability.
  • capabilities.reason explains a false capability when a reason is available.

6. Apply the change​

The PUT endpoint is declarative. Each supplied ownership bucket describes the desired state for that bucket. A bucket that is omitted is left unchanged. Send the request to the Replace Application Ownership endpoint.

The API adds owners before removing owners. This prevents the target from passing through a state with fewer owners than both the old and new sets. Re-read the GET endpoint after the PUT and verify the final state.

Troubleshooting checklist​

  • The token has no roles claim: Confirm the API permission was added as Application permissions, not Delegated permissions, that admin consent was granted in the target tenant, and that the token was requested after consent — acquire a new token after changing permissions.
  • The API returns 403 Forbidden: Decode the token without exposing it in logs and verify aud matches the Admin API for the same ring as the URL, tid is the tenant where the target object exists, and roles contains Identity.Ownership.Read.All for GET or Identity.Ownership.ReadWrite.All for PUT. Do not paste access tokens into tickets, source control, or chat.
  • The apply is refused because Identity is not an owner: The EasyLife 365 Identity service principal is not an owner of the target application. Add the correct ring's EasyLife 365 Identity enterprise application as an owner, then retry.
  • The apply is refused because it would remove Identity: The desired application-owner list would remove the EasyLife 365 Identity service principal. Include it in the desired list, or set options.allowUnmanage to true only when deliberately stopping EasyLife 365 Identity management for that application.
  • The apply is refused because the expected owners did not match: The application changed after the GET. Read the current owners again, update expectedApplicationOwners, and retry. This prevents an older automation run from overwriting a newer owner change.

Security recommendations​

  • Use Identity.Ownership.Read.All unless the integration must write.
  • Use a certificate or workload identity instead of a long-lived client secret where possible.
  • Store credentials only in a managed secret store or CI/CD secret service.
  • Restrict who can change the calling application's API permissions and credentials.
  • Keep allowUnmanage and allowNoOwners disabled unless a controlled decommissioning workflow requires them.
  • Log request IDs, target object IDs, status codes, and returned stage results, but never log access tokens or client secrets.