Add a new FastAPI endpoint to APIView Copilot. Use for: add endpoint, new endpoint, new API route, add route, create endpoint, add API, new POST endpoint, new GET endpoint.
npx skills add https://github.com/Azure/azure-sdk-tools --skill add-endpoint
When adding a new endpoint, follow every step below.
app.py for endpoint-specific models, or in src/_models.py for shared/reusable models.class Config with populate_by_name = True on any model that has aliases so it can be constructed with either the Python name or the alias.Field(...) for required fields, Field(None, ...) or Field(default=..., ...) for optional ones.class MyFeatureRequest(BaseModel):
"""Request model for my feature."""
review_id: str = Field(..., alias="reviewId")
language: str
include_deleted: bool = Field(False, alias="includeDeleted")
max_results: Optional[int] = Field(None, alias="maxResults")
class Config:
"""Configuration for Pydantic model."""
populate_by_name = True
class MyFeatureResponse(BaseModel):
"""Response model for my feature."""
job_id: str = Field(..., alias="jobId")
result_count: int = Field(..., alias="resultCount")
class Config:
"""Configuration for Pydantic model."""
populate_by_name = True
| Rule | Correct | Wrong |
|---|---|---|
| JSON field casing | "reviewId" | "review_id" |
| Alias declaration | Field(..., alias="reviewId") | bare review_id: str for multi-word names |
| Config on aliased models | class Config: populate_by_name = True | missing Config |
| Single-word fields | language: str (no alias needed) | language: str = Field(..., alias="language") |
@app.post(...) or @app.get(...) etc. with response_model= pointing to the response model.status_code= when it's not the default 200 (e.g., 202 for async jobs).Depends(require_roles(...)) for authentication. Use AppRole.READER / AppRole.APP_READER for read-only, AppRole.WRITER / AppRole.APP_WRITER for mutations.HTTPException with appropriate status codes.asyncio.to_thread(...) or background tasks.@app.post("/my-feature", response_model=MyFeatureResponse)
async def my_feature(
request: MyFeatureRequest,
_claims=Depends(require_roles(AppRole.READER, AppRole.APP_READER)),
):
"""Handle my feature requests."""
try:
result = await asyncio.to_thread(do_work, review_id=request.review_id)
return MyFeatureResponse(job_id=result.id, result_count=result.count)
except Exception as e:
logger.error("Error in /my-feature: %s", e, exc_info=True)
raise HTTPException(status_code=500, detail="Internal server error") from e
FastAPI automatically serializes response models by alias when response_model is set. This means:
jobId, resultCount), not the Python names.by_alias=True call is needed — FastAPI handles this via the response_model.MyFeatureResponse(job_id=..., result_count=...).Every endpoint must have a CLI command in cli.py with a --remote flag. The core logic must be shared between remote and local paths to the maximum extent practical.
Extract the business logic into a standalone function (in src/ or at module level in cli.py) that both the endpoint and the CLI's local path call. The CLI's --remote path sends an HTTP request to the endpoint instead.
┌─────────────┐
│ core logic │ ← shared function in src/
│ (do_work) │
└──────┬──────┘
│
┌────────────┴────────────┐
│ │
┌──────┴──────┐ ┌──────┴──────┐
│ app.py │ │ cli.py │
│ endpoint │ │ (local) │
└─────────────┘ └─────────────┘
│
if --remote:
HTTP POST → endpoint
def my_feature(language: str, review_id: str, include_deleted: bool = False, remote: bool = False):
"""Describe the command."""
if remote:
# Remote: HTTP call to the deployed endpoint
settings = SettingsManager()
base_url = settings.get("WEBAPP_ENDPOINT")
payload = {"language": language, "reviewId": review_id, "includeDeleted": include_deleted}
resp = requests.post(
f"{base_url}/my-feature", json=payload, headers=_build_auth_header(), timeout=60
)
if resp.status_code == 200:
print(json.dumps(resp.json(), indent=2))
else:
print(f"Error: {resp.status_code} - {resp.text}")
else:
# Local: call shared core logic directly
result = do_work(language=language, review_id=review_id, include_deleted=include_deleted)
print(json.dumps(result, indent=2))
Key rules:
--remote payload must use camelCase keys matching the endpoint's request model aliases._build_auth_header() for remote authentication.SettingsManager().get("WEBAPP_ENDPOINT") for the base URL.In CliCommandsLoader.load_command_table, add the command to the appropriate CommandGroup:
with CommandGroup(self, "review", "__main__#{}") as g:
# ... existing commands ...
g.command("my-feature", "my_feature")
Register any command-specific arguments in load_arguments:
with ArgumentsContext(self, "review my-feature") as ac:
ac.argument("review_id", options_list=["--review-id", "-r"], help="The review ID.")
ac.argument("include_deleted", action="store_true", help="Include deleted items.")
Notes:
--remote and --language are already registered globally — don't re-register them.review_id → --review-id).type=resolve_language_to_canonical for language params (already global).alias= on multi-word field names. The API contract is camelCase.model_config = ConfigDict(alias_generator=to_camel) — this project uses explicit alias= per field, not automatic generators.populate_by_name = True on models with aliases — without it, the model can't be constructed using Python field names.src/.--remote path must send camelCase keys matching the request model aliases.--remote or --language in command-specific ArgumentsContext — they are global.Guide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node/TypeScript (MCP SDK).
Automatically creates user-facing changelogs from git commits by analyzing commit history, categorizing changes, and transforming technical commits into clear, customer-friendly release notes. Turns hours of manual changelog writing into minutes of automated generation.
Use when implementation is complete, all tests pass, and you need to decide how to integrate the work - guides completion of development work by presenting structured options for merge, PR, or cleanup
Guide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node/TypeScript (MCP SDK).
React Native and Expo best practices for building performant mobile apps. Use when building React Native components, optimizing list performance, implementing animations, or working with native modules. Triggers on tasks involving React Native, Expo, mobile performance, or native platform APIs.
React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.
Next.js best practices - file conventions, RSC boundaries, data patterns, async APIs, metadata, error handling, route handlers, image/font optimization, bundling
Use when starting feature work that needs isolation from current workspace or before executing implementation plans - creates isolated git worktrees with smart directory selection and safety verification
Take azure/add-endpoint 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.