thomast1906/apim-policy-authoring
Creates production-ready Azure API Management policy XML for authentication (OAuth 2.0, JWT validation, subscription keys), rate limiting, CORS configuration, error handling, and API transformations. Use when implementing API security, access control, or request/response processing logic.
npx skills add https://github.com/thomast1906/github-copilot-agent-skills --skill apim-policy-authoring
Generates production-ready Azure API Management policy XML with authentication, rate limiting, CORS, error handling, correlation IDs, and security headers.
Activate this skill when users need:
See references/POLICY_TEMPLATES.md for complete production-ready XML templates:
INBOUND → BACKEND → OUTBOUND → ON-ERROR
1. INBOUND: Authentication, rate limiting, CORS, headers
2. BACKEND: Forwarding, retry, circuit breaker
3. OUTBOUND: Response transform, security headers, cleanup
4. ON-ERROR: Structured errors, logging, correlation ID
Before ANY policy generation, call:
Tool: mcp_azure_mcp_get_azure_bestpractices
Intent: "Azure API Management policy best practices for [authentication|rate-limiting|CORS|error-handling]"
For specific policy elements:
Tool: mcp_azure_mcp_documentation search
Query: "APIM validate-jwt policy reference"
<validate-jwt header-name="Authorization">
<openid-config url="https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration" />
<audiences>
<audience>api://{client-id}</audience>
</audiences>
</validate-jwt>
<set-variable name="userId" value="@(context.Request.Headers.GetValueOrDefault('Authorization','').AsJwt()?.Subject)" />
<rate-limit-by-key calls="1000" renewal-period="3600" counter-key="@((string)context.Variables['userId'])" />
<set-variable name="correlationId" value="@(Guid.NewGuid().ToString())" />
<set-header name="X-Correlation-ID" exists-action="override">
<value>@((string)context.Variables["correlationId"])</value>
</set-header>
<on-error>
<set-body>@{
return new JObject(
new JProperty("error", new JObject(
new JProperty("code", context.LastError.Source),
new JProperty("message", context.LastError.Message),
new JProperty("correlationId", context.Variables["correlationId"]),
new JProperty("timestamp", DateTime.UtcNow.ToString("o"))
))
).ToString();
}</set-body>
</on-error>
<set-header name="X-Content-Type-Options" exists-action="override">
<value>nosniff</value>
</set-header>
<set-header name="X-Frame-Options" exists-action="override">
<value>DENY</value>
</set-header>
<set-header name="Strict-Transport-Security" exists-action="override">
<value>max-age=31536000; includeSubDomains</value>
</set-header>
| API Type | Authentication | Rate Limit | Use Case |
|----------|----------------|------------|----------|
| Public Read-Only | Subscription Keys | 500 req/hour | Weather API, Public Holidays |
| Internal Corporate | OAuth (Entra ID) | 10,000 req/hour | Employee Directory, HR Systems |
| Sensitive Public | OAuth (Entra External ID) | 1,000 req/hour | Payment, Health Records |
| Hybrid | OAuth + Keys Fallback | 1,000/500 req/hour | APIs with free/premium tiers |
Before deploying, verify:
<inbound>, included in response + error<on-error> block with structured JSONX-Powered-By, Server in <outbound>Skill Version: 1.0
Last Updated: 29 January 2026
Primary Knowledge: APIM_PLATFORM_BASELINE_POLICIES.md, references/POLICY_TEMPLATES.md
Take thomast1906/apim-policy-authoring from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.