Power Automate: Unlock Hidden Step Data with actions(), outputs(), and body()
Learn how to retrieve inputs, outputs, status codes, and response bodies from previous steps using these three essential workflow functions.
Dynamic content is convenient, but it only shows a fraction of what each action can provide. Status codes, headers, and even some input fields are hidden from that menu. The actions(), outputs(), and body() functions let you reach into any previous step and pull out any property from its complete JSON response. This article walks through each function using a practical SharePoint example, so you can confidently grab the data you really need.
Scenario: New Employee Onboarding List
We'll use a SharePoint list named NewEmployeeOnboarding with the columns below. This list tracks requests for equipment and account setup.
| EmployeeName (text) | Department (choice) | StartDate (date) | EquipmentOrdered (Yes/No) | Status (choice) |
|---|---|---|---|---|
| Alice Tran | Engineering | 2026-07-01 | Yes | Approved |
| Bob Martinez | Marketing | 2026-07-15 | No | Pending Approval |
| Carol Singh | Human Resources | 2026-06-20 | Yes | Completed |
| David Chen | Engineering | 2026-08-01 | No | Submitted |
| Emily Johansson | Finance | 2026-07-22 | Yes | Approved |
The flow we'll build will query this list and then explore the data that is returned.
Building the Exploration Flow
Create an Instant cloud flow and add a trigger of your choice (e.g., manually trigger a flow). Then add a SharePoint – Get Items action and configure it to point to your site and the NewEmployeeOnboarding list. No filter is needed for now.
After that, insert a Compose action. We will use multiple Compose actions to inspect the output of the Get Items action with different functions.
The actions() Function: The Complete Picture
The actions() function returns the full inputs and outputs of any previous step as a JSON object. This is the rawest view – it includes every parameter you passed in and the entire response.
Write the following expression in the Compose action:
actions('Get_items')When you run the flow, the output will be a large JSON object showing the action's schema, inputs (like site address, list name, query parameters), and outputs (including body, status code, and headers).
Digging into a Specific Input
To extract just one property from this object, use the ? syntax to navigate through the JSON. For example, to get the site address that was used as input, write:
actions('Get_items')?['inputs']?['parameters']?['dataset']The result will be the SharePoint site URL, such as https://yourtenant.sharepoint.com/sites/Onboarding.
The outputs() Function: Status, Headers, and Body
The outputs() function returns a subset of the action's response: the statusCode, headers, and body. It strips away the input details and the top-level action metadata.
Replace the Compose expression with:
outputs('Get_items')The JSON you see will have three top-level properties:
statusCode– typically200for a successful request.headers– response headers (content-type, date, etc.).body– the actual data from SharePoint (the items).
If you only need the status code, use:
outputs('Get_items')?['statusCode']This is useful for error handling: you can check whether a step succeeded (200) or returned a different code.
The body() Function: Just the Data
The body() function is shorthand for outputs('name')?['body']. It returns the response body of the action, which typically contains the meaningful data.
body('Get_items')The body for a Get Items action will contain a value array with the list items, along with metadata like odata.nextLink if there are more items. For most work, you want the value array:
body('Get_items')?['value']This expression returns each SharePoint item as an object, which you can then iterate with an Apply to each or use in other actions.
When to Use Which Function
actions()– When you need the original input parameters (e.g., the query that was sent) or the complete action definition. Use it rarely because the output is large and usually contains more than you need.outputs()– When you need the full HTTP response, including status code and headers. It's indispensable for error handling or if an API returns information in the headers.body()– When you simply want the data from the action. In many cases, the dynamic content picker already exposes body properties, but if a property is missing (e.g., nested JSON),body()is the reliable fallback.
Common Mistakes and Troubleshooting
1. Incorrect Action Name
The action name must match exactly, including colons, underscores, and spaces. The easiest way to avoid typos is to use the dynamic content picker: start typing actions( and then select the action from the list that appears.
2. Using outputs() When You Already Have the Body
If the property you need is already offered in the dynamic content menu, don't waste an expression. Use outputs() only for status codes and headers that are hidden.
3. Forgetting the ? Property Accessor
To navigate into JSON, always use ?['propertyName']. Using ['propertyName'] directly after the function will still work, but staying consistent with the ? syntax avoids errors when properties might be null.
4. Not Handling Pagination
Get Items may not return all items if the list is large. The body includes an odata.nextLink property when there are more results. Use a pagination pattern (loop over the next link) to retrieve the full dataset.
Performance and Security Considerations
- Large lists: Retrieving many items in one
Get Itemscall can slow down your flow. Always filter as much as possible with OData queries.actions()andoutputs()still include the entire response, which could be heavy if you log them unnecessarily. - Delegation: The functions themselves are evaluated at runtime and don't affect delegation. However, the underlying action (e.g.,
Get Items) should use filtered queries for efficiency. - Security: The output of any action can contain sensitive data. Avoid writing these functions in test Compose steps that you forget to remove, and be cautious if you store the results in logs or emails.
A Practical Example: Checking an Action's Status
Suppose you have an action that sometimes fails. You can use outputs() to capture the status code and branch your flow:
equals(outputs('Send_an_HTTP_request')?['statusCode'], '200')If the HTTP request returns a 201 created instead of 200, this condition would be false. You can then trigger a fallback or notification.
Final Recommendations
- Start with
body()if you're just after the data. It's the most concise and covers 90% of use cases. - Move to
outputs()when you need to check if something succeeded or to read headers. - Reserve
actions()for debugging or when you need to verify what inputs were sent. - Always test your expressions with a Compose action first to see the raw JSON before using them in logic.
These three functions give you a backstage pass to every step in your flow. Master them, and you'll never be limited by the dynamic content picker again.
References
- Original article by Matthew Devaney
- Microsoft Learn: actions function
- Microsoft Learn: outputs function
- Microsoft Learn: body function
Core principles for resilient, maintainable, and efficient cloud flows, distilled from real-world implementations.
Build flows that gracefully handle failures and automatically notify you with run details.
Discover the trade-offs between Content-ID, Base64, and the Microsoft Graph API for embedding images in Power Automate emails. This guide covers which method works best for Outlook, Gmail, and more.