Custom actions in Dataverse
How Dataverse custom actions expose named operations as callable messages — designed for integration, reusable, callable from many surfaces.
Beyond standard CRUD operations (Create, Read, Update, Delete), Dataverse supports custom actions — named operations the maker defines that encapsulate business logic and become callable through the Web API, plug-ins, JavaScript, Power Automate flows, and other surfaces. Custom actions are the bridge between low-code configuration and clean integration surfaces.
What a custom action is. A custom action is a Dataverse-defined named operation:
- Has a name (e.g.
CalculateCustomerHealthScore,ApproveExpense,MergeOpportunities). - Has input parameters — typed inputs the caller supplies.
- Has output parameters — typed outputs the action returns.
- Has a definition — what the action does (typically a workflow or plug-in implementing the logic).
The action becomes a callable message in Dataverse, addressable through the Web API and other invocation surfaces.
Creating a custom action. Through the maker portal:
- Create a new process; choose Action as the category.
- Define input parameters and output parameters with types.
- Build the workflow steps that implement the logic — typical step types: query records, update records, send emails, call other actions, set output parameters.
- Activate.
Alternatively, custom actions can be implemented in code:
- Register a plug-in against the custom action's message.
- The plug-in receives the input parameters, performs the logic, sets the output parameters.
Calling a custom action.
- From the Web API:
POST /api/data/v9.2/CalculateCustomerHealthScorewith input parameters in the JSON body. Returns the output as JSON. - From JavaScript on a form:
Xrm.WebApi.execute(...)orXrm.Utility.invokeProcessAction(...). - From Power Automate: the Dataverse connector exposes custom actions as callable steps; the flow designer picks the action from a list and provides inputs.
- From a plug-in: invoke the action through the
IOrganizationService.Execute()method. - From X++ in F&O integration scenarios: through the Dataverse SDK.
Use cases.
-
Encapsulate complex business operations. "Approve Expense" might involve checking the manager's authorisation limit, deducting from the budget, creating an approval record, sending a notification, and updating the expense status — five operations in one transactional unit. The custom action wraps them; callers just call "Approve Expense".
-
Provide stable APIs. Custom actions decouple consumers from internal implementation. External integrations can call "MergeDuplicateAccounts" without knowing the dozen steps inside; if you refactor the implementation, callers don't need to change.
-
Reusable logic. A custom action callable from JavaScript on the form, from a Power Automate flow, from a plug-in, and from an external integration — write once, use many times.
-
Action without a record context. "Recalculate All Account Scores" is a global operation, not tied to a single record's CRUD. Custom actions support global scope.
Bound vs unbound actions.
- Bound action — associated with a specific table; called on a specific record. "Approve" bound to Expense means you call
POST /api/data/v9.2/expenses({id})/Approve— the action operates on that specific expense. - Unbound action — not tied to a specific record; called on the table level or globally. "GenerateMonthlyReport" doesn't operate on a single record.
Each has appropriate use cases.
Input and output parameter types. Custom actions support:
- Primitive types — string, integer, decimal, boolean, datetime.
- Entity references — pointers to other records (Lookup).
- Entity collections — sets of records.
- OptionSetValue — choice values.
- Money — currency-typed values.
Output parameters work the same way.
Transactional behaviour. Custom actions implemented as synchronous plug-ins or synchronous workflows run inside the originating transaction. Errors roll back the operation. Async actions run after the transaction; errors don't roll back.
Limits.
- Custom action complexity is bounded — very large operations may need to be split into multiple actions.
- Power Automate's custom-action support has occasionally lagged the underlying capability; verify per scenario.
- Custom-action versioning — changing inputs / outputs is a breaking change for callers. Treat as API contract.
Common pitfalls.
- Building custom actions for trivial CRUD — overhead exceeds benefit; standard Web API CRUD is fine.
- Custom action with no clear contract — confusing for callers; document inputs and outputs.
- Synchronous custom actions doing slow work — UI freezes.
- Async custom actions where sync was needed — transaction semantics don't match intent.
Operational reality. Custom actions are a powerful integration tool. Build them deliberately for genuine business operations that benefit from encapsulation and reusability. Document the contracts. Treat them as APIs.
Related guides
- Async jobs in DataverseHow Dataverse runs background work — system jobs, async plug-ins, workflow runs, and how to monitor, troubleshoot, and prevent the async backlog from getting out of hand.
- Bulk delete jobs in DataverseHow Dataverse's bulk delete handles mass record cleanup — scheduling, filters, retention policies, and the operational discipline around storage management.
- Business rules in DataverseHow business rules let you add field-level logic to forms without code — set value, lock field, show error, recommendation, and the limits of the engine.
- Business units and teams in Dataverse — a deep diveHow business units, owner teams, access teams, and Microsoft 365 group teams compose the security model in Dataverse — what each is for, how they interact, and the common design mistakes.
- Calculated and rollup columns in DataverseHow calculated columns and rollup columns work in Dataverse — what each does, the performance trade-offs, and when to use a formula column or a Power Automate flow instead.