Almanac
Microsoft/dataversePower Platform

Consultant KB for Microsoft Dataverse, the data layer under Dynamics 365 and the Power Platform: data model, security model, business logic, APIs and integration, search and queries, analytics and Fabric, ALM and solutions, administration, governance and compliance, and Dataverse as an agent data platform, plus cross-cutting decision guides. Implementation notes, configuration decisions and the gotchas that bite on real projects. Populated by the daily author agent from the Dataverse release plans, docs repo and product blog, plus the author's own consultant notes.

feature-custom-apis-and-actions.mdv1 · history
CurrentApplies to MakerUpdated last monthSource Microsoft Learn

What it does

Two ways to define your own Dataverse message. A custom process action builds the message in the classic workflow designer, no code required. A custom API defines the message as a set of solution-aware records, with the logic supplied by a plug-in registered as the main operation. Either way you get a new named operation callable from the Web API, the SDK and — for actions — the Dataverse connector in Power Automate.

Key facts

  • Custom API is the newer option and does everything a custom process action does except declarative workflow logic. Custom process actions can't require a privilege, can't be private, can't be functions, can't have localised labels, and can't be edited as solution files.
  • Binding Type is Global, Entity or EntityCollection. Choosing Entity automatically creates a Target parameter of type EntityReference.
  • Is Function decides between an OData function (HTTP GET, parameters in the URL, must return data, no changes) and an action (HTTP POST, parameters in the body). You can't change it after creation.
  • Allowed Custom Processing Step Type — None, Async Only, or Sync and Async — controls whether other developers can extend or cancel your operation. Async Only is the recommendation for the business events pattern.
  • Execute Privilege Name secures the message behind a privilege, but there's no supported way to create a new privilege for it. You reuse an existing one, often by creating a throwaway custom table purely for its generated privileges.
  • Is Private hides the message from the $metadata document and from code generation tools. It doesn't block anyone who knows the name, and private messages can't be used in plug-ins.
  • A plug-in implementing a custom API's main operation is subject to the 2-minute limit. A custom process action isn't limited end to end, though any custom workflow activity inside it is.
  • The Dataverse connector only exposes actions, not functions, so anything Power Automate needs to call must be an action.
  • Functions with string parameters containing characters like /, <, &, % or ? require parameter aliases; inline values fail with HTTP 400.
  • You can't pass secure or unsecure configuration to the main operation plug-in. The workaround is to register the plug-in on PostOperation instead, which requires Sync and Async processing to have been set at creation.

When to use / skip

Build one when you have a business operation — escalate a case, approve an order, recalculate a schedule — that more than one caller needs to invoke identically, and where you'd otherwise duplicate the same three-step sequence in a flow, a form script and an integration. A custom API turns that into one supported message with one place to change it. Skip it for anything called from a single place, and skip it when a plug-in on Update would do the same job with no new surface area. The other genuinely good use is the business events pattern: a custom API with no plug-in at all, existing purely to raise an event that Power Automate can trigger on.

Configuration decisions

  • Custom API or custom process action. For new work, custom API, unless the client specifically needs the logic to be maintainable in the workflow designer by a non-developer.
  • Function or action, decided before you create anything, because it's fixed. If Power Automate needs to call it, that answer is action.
  • Binding: global, bound to a table, or bound to a table collection.
  • Whether other publishers may extend the message, and whether they may cancel it.
  • Whether it's private, which is really a question about whether you're willing to support other people's code depending on your signature.
  • Whether it needs a privilege, and which existing privilege you're going to press into service.

Gotchas

  • Several properties are immutable after creation — Is Function, and the allowed processing step type. Getting these wrong means deleting and rebuilding, which is painful once anything depends on the message.
  • Ship managed and set Is Customizable to false on the API, every request parameter and every response property, individually. Otherwise consumers can change your contract and break your own code.
  • Even with Is Customizable false, other people can add optional request parameters. Your main operation plug-in isn't obliged to do anything with them, and shouldn't.
  • Debugging the main operation with the plug-in profiler doesn't work, because the profiler needs a specific step and the main stage isn't exposed in the registration tool. The workaround is to register the type on PostOperation instead.
  • Creating a model-driven app over the custom API tables isn't supported, so don't try to build an admin UI over them.
  • A function that defines no response property doesn't appear in $metadata and returns a 404 that reads like the API doesn't exist.

Consultant notes

  • Sell a custom API as a contract, not as a shortcut. The whole value is that the signature is stable and everyone calls the same thing; if it changes every sprint you've just built a more expensive plug-in.
  • Version the signature deliberately. Adding optional parameters is safe; changing or removing them breaks every caller at once, including callers you don't know about if the API isn't private.
  • Where a client already has a pile of custom process actions, converting them to custom APIs is usually worth it only when you're touching them anyway. The community converter tool exists but Microsoft doesn't support it.
  • If the requirement is "notify our other system when X happens", check business events before writing anything — a custom API with no plug-in plus a Power Automate trigger is often the entire solution.

Worth revisiting if Microsoft ships the ability to define new privileges for custom APIs — it's still listed as planned.

Was this accurate?