API Calls, HTTP Requests and Adaptive Cards
Connect your agent to external APIs with Send HTTP Request, parse JSON responses, and build rich Adaptive Cards for interactive user experiences.
Connecting Your Agent to the Outside World
Think of your agent as a cashier at a fast-food counter. The cashier takes your order (the conversation), but to get the food they need to call back to the kitchen (an API). The kitchen sends back the meal on a tray (the JSON response). The cashier then arranges it nicely on your table β that is the Adaptive Card.
Without API calls, your agent can only talk. With API calls, it can fetch live data β weather, order status, account balances β from any system that speaks HTTP. And with Adaptive Cards, it can show that data as beautiful, interactive cards instead of plain text.
Send HTTP Request vs Tool REST API
Two approaches exist for calling external APIs from an agent. The exam expects you to know when to use each.
| Feature | Send HTTP Request (Flow Action) | Tool with REST API (Custom Connector) |
|---|---|---|
| What it is | A built-in Power Automate action that makes raw HTTP calls | A reusable connector built from an OpenAPI specification |
| Setup effort | Low β configure URL, method, headers, body directly in the flow | Medium β import or author an OpenAPI spec, configure auth, publish |
| Auth options | Manual β set auth headers yourself (API key, bearer token, basic auth) | Managed β OAuth2, API key, or certificate handled by the platform |
| Reusability | Single flow only β each flow configures its own request | Shared across flows and agents β once published, any flow can use it |
| Response handling | Returns raw text β you must ParseJSON() to extract fields | Returns typed objects β fields are available directly in the flow designer |
| Best for | Quick integrations, prototyping, one-off calls, simple APIs | Production integrations called from multiple flows, complex APIs with many endpoints |
| Exam signal | Question mentions quick setup, single API call, or no connector available | Question mentions reusable, multiple flows, or OpenAPI specification |
Configuring a Send HTTP Request
The Send HTTP Request action has these configuration fields:
| Field | Purpose | Example |
|---|---|---|
| Method | HTTP verb | GET, POST, PUT, DELETE |
| URI | The API endpoint URL | https://api.weather.com/v1/forecast |
| Headers | Request headers as key-value pairs | Content-Type: application/json, Authorization: Bearer {token} |
| Body | Request payload (for POST/PUT) | {"city": "Auckland", "units": "metric"} |
| Authentication | Auth type if using managed auth | None, Active Directory OAuth, Raw (manual headers) |
| Cookie | Optional cookies | Rarely used in agent flows |
The response is always returned as plain text, regardless of the content type. This is the most important thing to remember for the exam.
ParseJSON() β The Critical Step
The Send HTTP Request action returns the entire response body as a single text string. To extract individual fields, you must use the ParseJSON() expression in Power Automate.
// Example API response (returned as plain text by the HTTP action):
{
"city": "Auckland",
"temperature": 18,
"condition": "Partly cloudy",
"wind": { "speed": 22, "direction": "SW" },
"forecast": [
{ "day": "Tomorrow", "high": 20, "low": 14 },
{ "day": "Wednesday", "high": 17, "low": 12 }
]
}
To use this data in subsequent flow actions, you parse it with a schema:
- Add a Parse JSON action after the HTTP action
- Set the Content to the HTTP response body
- Provide a Schema that describes the JSON structure (you can generate this from a sample response)
- Now individual fields like
body/city,body/temperature, andbody/wind/speedare available as typed outputs
Without ParseJSON(), you have a single text blob. With it, you have structured data you can map to flow outputs and topic variables.
Exam tip: The response is TEXT β you must ParseJSON()
This is tested frequently. The Send HTTP Request action returns the response as a text string, even when the API sends Content-Type: application/json. You cannot directly access body.temperature β you must parse the JSON first.
If an exam question shows a flow that calls an API and then tries to use a field from the response without a Parse JSON step, the answer is βthe flow fails because the response is not parsed.β
Adaptive Cards
Adaptive Cards are a JSON-based framework for rendering rich, interactive UI elements in chat. They work across Teams, Outlook, Copilot, and web chat.
Core elements:
| Element | What it renders | Use case |
|---|---|---|
| TextBlock | Formatted text (heading, body, caption) | Titles, descriptions, status messages |
| Image | An image from a URL | Product photos, weather icons, logos |
| ColumnSet / Column | Side-by-side layout | Two-column comparison, label-value pairs |
| FactSet | Key-value list | Order details, account summary |
| ActionSet | Buttons the user can click | Confirm, cancel, view details, open URL |
| Input.Text | Text input field | Collect feedback, search queries |
| Input.ChoiceSet | Dropdown or radio buttons | Select a category, choose an option |
| Container | Groups elements with optional style | Sections with backgrounds or borders |
In Copilot Studio, you send an Adaptive Card by placing the JSON in a Message node with the card attachment format, or by returning it from a flow and using the card display action in the topic.
Combining Generative Answers with Cards
A powerful pattern is to combine generative answers with Adaptive Cards:
- Generative answers handle the conversational response β explaining the data in natural language.
- Adaptive Card presents the structured data visually β a summary card, a comparison table, or an interactive form.
For example, when a user asks βWhat is the weather in Auckland?β, the agent could respond with a text message (βIt is 18 degrees and partly cloudy in Auckland, with moderate southwest windsβ) followed by an Adaptive Card showing the full forecast with icons. The text satisfies accessibility and screen readers; the card provides visual richness.
π Dev Calls the Weather API for Delivery Alerts
Dev wants his logistics agent to warn customers about weather-related delivery delays. Here is his implementation:
Step 1: Send HTTP Request β Devβs agent flow calls a weather API using the delivery city from the shipment record:
Method: GET
URI: https://api.weather.com/v1/forecast?city={DeliveryCity}&units=metric
Headers: X-API-Key: {stored in environment variable}
Step 2: Parse the response β Dev adds a Parse JSON action with a schema matching the API response structure. Now he has typed access to temperature, condition, wind.speed, and forecast[].
Step 3: Build the Adaptive Card β Dev constructs an Adaptive Card in a Compose action using TextBlock for the forecast heading, ColumnSet for the icon and temperature, and a FactSet for the multi-day outlook β all with parsed API values injected dynamically.
Step 4: Return to the topic β The flow returns success = true, a text summary, and the Adaptive Card JSON. The topic shows both: natural language and the visual card.
The gotcha Dev hit: His first attempt tried to access body.condition directly from the HTTP response without ParseJSON(). The flow failed silently and returned an empty result. Adding the Parse JSON step fixed it immediately.
Key Terms
Knowledge Check
Dev's flow calls a weather API using Send HTTP Request and then tries to use body.temperature in the next action. The flow fails. What is the problem?
Priya at AgentForge needs to call the same CRM API from five different agent flows. The API has a full OpenAPI spec and uses OAuth2. What should she use?
Which Adaptive Card element should Dev use to display a list of shipment details as label-value pairs (Tracking Number: ABC123, Status: In Transit, ETA: Tomorrow)?
π¬ Video coming soon
API Calls, HTTP Requests and Adaptive Cards