Introduction

To expose a governed Dataverse operation, define its named custom application programming interface (API) and typed contract, attach the implementing plug-in, enforce caller and record authorization, and configure Microsoft Power Platform managed identity version 2 for any outbound Azure access. Then test these boundaries separately: a caller may be entitled to request the operation while the plug-in identity lacks access to the external resource. Successful token acquisition alone does not establish that the business operation should succeed.

Custom APIs, business events and plug-in identity serve successive parts of this procedure. The API states what the caller requests and receives. A business event lets subscribers react to a successfully completed operation. The outbound identity establishes which workload Azure trusts. This guide combines them around one illustrative service-request release operation; its names and business rules are proposed design choices, not built-in Dataverse capabilities or executed tenant results.

Architecture Overview

Assume a service team needs to release an eligible request for fulfillment. A developer proposes an entity-bound action named lpx_ReleaseServiceRequest for a custom table named lpx_servicerequest. The caller supplies a request identifier; the server checks permission and eligibility, reads a small policy document from an approved Azure resource, and records the release in Dataverse. Fulfillment happens separately.

The recommended boundary is deliberately narrow. The caller cannot provide an arbitrary resource address, choose the plug-in identity, or replace the policy document. The result confirms the recorded release decision. It does not mean a warehouse accepted work or that every subscriber has finished.

Treat the path as three independently reviewable contracts:

BoundaryQuestion to settleEvidence to require in the example
Caller to named operationWho may release which request?An authorized caller succeeds on an eligible row; an unauthorized caller cannot release it.
Plug-in to AzureWhich signed component may read which policy?The intended component accesses its policy; unrelated resources remain inaccessible.
Completed operation to subscriberWhat precisely has happened?The subscriber can identify the request and interpret completion without assuming fulfillment.

Before implementation, use an isolated Dataverse development environment, an unmanaged development solution, the Plug-in Registration tool (PRT), a supported plug-in development toolchain, and administrative help for the required identity and Azure permissions. Use synthetic requests and a disposable policy resource. Azure resources can incur charges. Keep signing keys and tokens out of source control, tracing, and API responses.

Core Components and Contract Choices

Step 1: Define the custom API before writing the caller

A Dataverse custom API creates a message callable through the Web API or software development kit (SDK) for .NET. It can have a plug-in implementation or simply carry an event. Custom process actions are another way to create custom messages; custom API is the developer-oriented choice here because the operation is implemented in code.

Choose Action for this state-changing operation. Functions are read-only HTTP GET operations and require a response property; actions use POST. The Dataverse connector supports performing actions, which also matters if Power Automate will call the operation. Choose Entity binding for a single request: Dataverse supplies the Target request parameter as an EntityReference. Global binding has no associated table; EntityCollection binding does not automatically supply a collection parameter.

Write a proposed contract such as this before creating its metadata:

Contract itemProposed type and meaningAcceptance consequence
TargetImplicit entity-bound reference to lpx_servicerequestAn identifier for another table must not authorize a release.
RequestIdRequired Guid, generated by the calling application for the logical attemptPreserve it when retrying an uncertain outcome; never reuse it for a different request.
ReleaseIdString response identifying the recorded releaseA replay must return the same business result rather than create another release.
ChangedBoolean response indicating whether this invocation changed the business stateA caller can distinguish a new transition from an already-recorded result.

These replay semantics require application logic and durable state. Declaring a Guid parameter does not implement them. Decide where the request-to-result association lives, how concurrent attempts are prevented from creating two releases, and what happens when a reused RequestId targets another row. For this design, reject that last case as a contract violation. Do not allow an unchecked read followed by a write to stand in for a concurrency strategy.

Avoid returning a successful response with empty defaults for a refused release. Define the refusal as a failed operation with a useful, non-sensitive explanation; reserve Changed: false for a previously successful release. Otherwise callers cannot distinguish rejection from replay.

Step 2: Attach the implementation and control extension

Register the assembly and associate its plug-in type through the custom API's PluginTypeId. The main implementation does not require a separately registered processing step. It reads InputParameters and writes OutputParameters. Add the assembly and required types to the development solution; assembly registration alone is not release packaging. Any additional registered steps must be added separately.

For this design, select AllowedCustomProcessingStepType as Async Only: subscribers may react after completion without changing the release decision. None closes that extension surface; Sync and Async allows synchronous extensions that can alter or cancel behavior. Choose intentionally before consumers depend on it.

