codeflash-internal/tiles/codeflash-internal-skills/skills/add-api-endpoint/SKILL.md

171 lines
5.3 KiB
Markdown
Raw Normal View History

---
name: add-api-endpoint
description: >
Guide for adding a new API endpoint to the codeflash-internal system.
Use when adding a new endpoint, creating a route, or implementing a new API.
Covers both aiservice (Django-Ninja) and cf-api (Express) endpoints
including schemas, routers, authentication, URL registration, and tests.
---
# Add API Endpoint
Use this workflow when adding a new endpoint to either the aiservice backend or the cf-api middleware. Follow the section that matches your target service.
## Part A: AIService Endpoint (Django-Ninja)
### Step 1: Define Schemas
Create request and response schemas.
1. Create or update schemas in the appropriate module (e.g., `core/shared/` for shared, `core/languages/python/` for Python-specific)
2. Use `ninja.Schema` for all request/response types:
```python
from ninja import Schema
class MyRequestSchema(Schema):
source_code: str
trace_id: str
language: str = "python"
class MyResponseSchema(Schema):
results: list[str]
class MyErrorResponseSchema(Schema):
message: str
```
3. Follow existing patterns in `core/shared/optimizer_models.py`
**Checkpoint**: Schemas should use Pydantic validation. Test with `MyRequestSchema.model_validate(data)`.
### Step 2: Create the Router
Create a NinjaAPI router for the endpoint.
1. Create a new module (e.g., `core/shared/my_feature.py` or `core/languages/python/my_feature/my_feature.py`)
2. Define the router and endpoint:
```python
from ninja import NinjaAPI
from authapp.auth import AuthenticatedRequest
my_feature_api = NinjaAPI(urls_namespace="my_feature")
@my_feature_api.post(
"/", response={200: MyResponseSchema, 400: MyErrorResponseSchema, 500: MyErrorResponseSchema}
)
async def my_endpoint(
request: AuthenticatedRequest, data: MyRequestSchema
) -> tuple[int, MyResponseSchema | MyErrorResponseSchema]:
# Implementation here
return 200, MyResponseSchema(results=[])
```
3. All endpoints must be `async def`
4. Use `AuthenticatedRequest` for authenticated endpoints
5. For multi-language endpoints, add dispatch by `data.language` with lazy imports
**Checkpoint**: The endpoint should handle success and error cases with proper status codes.
### Step 3: Register in urls.py
Add the endpoint to `aiservice/urls.py`.
1. Import the API object:
```python
from core.shared.my_feature import my_feature_api
```
2. Add to `urlpatterns`:
```python
path("ai/my-feature", my_feature_api.urls),
```
3. Follow the naming convention: `ai/<kebab-case-name>`
**Checkpoint**: The endpoint should be accessible at `/ai/my-feature/`.
### Step 4: Add Tests
Write tests for the endpoint.
1. Create test file in `tests/` matching the source structure
2. Test the handler function directly (not via HTTP):
```python
@pytest.mark.asyncio
async def test_my_endpoint():
# Mock request and data
result = await my_endpoint(mock_request, mock_data)
assert result[0] == 200
```
3. Run: `uv run pytest tests/path/test_file.py -v`
**Checkpoint**: Tests pass. Run `uv run prek run --all-files`.
## Part B: CF-API Endpoint (Express)
### Step 1: Create Endpoint Handler
Create the endpoint handler in `js/cf-api/endpoints/`.
1. Create `js/cf-api/endpoints/my-feature.ts`:
```typescript
import { Request, Response } from "express"
export async function myFeature(req: Request, res: Response) {
// Implementation
res.status(200).json({ results: [] })
}
```
2. Follow existing patterns in `endpoints/`
**Checkpoint**: Handler should return appropriate status codes and JSON responses.
### Step 2: Create Route File or Add to Existing
Add the route to the appropriate route file.
1. If it's a new domain, create `js/cf-api/routes/my-feature.routes.ts`:
```typescript
import { Router } from "express"
import { addAsync } from "@awaitjs/express"
import { myFeature } from "../endpoints/my-feature.js"
import { ROUTES } from "../constants/index.js"
const router = addAsync(Router()) as any
router.postAsync(ROUTES.MY_FEATURE, myFeature)
export default router
```
2. If it belongs to an existing domain, add to the corresponding route file
3. Add the route constant to `constants/index.ts`
**Checkpoint**: Route file exports a router with the endpoint registered.
### Step 3: Register in Route Index
Register the route in `js/cf-api/routes/index.ts`.
1. Import the route module
2. Register in the correct section:
- Before body parser: webhook routes only
- Public routes: no auth required
- Protected routes: after `checkForValidAPIKey` middleware
3. Apply middleware as needed (`trackUsage`, `idLimiter`, etc.)
**Checkpoint**: The endpoint should be accessible with proper authentication.
### Step 4: Add Tests
Write tests using the dependency injection pattern.
1. Create test file in `js/cf-api/__tests__/`
2. Use `setXxxDependencies()` / `resetXxxDependencies()` for mocking
3. Follow existing test patterns
**Checkpoint**: Tests pass with `npm test`.
## Key Files Reference
| File | What to modify |
|------|---------------|
| `core/shared/optimizer_models.py` | Schema patterns |
| `aiservice/urls.py` | AIService endpoint registration |
| `js/cf-api/routes/index.ts` | CF-API route registration |
| `js/cf-api/constants/index.ts` | Route constants |
| `authapp/auth.py` | Authentication patterns |