Integrating football-data.org with Microsoft Copilot Studio Using a REST API Tool
Introduction
One of the most important transitions when learning Microsoft Copilot Studio is moving from an Agent that only answers questions to an Agent that can interact with external systems.
Until this point, many of our experiments have focused on concepts such as:
Instructions → Knowledge → Retrieval → Grounding → Answer
Those concepts primarily concern how an Agent obtains and uses information.
A REST API integration introduces a different architectural capability:
Tools and Actions.
Instead of retrieving information from a Knowledge Source and grounding a generated answer in that content, the Agent can invoke an external service at runtime, receive structured data, and use that data to answer the user.
In this laboratory, we use football-data.org as the external service and Microsoft Copilot Studio as the Agent platform.
Our initial architecture is intentionally small:
User ↓Copilot Studio Agent ↓Generative Orchestration ↓REST API Tool ↓football-data.org REST API ↓JSON Response ↓REST API Tool ↓Agent ↓User Response
The first capability exposed to the Agent is also deliberately narrow:
Retrieve the current standings for a football competition.
This follows an important principle for learning Agent architecture: build atomic capabilities first.
Rather than importing an entire football API containing competitions, teams, players, matches, scorers, standings, seasons, and many other endpoints, we begin with one API operation and understand the entire execution pipeline before expanding it.
Microsoft currently documents the REST API Tool capability as a preview feature in Copilot Studio, so its UI, limitations, and behavior can change. Microsoft explicitly states that preview functionality isn’t intended for production use. (Microsoft Learn)
Microsoft Learn — Extend your agent with tools from a REST API (preview)
1. The Architectural Change: From Knowledge to Tools
Before discussing OpenAPI, authentication, or HTTP, it is important to understand what has changed architecturally.
Consider a traditional Knowledge-based Agent.
A user asks:
"What is our corporate vacation policy?"
A simplified architecture might be:
User Question ↓Agent ↓Instructions ↓Retrieval ↓Knowledge Source ↓Relevant Content ↓Grounding ↓Generative Model ↓Answer
Now consider:
"Show me the current Premier League standings."
This is fundamentally different.
The standings are dynamic operational data. We do not want the Agent to answer from general model knowledge or from a static document uploaded three months ago.
Instead:
User Question ↓Agent ↓Intent Interpretation ↓Generative Orchestration ↓Select Tool ↓Execute REST operation ↓External System ↓Current structured data ↓Agent ↓Answer
This gives us one of the most important distinctions in our entire Copilot Studio project:
| Component | Fundamental question |
|---|---|
| Instructions | How should the Agent behave? |
| Knowledge | What information can the Agent retrieve? |
| Retrieval | What information is relevant? |
| Grounding | What retrieved evidence supports the answer? |
| Tool | What capability can the Agent invoke? |
| Action | What operation can the Agent perform? |
| Authentication | Is the caller authorized to access the external system? |
| Orchestration | Which capability should be used now? |
| API | Which external functionality or data is available? |
Therefore:
Knowledge ≠ Tool
and:
Retrieving Knowledge ≠ Calling an API
Both can provide information to an Agent, but the mechanisms and security models are different.
2. Why Use a REST API Tool?
We could integrate football-data.org using several architectures.
For example:
Agent ↓Power Automate ↓HTTP ↓football-data.org
Or potentially:
Agent ↓Custom Connector ↓football-data.org
Or:
Agent ↓Custom middleware ↓football-data.org
But this laboratory specifically explores:
Agent ↓REST API Tool ↓football-data.org
That is valuable because it exposes the fundamental REST integration concepts directly:
OpenAPI+Authentication+Operations+Parameters+HTTP+JSON
without initially introducing Power Automate, Azure Functions, Graph, or custom middleware.
Microsoft describes REST API Tools around three primary pieces of information:
- An OpenAPI specification describing available API functions/actions.
- The authentication requirements for accessing the external system.
- Descriptions that help the language model determine when the API should be invoked. (Microsoft Learn)
That third requirement deserves particular attention.
In conventional programming, descriptions are usually documentation.
In an Agent architecture, descriptions can participate in tool selection.
That changes how we should write OpenAPI descriptions.
3. Our OpenAPI Specification
For this laboratory we created a deliberately minimal OpenAPI document.
The uploaded file declares:
{ "swagger": "2.0", "info": { "title": "Football Data API", "description": "Retrieve football competition standings from football-data.org.", "version": "1.0" }}
The document is explicitly Swagger/OpenAPI 2.0.
This is relevant because Microsoft’s current Copilot Studio documentation states that REST API Tools are created from an OpenAPI v2 specification. If a v3 specification is supplied, the creation process can translate it to v2 because of the underlying Power Platform processing requirements. (Microsoft Learn)
Our file therefore avoids that translation step.
4. API Endpoint Architecture
The specification defines:
host: api.football-data.orgbasePath: /v4scheme: https
These components combine conceptually into:
https +api.football-data.org +/v4
producing the API base address:
https://api.football-data.org/v4
The API operation currently exposed in our specification is:
GET /competitions/{code}/standings
The specification gives it the operation identifier:
GetCompetitionStandings
and describes it as:
Get competition standings
Therefore, the complete conceptual request becomes:
GEThttps://api.football-data.org/v4/competitions/{code}/standings
where {code} must be replaced by a competition identifier.
5. Understanding operationId
The operationId deserves special attention because it is much more than cosmetic metadata.
Our specification contains:
operationId: GetCompetitionStandings
Conceptually:
OpenAPI │ └── Path /competitions/{code}/standings │ └── GET │ └── operationId GetCompetitionStandings
In API-plugin architectures, the operation identifier provides a stable logical identifier for the operation; Microsoft documentation for API plugins also describes function-to-operationId mapping. (Microsoft Learn)
This gives us an important API design rule:
operationIdshould be meaningful, unique within the specification, stable, and descriptive of the operation.
Good:
GetCompetitionStandingsGetTeamMatchesGetCompetitionScorersGetMatchDetails
Poor:
Get1ActionRequestOperationA
As our football Agent grows, good operation naming will become increasingly important.
6. The code Path Parameter
Our endpoint is:
/competitions/{code}/standings
The OpenAPI specification defines code as:
name: codein: pathrequired: truetype: string
This tells the API consumer several things.
First, code is not a query parameter.
We are not constructing:
/competitions/standings?code=PL
Instead, the value becomes part of the URI:
/competitions/PL/standings
Second, it is required.
The operation cannot logically execute without a competition code.
Our specification currently documents examples including:
| Code | Competition |
|---|---|
PL | Premier League |
PD | Primera Division |
BL1 | Bundesliga |
SA | Serie A |
FL1 | Ligue 1 |
CL | UEFA Champions League |
These mappings are explicitly described in our uploaded specification.
This leads to one of the most interesting Agent behaviors in the entire experiment.
The user should not need to say:
GetCompetitionStandings(code="PL")
The user says:
Show me the Premier League standings.
The Agent needs to move from human semantics to structured API semantics:
"Premier League" ↓Intent interpretation ↓Competition identification ↓PL ↓Tool parametercode = PL
This is one reason why Agent + Tool architectures are powerful.
The LLM becomes an interpretation layer between natural language and deterministic APIs.
7. The Full Semantic-to-HTTP Translation
We can now model the process more precisely.
The user says:
"What are the current Premier League standings?"
The Agent interprets:
Intent:retrieve standingsEntity:Premier LeagueRequired capability:competition standingsRequired parameter:competition code
The Agent/tool configuration maps:
Premier League → PL
The Tool executes:
GET /v4/competitions/PL/standings
The external system returns structured JSON.
The Agent can then transform that structured result into a user-friendly answer.
Conceptually:
Natural Language ↓Semantic Interpretation ↓Tool Selection ↓Parameter Resolution ↓HTTP Request ↓External Processing ↓JSON ↓Result Interpretation ↓Natural Language
This is a useful general model for Agent-to-API integration.
8. Step 1 — Upload Specification
The first screen shown in our experiment is:
Add tool → Upload specification
The file uploaded is:
football-data-openapi.json
Copilot Studio successfully parsed the file and displayed its content.
That confirms several things.
The document is readable by the platform.
Its root OpenAPI/Swagger structure was recognized.
The wizard was able to proceed from:
Upload specification
to:
API plugin details
The current Microsoft procedure follows essentially this lifecycle:
Add Tool ↓New Tool ↓REST API ↓Upload OpenAPI ↓API Details ↓Authentication ↓Select Tools ↓Configure Tools ↓Review ↓Publish
This corresponds closely to what we observed in the actual Copilot Studio interface.
9. Step 2 — API Plugin Details
The second important screen is:
API plugin details
Our current configuration uses:
Tool name
Football Data API
and:
Description
Retrieve football competition standings from football-data.org.
This description is consistent with the description in our OpenAPI file.
But we should understand something important:
This description is part of the Agent architecture.
Microsoft explicitly says descriptions help the language model determine when the API should be invoked. (Microsoft Learn)
In conventional software:
Description → primarily developer documentation
In generative orchestration:
Description ↓Semantic understanding ↓Capability discovery ↓Potential tool selection
Therefore, vague descriptions are undesirable.
10. Improving the API Description
Our current description is valid but minimal:
Retrieve football competition standings from football-data.org.
A richer version could be:
Retrieves current football competition standings from football-data.org. Use this API when users ask for league tables, competition standings, rankings, positions, points, wins, draws, losses, goals, goal differences, or team positions in supported football competitions such as the Premier League, La Liga, Bundesliga, Serie A, Ligue 1, and UEFA Champions League.
This creates a much richer semantic vocabulary.
The orchestration layer can associate concepts such as:
standingsleague tablerankingpositionpointswinslossesdrawsPremier LeagueBundesligaSerie A
with the capability.
For example, these user prompts are semantically different:
Show the Premier League standings.
Who is first in the Premier League?
How many points does Arsenal have?
What is the current English league table?
Where is Liverpool in the league?
Yet they may all require the same underlying API operation.
Good Tool metadata helps bridge that semantic gap.
11. API-Level Description vs Operation-Level Description
As our API grows, we should distinguish two description levels.
The API description answers:
What general capability does this API provide?
For example:
Provides football competition, team, match,standing, fixture, result, and scorer data.
An operation description answers:
When should this specific operation be called?
For example:
GetCompetitionStandings
could have:
Retrieves the current league table for a specific competition, including team position, points, wins, draws, losses, goals, and other standings data.
This produces a hierarchy:
Football Data API│├── GetCompetitionStandings│├── GetCompetitionMatches│├── GetCompetitionScorers│├── GetTeamMatches│└── GetMatchDetails
Later, orchestration may need to distinguish between:
"When does Arsenal play next?"
and:
"Where is Arsenal in the Premier League?"
The first should eventually invoke a matches/fixtures operation.
The second should invoke standings.
This is why API descriptions and operation descriptions become increasingly important as the number of Tools grows.
12. Solution and ALM
The API plugin details screen also contains:
Solution
with the message that a Solution can be selected or one can be automatically created.
Microsoft’s current documentation confirms that a Solution can be selected and that, if none is selected, one can be created automatically. Microsoft also notes that storing the action in a Solution facilitates moving it between environments. (Microsoft Learn)
This connects our small experiment to Power Platform ALM.
For an experiment:
Automatic Solution
may be sufficient.
For an enterprise project, we would generally want deliberate lifecycle management:
Development ↓Custom Solution ↓Source Control / Pipeline ↓Test Environment ↓Validation ↓Production Environment
Eventually our Agent could have:
Football Agent Solution│├── Agent├── REST API Tools├── Connections├── Environment configuration├── Flows└── Other Power Platform components
We do not need to implement all of this now, but recognizing the ALM boundary early prevents treating a Tool as an isolated object with no lifecycle.
13. Authentication Is a Separate Architectural Layer
After API plugin details, the next stage visible in the wizard is:
Authentication
This is a critical transition.
So far we have answered:
WHAT endpoint exists?WHAT operation can be called?WHAT parameters does it require?
Authentication answers:
WHO or WHAT is allowed to call it?
These are separate concerns.
OpenAPI ↓API contractAuthentication ↓Access control / credentials
An API might expose:
GET /competitions/PL/standings
but that does not imply that every caller may execute it.
14. Authentication Options in Copilot Studio
Microsoft’s current REST API Tool documentation lists three authentication choices in this wizard:
NoneAPI keyAuth 2.0
They represent very different security models.
| Authentication | Basic concept |
|---|---|
| None | Endpoint can be accessed without credentials |
| API key | Shared secret/token identifies or authorizes API access |
| OAuth 2.0 | Token-based delegated authorization through an identity provider |
For our football-data.org laboratory, the relevant model is an API key.
This is pedagogically useful because we can study authenticated REST requests without immediately introducing:
Microsoft Entra IDApp RegistrationClient IDClient SecretAuthorization CodeScopesAccess TokensRefresh TokensConsent
Those will come later when they are actually required.
15. Understanding API Key Authentication
An API key is conceptually a secret value associated with access to an API.
The HTTP request becomes something like:
HTTP Request+API credential
rather than merely:
HTTP Request
Microsoft’s broader API-plugin documentation describes three common ways an API plugin can send an API key:
Authorization headerCustom headerQuery parameter
The precise mechanism must match the API contract.
That means we must never randomly choose:
Header
or:
Query
because one “looks better.”
The external API defines the authentication protocol.
16. Secrets Must Not Become Agent Instructions
This is an extremely important security rule.
Never design an Agent like this:
Instructions:When calling football-data.org,use API key abc123456789...
That mixes two completely different architectural layers.
Instructions ↓Agent behavioral policy
versus:
Credentials ↓Authentication subsystem
A better mental model is:
User ↓Agent ↓Tool Invocation ↓Authentication Layer ↓Credential Injection ↓HTTP Request ↓External API
The language model does not need the secret merely to reason about which Tool to use.
The credential belongs to the authentication mechanism.
This principle becomes far more important when we later integrate enterprise APIs.
17. Authentication Configuration in the Wizard
Microsoft currently documents the following fields when API key is selected:
Parameter label
A human-readable label shown to the user.
Parameter name
The actual API parameter/header name expected by the external service.
Parameter location
Where the credential is sent:
Header
or:
Query
This creates a mapping such as:
Copilot Studio │ ├── Parameter label │ ├── Parameter name │ └── Parameter location ↓ HTTP Request
We should configure those values according to football-data.org’s authentication contract rather than guessing them.
That will be the next controlled configuration step in our laboratory.
18. A Security Detail: Runtime Authentication
There is an important nuance in Microsoft’s current Copilot Studio documentation.
For the API key option in the REST API Tool wizard, Microsoft states that when the Agent wants to use the API Tool at runtime, the user is prompted to authenticate and provides an API key for the Agent to connect to the API. (Microsoft Learn)
That means we must distinguish between:
Agent Maker
Agent User
Connection
API Credential
and:
External API Identity
These identities are not automatically the same.
This becomes extremely important when comparing this architecture later with Microsoft Graph and Microsoft Entra delegated authorization.
19. API Keys vs Microsoft Entra Delegated Authentication
Imagine two architectures.
API-key model
User ↓Agent ↓Tool ↓API Key ↓External API
The external system primarily understands the API credential.
Now compare that with a future Microsoft Graph architecture:
Microsoft 365 User ↓Agent ↓Tool ↓OAuth / Entra ID ↓Delegated Access Token ↓Microsoft Graph ↓User-authorized resources
These have very different security implications.
With delegated access, the identity and permissions of the signed-in user can participate directly in authorization.
With an API key, the authorization boundary is typically associated with the key itself.
Therefore:
API authentication
does not automatically mean:
Microsoft 365 user authorization
This distinction will matter enormously when we move from football data to SharePoint, Graph, HR, Finance, or enterprise APIs.
20. Select Tools
After authentication, the wizard proceeds to:
Select Tools
This stage is where the OpenAPI specification becomes operational Agent capabilities.
Our specification currently contains only one combination:
Path:/competitions/{code}/standingsMethod:GEToperationId:GetCompetitionStandings
Microsoft explains that REST API Tools are derived from API operations represented by combinations of endpoints and HTTP methods. (Microsoft Learn)
Conceptually:
OpenAPI ↓Paths ↓HTTP Methods ↓Operations ↓Selectable Tools
Because our OpenAPI is atomic, we expect only one relevant operation.
That is intentional.
21. Why We Should Not Import Everything Yet
Imagine importing thirty football operations immediately.
The Agent might suddenly have:
GetCompetitionsGetCompetitionGetCompetitionStandingsGetCompetitionMatchesGetCompetitionTeamsGetCompetitionScorersGetTeamGetTeamMatchesGetTeamCompetitionsGetMatchGetMatchHeadToHead...
Then if something fails, several variables exist:
Did orchestration select the wrong Tool?Did entity extraction fail?Was the wrong parameter generated?Did authentication fail?Was the endpoint incorrect?Did the API reject the request?Was the returned schema misunderstood?
Our current experiment removes most of those variables.
We have:
ONE API ↓ONE endpoint ↓ONE HTTP method ↓ONE operation ↓ONE parameter
This is exactly the kind of controlled environment we want when learning Agent orchestration.
22. Configure Tool
After selecting an operation, Copilot Studio allows us to configure the Tool.
This includes:
Tool nameTool description
Microsoft specifically notes that Tool descriptions should provide enough information for the language model to determine whether a user query aligns with the Tool. (Microsoft Learn)
For our operation, I would use:
Tool name
Get Competition Standings
Tool description
Retrieves the current standings or league table for a supported football competition. Use this tool when the user asks about league rankings, competition standings, team positions, points, wins, draws, losses, goals, goal difference, or the current table.
Notice the separation:
API:Football Data APITool:Get Competition Standings
Later:
Football Data API│├── Get Competition Standings├── Get Competition Matches├── Get Competition Scorers└── Get Team Matches
The API represents the broader external capability.
Each Tool represents a narrower executable capability.
23. Tool Selection Is a Semantic Problem
Traditional application code might explicitly say:
if command == "standings" call GetCompetitionStandings()
Generative orchestration can work differently.
The user might say:
Who's leading the Premier League?
The word:
standings
never appears.
Yet the Agent needs to infer:
Question concerns ranking ↓Ranking is represented by standings ↓GetCompetitionStandings is relevant ↓Call Tool
Another user might ask:
How far behind the leader is Arsenal?
Again, the exact Tool name does not appear.
The Agent must reason from semantic intent.
This explains why Tool descriptions are not trivial documentation.
They help define the semantic boundary of a capability.
24. Parameter Selection
Our Tool has one parameter:
code
The OpenAPI currently describes it as:
Competition code, for example PL, PD, BL1, SA, FL1, or CL.
This is already useful.
But we could make it even more explicit:
Football competition code. Use
PLfor Premier League,PDfor Primera Division/La Liga,BL1for Bundesliga,SAfor Serie A,FL1for Ligue 1, andCLfor UEFA Champions League.
This provides a direct semantic mapping:
Natural language ↓Canonical API value
For example:
"English Premier League" ↓PL
"Bundesliga" ↓BL1
"Champions League" ↓CL
This is essentially entity normalization.
25. Entity Resolution
This introduces another useful Agent concept:
Entity Resolution.
The user thinks in business-domain concepts:
Premier LeagueChampions LeagueSerie A
The API thinks in identifiers:
PLCLSA
Therefore:
Human Entity ↓Agent Interpretation ↓Canonical Identifier ↓API Parameter
The same pattern appears constantly in enterprise systems.
For SharePoint:
"HR Policies" ↓Site ID
For Dataverse:
"Contoso" ↓Account GUID
For Graph:
"John Smith" ↓User ID
For a custom ERP:
"Customer ACME" ↓CustomerNumber 18472
Our football Agent therefore gives us a safe environment for learning a pattern that will later become extremely important in enterprise Agent design.
26. The HTTP Request
Once Tool selection and parameter resolution succeed, we eventually arrive at deterministic HTTP.
For Premier League:
GET https://api.football-data.org/v4/competitions/PL/standings
The request also needs whatever authentication football-data.org requires.
At this point, the generative part has largely done its job:
Interpret request ↓Choose Tool ↓Resolve parameters
Then conventional software engineering takes over:
HTTP ↓Authentication ↓Endpoint ↓Status Code ↓JSON
This boundary is worth remembering.
Agents do not replace APIs.
They provide an intelligent orchestration and interpretation layer around deterministic systems.
27. The API Response
A successful request returns structured data.
Conceptually:
HTTP 200+JSON
The Tool receives that structured result and makes it available to the Agent.
Then the Agent can transform:
Structured Machine Data
into:
Human-Friendly Explanation
For example:
JSON ↓teamspositionspointswinsdrawslosses ↓Agent ↓formatted standings
Eventually, because our Football Agent is intended to use Adaptive Cards, we can introduce another transformation:
REST API ↓JSON ↓Agent ↓Adaptive Card model ↓Rendered UI
But that is a separate layer and should not be confused with the API integration itself.
28. HTTP Status Codes
Our current OpenAPI specification documents several possible responses.
It defines:
200Competition standings returned successfully400Invalid request403Authentication or subscription restriction404Competition not found429API request limit exceeded
These status codes are extremely useful for testing.
They give us multiple controlled failure scenarios.
HTTP 200
Tool ↓Request ↓API ↓200 ↓JSON ↓Agent
Normal successful execution.
HTTP 400
The request itself is invalid.
Potential causes include invalid parameter structures or unsupported combinations.
HTTP 403
The server understood the request but access is not permitted according to authentication/subscription rules.
This is especially useful for testing our authentication layer.
HTTP 404
The requested competition/resource cannot be found.
The Agent should not transform this into an invented answer.
HTTP 429
The service is rate-limiting requests.
This is operationally important.
An Agent should distinguish:
"I don't know the standings"
from:
"The external service temporarily rejected the request because its request limit was reached."
These represent very different failure modes.
29. Hallucination Boundaries
This API experiment introduces an important reliability principle.
Suppose the user asks:
"Show me today's Premier League standings."
The Agent calls the Tool.
The API fails with:
429 Too Many Requests
The Agent should not decide:
“I probably know roughly what the standings look like, so I will answer anyway.”
For this type of Agent, we want a strong distinction between:
Current football data
and:
General model knowledge
The API is the authoritative runtime source for dynamic football information.
Therefore:
API unavailable ↓Do not fabricate current data ↓Explain inability to retrieve current data
This is conceptually similar to the grounding experiment we previously performed with Knowledge Sources, but the trust boundary is different.
30. Static Knowledge vs Dynamic Operational Data
This gives us a useful architecture table.
| Information | Better mechanism |
|---|---|
| History of the Premier League | Knowledge |
| Explanation of offside | Knowledge / model |
| Club historical documentation | Knowledge |
| Current standings | REST API |
| Today’s matches | REST API |
| Latest score | REST API |
| Current scorers | REST API |
| Create a SharePoint request | Action |
| Update business data | Action/Tool |
| Corporate policy document | SharePoint Knowledge |
This illustrates an important architectural principle:
Do not use an LLM’s memory as a substitute for a transactional or operational system of record.
31. Generative vs Deterministic Responsibilities
The architecture now contains two different worlds.
Generative responsibility
The Agent is good at:
Understanding languageInterpreting intentResolving meaningSelecting capabilitiesMaintaining conversational contextExplaining resultsFormatting results
Deterministic responsibility
The API is good at:
Returning current dataEnforcing authenticationApplying API rulesReturning structured objectsReturning status codesMaintaining authoritative records
The best architecture combines both:
LLM"Understand what the human wants" +API"Provide authoritative structured data"
We should not make either side perform the other’s job unnecessarily.
32. Generative Orchestration
Now we can place Generative Orchestration more clearly in the architecture.
Suppose the Agent eventually has these Tools:
GetCompetitionStandingsGetCompetitionMatchesGetCompetitionScorersGetTeamMatchesGetMatchDetails
The user asks:
"When does Arsenal play next?"
The Agent must determine that:
GetCompetitionStandings
is probably not appropriate.
Instead, it should select something like:
GetTeamMatches
But if the user asks:
"Where is Arsenal in the league?"
then:
GetCompetitionStandings
may be appropriate.
Conceptually:
User Prompt ↓Context ↓Instructions ↓Generative Orchestration ↓Available Capabilities ┌──────┼─────────┐ ↓ ↓ ↓Knowledge Tool A Tool B ↓ Selected Tool ↓ Parameters ↓ Execution
This is significantly different from traditional hardcoded routing.
33. Tool Descriptions Become Part of Orchestration Design
Suppose two Tools are described poorly:
Tool A:Gets data.Tool B:Gets football information.
The model has little semantic information to distinguish them.
Compare:
GetCompetitionStandingsRetrieves the current league table for a competition,including ranking, points, wins, draws, losses,goals, and team positions.
and:
GetTeamMatchesRetrieves scheduled, completed, or recent matchesfor a specific football team. Use this tool forfixtures, previous results, next matches, and match history.
Now the semantic boundary is much clearer.
Therefore, when designing Agent Tools, API documentation becomes part of AI orchestration engineering.
That is a subtle but important shift from conventional API development.
34. Connections After Publishing
Microsoft’s current documented process does not stop when the Tool definition itself is published.
After publishing, the workflow includes creating or selecting a connection for the REST API Tool and then adding the configured Tool to the Agent. (Microsoft Learn)
Conceptually:
Define REST API ↓Define Authentication ↓Select Operations ↓Configure Tools ↓Publish Tool Definition ↓Create / Select Connection ↓Add Tool to Agent ↓Runtime Usage
This distinction is important:
Tool definition
and:
Runtime connection
are related but not conceptually identical.
The Tool defines what can be done.
The connection provides the runtime integration context required to actually do it.
35. Authentication Configuration vs Connection
It is useful to think of three layers.
Layer 1 — API Contract
OpenAPI
Defines:
EndpointsMethodsParametersOperationsResponses
Layer 2 — Authentication Model
Defines:
How the external system protects the API
For example:
API key
Layer 3 — Runtime Connection
Represents the usable connection between Copilot Studio and the external service.
Conceptually:
OpenAPI ↓"What can I call?"Authentication ↓"How is access proven?"Connection ↓"Which runtime integration can execute it?"
Keeping these concepts separate makes troubleshooting much easier.
36. Troubleshooting the Complete Chain
When a Tool fails, we should not immediately change everything.
Instead, isolate the layer.
User Prompt ↓Did the Agent understand intent? ↓Did orchestration choose the Tool? ↓Was the correct Tool selected? ↓Was `code` resolved correctly? ↓Did authentication succeed? ↓Was the HTTP request valid? ↓What status code returned? ↓Was JSON returned? ↓Did the Agent interpret it correctly?
For example:
Problem A
The Tool never runs.
Investigate:
InstructionsTool descriptionOrchestration
Problem B
The Tool runs with:
code = "Premier League"
instead of:
code = "PL"
Investigate:
Parameter descriptionEntity resolutionInstructions
Problem C
The Tool calls the API but receives:
403
Investigate:
AuthenticationCredentialSubscription/API permissions
Problem D
The API returns correct JSON but the Agent displays the standings incorrectly.
Investigate:
Response interpretationFormattingAdaptive Card
These are four completely different problems.
37. Observability Matters
As Agents become more capable, we need to know what happened internally at the architectural level without pretending we can inspect hidden model reasoning.
Useful observable information includes:
User requestTool selectedParameters suppliedHTTP resultTool resultFinal Agent response
Conceptually:
User ↓Prompt ↓Agent ↓
[observable tool invocation]
↓ Tool ↓
[observable result]
↓ Agent ↓ Response
That is enough to troubleshoot many integration problems.
We do not need access to private chain-of-thought to determine whether the wrong Tool or wrong parameter was used.
38. Rate Limits Become an Agent Concern
The presence of HTTP 429 in our specification introduces another enterprise architecture consideration.
Imagine one user asks:
Show Premier League standings.
One API call is trivial.
Now imagine:
5,000 users×multiple conversations×multiple Tool calls
Tool invocation becomes consumption of an external dependency.
Therefore, an Agent architect eventually needs to consider:
API quotasRate limitsLatencyRetriesCachingTimeoutsFailure behaviorCostConcurrency
This is one reason why “the Agent can call an API” is only the beginning of production architecture.
39. Least Privilege Still Applies
Our football API is a low-risk educational scenario, but the principle generalizes.
Imagine a future Agent API that exposes:
GET employeePOST employeePUT employeeDELETE employee
Just because the OpenAPI specification contains all four operations does not mean the Agent should receive all four Tools.
Microsoft’s current REST API Tool documentation explicitly describes selecting only the operations you want users to be able to execute. (Microsoft Learn)
Therefore:
API capability ≠Agent-required capability
If the Agent only needs:
GET
do not automatically expose:
POSTPUTDELETE
This is application of the principle of least privilege at the capability level.
40. Read-Only Tools Are Excellent First Tools
Our first operation is:
GET
That is ideal.
It retrieves information without modifying the external system.
This gives us a natural learning progression:
Read-only REST API ↓Multiple read operations ↓Parameter handling ↓Response processing ↓Authentication ↓Error handling ↓Write operations
Later, when we introduce:
POSTPUTPATCHDELETE
the risk model changes.
A hallucinated explanation is one thing.
A hallucinated destructive action is something else entirely.
41. Why Power Automate Is Not Required Here
Because Copilot Studio can expose the REST API directly as a Tool, we do not need Power Automate simply to make this HTTP request.
Our architecture can remain:
Agent ↓REST API Tool ↓football-data.org
That does not mean Power Automate is obsolete.
Power Automate becomes useful when we need deterministic orchestration such as:
Agent ↓Flow ├── Call API ├── Transform data ├── Update SharePoint ├── Start approval ├── Send Teams notification └── Return result
A useful architectural rule is:
Do not introduce an extra orchestration layer unless it provides value.
If the requirement is:
Call one REST endpoint and return its result
a direct REST Tool may be simpler.
If the requirement becomes:
Call API→ process data→ write SharePoint→ approval→ notification→ return structured result
Power Automate may become much more appropriate.
42. Why Microsoft Graph Is Not Needed
Another important architectural lesson from this experiment is what we are not using.
We do not need Microsoft Graph.
Graph is irrelevant to the current requirement.
football-data.org is an external REST service.
Introducing:
Entra App RegistrationGraph permissionsDelegated scopesApplication permissions
would add complexity without solving a problem we currently have.
This follows an important architecture principle:
Use the simplest integration mechanism that correctly satisfies the requirement.
43. Future Expansion of the OpenAPI Specification
Once the first Tool works correctly, the specification can evolve.
Conceptually:
Football Data API│├── Competitions│ ├── GetCompetition│ ├── GetCompetitionStandings│ ├── GetCompetitionMatches│ └── GetCompetitionScorers│├── Teams│ ├── GetTeam│ └── GetTeamMatches│└── Matches ├── GetMatch └── GetHeadToHead
At that point, the laboratory becomes much more interesting because Generative Orchestration must choose between multiple capabilities.
For example:
"Show me the Premier League table" ↓GetCompetitionStandings
"Who are the Premier League top scorers?" ↓GetCompetitionScorers
"When does Arsenal play next?" ↓GetTeamMatches
"What happened in Arsenal's last match?" ↓GetTeamMatches / GetMatch
Then we will be testing true Tool selection rather than merely Tool execution.
44. OpenAPI Becomes an Agent Contract
In conventional API development, OpenAPI is frequently thought of as documentation.
In this architecture, it becomes more significant.
It defines a machine-readable boundary between:
Generative Agent
and:
Deterministic External System
It describes:
Available operationsHTTP methodsPathsParametersDescriptionsResponsesAuthentication-related structure
Therefore:
Natural Language ↓Agent ↓Semantic Tool Selection ↓OpenAPI Contract ↓HTTP ↓External System
This makes OpenAPI one of the most important technologies for connecting Agents to existing enterprise APIs.
45. The Agent Is an Orchestrator, Not the System of Record
Another architectural principle emerges from this experiment.
The Agent does not become the football database.
football-data.org remains the external data provider.
The Agent becomes an intelligent interface/orchestration layer.
football-data.org ↓Authoritative operational dataCopilot Studio ↓Interpretation and orchestrationLLM ↓Natural-language interaction
The Agent should not replace authoritative systems.
It should make those systems easier to interact with.
The same principle will later apply to:
SharePointDataverseDynamics 365Microsoft GraphERP systemsCRM systemsCustom APIsSQL-backed applications
46. Our Current Complete Architecture
We can now describe the laboratory more precisely.
USER
│
│ Natural Language
▼
┌─────────────────────┐
│ Copilot Studio Agent│
└─────────────────────┘
│
│ Instructions
│ Context
▼
┌─────────────────────┐
│ Generative │
│ Orchestration │
└─────────────────────┘
│
│ Select capability
▼
┌─────────────────────┐
│ REST API Tool │
│ │
│ GetCompetition- │
│ Standings │
└─────────────────────┘
│
│ code = PL
▼
┌─────────────────────┐
│ Authentication │
│ API Credential │
└─────────────────────┘
│
│ HTTPS
▼
┌─────────────────────────────────┐
│ api.football-data.org/v4 │
│ │
│ /competitions/PL/standings │
└─────────────────────────────────┘
│
│ JSON
▼
┌─────────────────────┐
│ REST API Tool │
└─────────────────────┘
│
│ Structured result
▼
┌─────────────────────┐
│ Agent │
│ Response generation │
└─────────────────────┘
│
▼
USER
This is our first important direct Agent → authenticated REST API architecture.
47. Knowledge and REST Tools Can Eventually Work Together
Later, we could combine both worlds.
Suppose the Agent has football-history Knowledge plus current football API data.
A user asks:
"Compare Arsenal's current league position with its historical performance."
Potential architecture:
User
↓
Agent
↓
Orchestration
↙ ↘
↓ ↓
Knowledge REST Tool
↓ ↓
Retrieval Current API
↓ ↓
Grounding JSON
↘ ↙
Context
↓
Generated Answer
Now:
Knowledge
provides historical/contextual information.
While:
REST API Tool
provides current operational data.
That combination is much closer to sophisticated enterprise Agent architectures.
48. Knowledge + Tool + Action
Eventually, we can extend the architecture further:
Knowledge ↓"What information is relevant?"Tool ↓"What external information can I retrieve?"Action ↓"What operation can I perform?"
For a future SharePoint scenario:
User:"Can I request this type of equipment?" ↓Agent ↓SharePoint Knowledge ↓Retrieve equipment policy ↓Ground policy answer ↓User:"Yes, create the request." ↓Agent ↓Tool / Action ↓Power Automate ↓Create SharePoint item
Our football API laboratory is teaching the middle layer of that architecture.
49. Security Model Summary
Even this simple laboratory should make us ask the correct security questions:
| Question | Why it matters |
|---|---|
| What system is being called? | Defines external trust boundary |
| What endpoint is exposed? | Defines capability |
| Is it read or write? | Defines operational risk |
| How is authentication performed? | Defines identity/credential mechanism |
| Where is the secret handled? | Defines credential exposure risk |
| Who establishes the connection? | Defines runtime context |
| What operations are exposed to the Agent? | Defines Agent privilege |
| What data is returned? | Defines data exposure |
| Can the API rate-limit calls? | Defines operational behavior |
| What happens when the API fails? | Defines reliability behavior |
Security therefore begins at:
Add Tool
not after the Agent is finished.
50. The Most Important Technical Lesson
The deeper lesson from this laboratory is not simply:
“Copilot Studio can call football-data.org.”
The important lesson is the architectural pipeline:
Natural Language ↓Intent ↓Generative Orchestration ↓Capability Selection ↓Tool ↓Parameter Resolution ↓Authentication ↓OpenAPI Contract ↓HTTP Request ↓External API ↓Structured JSON ↓Agent Interpretation ↓Generated Response
Each component has a separate responsibility.
That separation becomes essential when troubleshooting and designing production Agents.
51. Current State of Our Laboratory
Based on the OpenAPI specification and the Copilot Studio screens, we have reached approximately this point:
REST API selected ✓OpenAPI specification created ✓OpenAPI 2.0 ✓Specification uploaded ✓API parsed by Copilot Studio ✓Host configuredapi.football-data.org ✓Base path/v4 ✓HTTPS ✓Endpoint/competitions/{code}/standings ✓HTTP methodGET ✓operationIdGetCompetitionStandings ✓Path parametercode ✓API plugin detailsFootball Data API ✓Authentication ← NEXT CONTROLLED STEPSelect Tools ○Configure Tool ○Select Tool Parameters ○Review ○Publish ○Create Connection ○Add Tool to Agent ○Runtime Test ○
Our uploaded OpenAPI already provides the endpoint, operation identifier, path parameter, and documented response codes required for this initial atomic experiment.
52. What We Should Test Eventually
Once configuration is complete, we should not test only:
"Show me Premier League standings."
A proper Agent test set should eventually contain several semantic variations.
| Test | What it validates |
|---|---|
Show me the Premier League standings. | Basic Tool invocation |
Who's leading the Premier League? | Semantic Tool selection |
Where is Arsenal in the league? | Intent interpretation |
Show Bundesliga standings. | Parameter mapping |
Show Serie A standings. | Parameter mapping |
Show Champions League standings. | Parameter mapping |
| Invalid competition | Error handling |
| Missing credential | Authentication handling |
| API rate limit | HTTP 429 behavior |
| API unavailable | Failure handling |
| Ask unrelated question | Tool should not be unnecessarily invoked |
This is how we move from:
"It worked once"
to:
"We understand its behavior."
53. REST Tool vs Power Automate vs Custom Connector
This experiment also begins a comparison we will continue throughout the project.
| Approach | Good fit |
|---|---|
| REST API Tool | Direct Agent-to-REST integration |
| Power Automate | Deterministic multi-step business process |
| Custom Connector | Reusable Power Platform API abstraction |
| Azure Function | Custom server-side logic/code |
| Microsoft Graph | Microsoft 365 API access |
| MCP | Standardized Agent/tool integration architecture |
| Custom API | Full control over external business capability |
None of these is universally superior.
Architecture depends on the problem.
For our current requirement:
Agent ↓GET current football standings ↓External REST API
a REST API Tool is an excellent educational architecture.
54. Preview Status and Production Considerations
A final point is especially important because Copilot Studio is evolving quickly.
Microsoft’s current documentation explicitly marks this REST API Tool experience as preview and prerelease documentation. Microsoft states that preview features may have restricted functionality and are not intended for production use. (Microsoft Learn)
Therefore, this laboratory should currently be treated as:
LearningPrototypeArchitecture explorationTechnical validation
rather than automatically as:
Production architecture
For production use, we would need to reevaluate the feature’s current support status, limitations, security model, ALM behavior, connection model, monitoring, licensing, and governance at that time.
Conclusion
The football-data.org experiment represents an important milestone in our Copilot Studio learning path.
Previously, much of our architecture was:
User ↓Agent ↓Knowledge ↓Retrieval ↓Grounding ↓Answer
Now we are introducing:
User ↓Agent ↓Generative Orchestration ↓Tool ↓Authentication ↓REST API ↓External System ↓Structured Result ↓Agent ↓Answer
The uploaded OpenAPI specification provides a deliberately small contract: one HTTPS API, one GET endpoint, one operationId, and one required path parameter.
That simplicity is valuable because it allows us to understand each architectural boundary independently.
The key concepts introduced by this laboratory are:
OpenAPI = Contract
Description = Semantic guidance for orchestration
Tool = Executable Agent capability
Parameter = Structured input
Authentication = Access boundary
Connection = Runtime integration context
REST API = External capability
JSON = Structured result
Generative Orchestration = Capability selection
Agent = Conversational and orchestration layer
And perhaps the most important principle:
The LLM should understand the user’s intent; the API should remain responsible for authoritative operational data.
For our Football Agent, the Agent should understand that “Who’s leading the Premier League?” means it needs current standings. It should resolve the required competition, select GetCompetitionStandings, provide the appropriate code, invoke the external service, and explain the returned result.
It should not invent the current league table.
That separation between generative intelligence and deterministic external systems is one of the foundations of reliable enterprise Agent architecture.
Official Microsoft References
Microsoft Learn — Extend your agent with tools from a REST API (preview)
This is the primary reference for the exact Copilot Studio wizard we are using: OpenAPI upload, API details, authentication, Tool selection, publishing, connection creation, and adding the Tool to the Agent. (Microsoft Learn)
Microsoft Learn — Configure API key authentication
This explains API-key authentication for OpenAPI/API plugins, including authentication configuration and the ways API keys can be represented in API integration architectures. (Microsoft Learn)
Microsoft Learn — Configure authentication for MCP and API plugins
This provides the broader authentication model and distinguishes API plugins from MCP plugins. Microsoft’s current documentation lists API key support for API plugins, while MCP plugins use other supported authentication mechanisms. (Microsoft Learn)
One detail is worth keeping in our notes: Microsoft’s extensibility documentation is evolving quickly, and some generic API-plugin documentation currently lists limitations that do not map perfectly onto the newer Copilot Studio REST API Tool wizard. For this laboratory, I would therefore treat the current Copilot Studio REST API Tool documentation and the UI actually shown in your environment as authoritative for the wizard we’re configuring, and validate the football-data.org authentication behavior experimentally before generalizing it to production architecture. (Microsoft Learn)