Implement the recommended business sequence as follows:

  1. Validate the message, parameter types, target table and request identifier before contacting Azure.
  2. Check the caller's release entitlement and the target row's eligibility. Resolve an existing successful result before repeating work.
  3. Read the approved policy using the configured outbound identity. Validate the policy's expected shape and required business values; an unreadable or malformed policy must not silently authorize a release.
  4. Apply the guarded Dataverse transition and persist the result association. Set both response properties explicitly from the recorded result.

This sequence is a design requirement for the example, not a claim that Dataverse generates the business logic. Keep the Azure operation read-only here. Introducing an external write would require a separate recovery contract for a remote side effect followed by a local failure; a Dataverse failure must not be assumed to reverse an Azure change.

How Components Work Together

Step 3: Govern execution independently of discovery

Use ExecutePrivilegeName to require an appropriate existing Dataverse privilege. Microsoft documents no supported facility for a developer to invent a new standalone privilege for this property. Verify the selected privilege exists and that its assignment actually represents the intended release entitlement. The API gate is only one part of the design: the implementation must also enforce the chosen access rules for the target and its operations.

IsPrivate hides a custom API from metadata and code generation; it is not an authorization boundary. A caller that knows the message may still compose a request. For this supported integration contract, keep the API discoverable and treat its published parameter names and meanings as compatibility commitments.

If an external service calls Dataverse as an application, its Dataverse application user and assigned security roles govern that inbound access. That is separate from the plug-in's outbound identity. Do not grant broad Dataverse roles merely to fix an Azure denial, or expand Azure permissions to fix a rejected Dataverse caller.

The following illustrative late-bound client fragment uses the proposed contract after an authorized IOrganizationService named service and a valid requestRowId have been supplied. It is not a complete authenticated client or evidence of execution:

var request = new OrganizationRequest("lpx_ReleaseServiceRequest")
{
   ["Target"] = new EntityReference("lpx_servicerequest", requestRowId),
   ["RequestId"] = logicalRequestId
};

OrganizationResponse response = service.Execute(request);
string releaseId = (string)response.Results["ReleaseId"];
bool changed = (bool)response.Results["Changed"];

Here logicalRequestId is the caller's retained Guid for the attempt. A timeout leaves the caller uncertain about completion, so creating a fresh identifier on every retry defeats the proposed replay contract. Broader retry and concurrency implementation belongs in AB-400: Reliable Dataverse Bulk and Background Operations.

Step 4: Establish outbound managed identity version 2

The current Microsoft setup recommends version 2 for new and existing plug-ins. Provision an application registration or user-assigned managed identity; sign and register the plug-in; configure a federated identity credential; create a Dataverse managed identity record; associate the assembly or package; and grant resource access. The plug-in requests tokens through IManagedIdentityService.AcquireToken for the destination resource's scope. An inbound Dataverse scope is not a substitute for the scope of an Azure destination.

For a trusted-issuer production certificate, version 2 uses SHA-256 Base64URL hashes of the full issuer and subject Distinguished Name (DN) strings. Use the exact runtime strings from X509Certificate2.Issuer and .Subject, the intended environment, and cloud-specific federation settings. A self-signed certificate is development-only. The Dataverse record uses version: 2, credentialsource: 2, subjectscope: 1, the identity's application ID and tenant ID; bind it to the correct assembly or package through managedidentityid.

In the example, assign only the permission needed to read the selected policy resource. Record the identity owner, resource owner, certificate renewal responsibility, and environment mapping alongside the deployment instructions. A deployment that imports the custom API but omits this trust setup is incomplete.

Test token acquisition and the actual resource read independently. For AADSTS700213, compare the configured federation subject with the runtime certificate/environment values and confirm version 2. When a token is obtained but the resource refuses access, investigate the destination scope and resource authorization rather than broadening the caller's Dataverse role.

Step 5: Give subscribers a precise business event

Dataverse business events expose selected events through a catalog organized around a solution and its categories. Custom APIs can represent these events, including notification-only APIs without a main plug-in. Notifications describe successfully completed operations and support asynchronous reactions; they are not a place for a subscriber to veto an already completed release.

Catalog the release action only if “release operation completed” is useful to consumers. Document that meaning alongside Target and RequestId. A successful replay can complete the API without creating a new release, so a subscriber must not interpret every completion as another fulfillment instruction. In this proposed design, the subscriber resolves the stable recorded ReleaseId and uses it to suppress repeated business work. Implementing that receiver and its transport is outside this guide.

If consumers instead need a notification specifically meaning “a new release was recorded,” design a separate, narrowly named notification contract and a controlled producer that emits it for that transition. Microsoft recommends an On name prefix for notification-only actions. A notification API's name does not prove that the represented business fact occurred; the producer must establish that fact before announcing it.

Keep event data small and sufficient to identify what happened. A full request export, attachments, and policy contents would expand both the disclosure surface and the consumer's coupling. Business events are not a bulk-data export mechanism. Cataloging also does not implement delivery guarantees, consumer authorization, or recovery; those belong in AB-400: Publishing Dataverse Events to External Services.

Design Considerations and Acceptance

Step 6: Verify the complete contract in isolation

Use test identities and disposable data to verify the following expected observations. These are acceptance criteria, not results obtained from a tenant:

TestExpected observation for the proposed designFailure meaning
Authorized caller, eligible row, readable valid policyOne recorded release; nonempty ReleaseId; Changed: trueContract, policy evaluation, or persistence is incomplete if success has no recorded result.
Same target and RequestId repeatedSame release result; Changed: false; no new business transitionReplay logic is absent if another release appears.
Same RequestId used for another targetExplicit rejectionThe replay association is not bound to the intended operation.
Caller lacks the execute privilege or target authorizationFailure without a release or policy access initiated by the implementationAuthorization occurs too late or uses the wrong principal.
Federation subject deliberately mismatchedToken acquisition fails; request remains unreleasedA successful release would indicate an unintended fallback or ignored dependency.
Identity has no policy-resource permissionResource read fails; request remains unreleasedAuthentication was confused with authorization if the operation proceeds.
Policy is malformedControlled refusal; no recorded releaseParsing defaults must not become permission to proceed.
Subscriber unavailableAPI success is assessed from its recorded release, separately from subscriber processingThe caller's response is being interpreted as end-to-end fulfillment.

Run concurrent attempts too. Inspect durable results after both calls finish; checking only the two response bodies can miss duplicate state. Include the scenario where the caller loses the response and retries after the original invocation completed. Trace the logical attempt and release identifiers without recording tokens or policy secrets.

Before distributing the definition, review the managed solution and set Is Customizable to false on the custom API, its request parameters and response properties as Microsoft recommends. Preserve a supported contract when upgrading: changing a parameter's meaning under the same name can break a caller even when its code still compiles.

For cleanup, first stop the disposable callers and subscriptions, then remove only the test solution components, test data and dedicated Azure resources. Revoke test role assignments and federation credentials after confirming no other workload shares them. Do not delete a shared identity or signing certificate to clean up one experiment.

Common Mistakes

The most damaging mistake is treating one successful layer as proof of all the others. Metadata discovery does not establish authorization. Token acquisition does not establish resource permission. A successful API response does not establish downstream fulfillment. Store distinct evidence for each boundary so an operator can identify the failing contract.

Another mistake is publishing the operation before deciding how extensions and retries affect its meaning. A synchronous third-party extension can change a contract that the publisher intended to own. A replay can be technically successful while representing no new business event. Resolve those semantics before integrations multiply.

Finally, an assembly registered in a developer environment is not a portable release. Include the API definition, typed contract and implementation in the solution, then separately account for environment-specific identity trust, resource authorization and test evidence. Keep the main API implementation distinct from optional subscriber step registrations.

Certification Relevance

The selected AB-400 study-guide baseline, verified October 15, 2026 for skills effective October 16, 2026, places custom API messages, business events and plug-in managed identity within Extend Microsoft Power Platform. Product sources were rechecked October 16, 2026 for this guide. The scope baseline does not establish live exam availability; no verified AB-400 Registry record was available for this series.

The practical outcome is the ability to explain and verify one governed capability from caller to implementation to resource access and completion notification. Generic execution-stage behavior is developed in AB-400: Dataverse Plug-ins and the Event Execution Pipeline; the contract here builds on that foundation.

Conclusion

Expose the smallest operation whose business meaning you can preserve. Define its inputs, outputs, authorization and replay behavior, attach the implementation, configure outbound version 2 identity, and make event semantics explicit. Accept the design only when allowed calls succeed and the corresponding denied, replayed and dependency-failure cases produce the intended durable state.

Authoritative Sources