Skip to content

Commit f7f2b01

Browse files
mortenohclaude
andcommitted
fix: change config endpoint from /api/v1/config to /api/v1/configs
Changes the config endpoint to use plural form for consistency with other endpoints (artifacts, tasks) and REST API conventions. Updated: - service_builder.py: Changed default prefix in _ConfigOptions and with_config() - All test files: Updated endpoint references - All example files: Updated endpoint references - Documentation: Updated endpoint references - Postman collections: Updated endpoint references All tests pass (551 passed, 1 skipped) All linting checks pass 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 9895429 commit f7f2b01

33 files changed

Lines changed: 296 additions & 292 deletions

docs/guides/authentication.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -190,13 +190,13 @@ custom_paths = default_paths + ["/public", "/status"]
190190

191191
```bash
192192
# Valid request
193-
curl -H "X-API-Key: sk_dev_test123" http://localhost:8000/api/v1/config
193+
curl -H "X-API-Key: sk_dev_test123" http://localhost:8000/api/v1/configs
194194

195195
# Missing key (returns 401)
196-
curl http://localhost:8000/api/v1/config
196+
curl http://localhost:8000/api/v1/configs
197197

198198
# Invalid key (returns 401)
199-
curl -H "X-API-Key: invalid_key" http://localhost:8000/api/v1/config
199+
curl -H "X-API-Key: invalid_key" http://localhost:8000/api/v1/configs
200200

201201
# Unauthenticated path (no key needed)
202202
curl http://localhost:8000/api/v1/health
@@ -211,7 +211,7 @@ headers = {"X-API-Key": "sk_dev_test123"}
211211

212212
# Authenticated request
213213
response = requests.get(
214-
"http://localhost:8000/api/v1/config",
214+
"http://localhost:8000/api/v1/configs",
215215
headers=headers
216216
)
217217

@@ -228,7 +228,7 @@ headers = {"X-API-Key": "sk_dev_test123"}
228228

229229
async with httpx.AsyncClient() as client:
230230
response = await client.get(
231-
"http://localhost:8000/api/v1/config",
231+
"http://localhost:8000/api/v1/configs",
232232
headers=headers
233233
)
234234
assert response.status_code == 200
@@ -366,7 +366,7 @@ Chapkit automatically logs authentication events with **masked keys** for securi
366366
{
367367
"event": "auth.success",
368368
"key_prefix": "sk_prod",
369-
"path": "/api/v1/config"
369+
"path": "/api/v1/configs"
370370
}
371371
```
372372

@@ -376,7 +376,7 @@ Chapkit automatically logs authentication events with **masked keys** for securi
376376
{
377377
"event": "auth.invalid_key",
378378
"key_prefix": "sk_unkn",
379-
"path": "/api/v1/config",
379+
"path": "/api/v1/configs",
380380
"method": "GET"
381381
}
382382
```
@@ -386,7 +386,7 @@ Chapkit automatically logs authentication events with **masked keys** for securi
386386
```json
387387
{
388388
"event": "auth.missing_key",
389-
"path": "/api/v1/config",
389+
"path": "/api/v1/configs",
390390
"method": "GET"
391391
}
392392
```
@@ -430,7 +430,7 @@ All authentication errors follow RFC 9457 Problem Details format.
430430
"title": "Unauthorized",
431431
"status": 401,
432432
"detail": "Missing authentication header: X-API-Key",
433-
"instance": "/api/v1/config"
433+
"instance": "/api/v1/configs"
434434
}
435435
```
436436

@@ -442,7 +442,7 @@ All authentication errors follow RFC 9457 Problem Details format.
442442
"title": "Unauthorized",
443443
"status": 401,
444444
"detail": "Invalid API key",
445-
"instance": "/api/v1/config"
445+
"instance": "/api/v1/configs"
446446
}
447447
```
448448

@@ -460,7 +460,7 @@ All authentication errors follow RFC 9457 Problem Details format.
460460

461461
Test with:
462462
```bash
463-
curl -H "X-Custom-API-Key: sk_dev_test123" http://localhost:8000/api/v1/config
463+
curl -H "X-Custom-API-Key: sk_dev_test123" http://localhost:8000/api/v1/configs
464464
```
465465

466466
### Multiple Environments

docs/guides/monitoring.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ All operational endpoints (`/health`, `/system`, `/metrics`) use root-level path
350350

351351
**Solution**:
352352
1. Make some requests to your API endpoints
353-
2. Verify FastAPI instrumentation with: `curl http://localhost:8000/api/v1/config`
353+
2. Verify FastAPI instrumentation with: `curl http://localhost:8000/api/v1/configs`
354354
3. Check metrics again: `curl http://localhost:8000/metrics | grep http_request`
355355

356356
### Prometheus Cannot Scrape

examples/custom_operations_api.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ class ResetResponse(BaseModel):
6666
def create_feature_router() -> APIRouter:
6767
"""Create config router with custom operations."""
6868
router = CrudRouter[ConfigIn[FeatureConfig], ConfigOut[FeatureConfig]](
69-
prefix="/api/v1/config",
69+
prefix="/api/v1/configs",
7070
tags=["config"],
7171
entity_in_type=ConfigIn[FeatureConfig],
7272
entity_out_type=ConfigOut[FeatureConfig],
@@ -84,7 +84,7 @@ async def toggle_enabled(
8484
config = await manager.find_by_id(config_id)
8585

8686
if config is None:
87-
raise NotFoundError(f"Config {entity_id} not found", instance=f"/api/v1/config/{entity_id}")
87+
raise NotFoundError(f"Config {entity_id} not found", instance=f"/api/v1/configs/{entity_id}")
8888

8989
# Create updated config with modified enabled flag
9090
updated_data = FeatureConfig(
@@ -117,7 +117,7 @@ async def validate_config(
117117
config = await manager.find_by_id(config_id)
118118

119119
if config is None:
120-
raise NotFoundError(f"Config {entity_id} not found", instance=f"/api/v1/config/{entity_id}")
120+
raise NotFoundError(f"Config {entity_id} not found", instance=f"/api/v1/configs/{entity_id}")
121121

122122
errors: list[str] = []
123123
warnings: list[str] = []
@@ -162,11 +162,11 @@ async def duplicate_config(
162162
config = await manager.find_by_id(config_id)
163163

164164
if config is None:
165-
raise NotFoundError(f"Config {entity_id} not found", instance=f"/api/v1/config/{entity_id}")
165+
raise NotFoundError(f"Config {entity_id} not found", instance=f"/api/v1/configs/{entity_id}")
166166

167167
# Check if name already exists
168168
if await manager.find_by_name(new_name):
169-
raise ConflictError(f"Config with name '{new_name}' already exists", instance="/api/v1/config")
169+
raise ConflictError(f"Config with name '{new_name}' already exists", instance="/api/v1/configs")
170170

171171
# Create duplicate with new name
172172
duplicate = ConfigIn[FeatureConfig](

examples/docker/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ vi .env
5555
docker-compose -f docker-compose.auth-envvar.yml up
5656

5757
# 4. Test
58-
curl -H "X-API-Key: YOUR_KEY_HERE" http://localhost:8000/api/v1/config
58+
curl -H "X-API-Key: YOUR_KEY_HERE" http://localhost:8000/api/v1/configs
5959
```
6060

6161
### Option 2: Docker Secrets (Most Secure)
@@ -75,7 +75,7 @@ chmod 400 secrets/api_keys.txt
7575
docker-compose -f docker-compose.auth-secrets.yml up
7676

7777
# 5. Test
78-
curl -H "X-API-Key: YOUR_KEY_HERE" http://localhost:8000/api/v1/config
78+
curl -H "X-API-Key: YOUR_KEY_HERE" http://localhost:8000/api/v1/configs
7979
```
8080

8181
## File Structure
@@ -103,7 +103,7 @@ curl http://localhost:8000/health
103103

104104
```bash
105105
# Replace YOUR_KEY with actual key
106-
curl -H "X-API-Key: YOUR_KEY" http://localhost:8000/api/v1/config
106+
curl -H "X-API-Key: YOUR_KEY" http://localhost:8000/api/v1/configs
107107
```
108108

109109
### View Logs

examples/docs/POSTMAN.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ POST /api/v1/ml/$predict
233233

234234
**Create config with normalization:**
235235
```json
236-
POST /api/v1/config
236+
POST /api/v1/configs
237237
{
238238
"name": "weather_model_normalized",
239239
"data": {

examples/docs/README.md

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ curl http://127.0.0.1:8000/health
4545
### 3. Create Configuration
4646

4747
```bash
48-
curl -X POST http://127.0.0.1:8000/api/v1/config \
48+
curl -X POST http://127.0.0.1:8000/api/v1/configs \
4949
-H "Content-Type: application/json" \
5050
-d '{
5151
"name": "my_model_config",
@@ -125,12 +125,12 @@ All ML services provide these endpoints:
125125
- `GET /system` - System information (if `.with_system()` enabled)
126126

127127
### Configuration
128-
- `POST /api/v1/config` - Create config
129-
- `GET /api/v1/config` - List all configs (supports pagination)
130-
- `GET /api/v1/config/{id}` - Get specific config
131-
- `PUT /api/v1/config/{id}` - Update config
132-
- `DELETE /api/v1/config/{id}` - Delete config
133-
- `GET /api/v1/config/$schema` - Get config JSON schema
128+
- `POST /api/v1/configs` - Create config
129+
- `GET /api/v1/configs` - List all configs (supports pagination)
130+
- `GET /api/v1/configs/{id}` - Get specific config
131+
- `PUT /api/v1/configs/{id}` - Update config
132+
- `DELETE /api/v1/configs/{id}` - Delete config
133+
- `GET /api/v1/configs/$schema` - Get config JSON schema
134134

135135
### Artifacts
136136
- `POST /api/v1/artifacts` - Create artifact
@@ -212,10 +212,10 @@ List endpoints support optional pagination:
212212

213213
```bash
214214
# Without pagination (returns array)
215-
curl http://127.0.0.1:8000/api/v1/config
215+
curl http://127.0.0.1:8000/api/v1/configs
216216

217217
# With pagination (returns PaginatedResponse)
218-
curl "http://127.0.0.1:8000/api/v1/config?page=1&size=10"
218+
curl "http://127.0.0.1:8000/api/v1/configs?page=1&size=10"
219219
```
220220

221221
## Error Handling
@@ -228,7 +228,7 @@ All services use RFC 9457 problem details format:
228228
"title": "Not Found",
229229
"status": 404,
230230
"detail": "Config 01K72P60ZNX2PJ6QJWZK7RMCRV not found",
231-
"instance": "/api/v1/config/01K72P60ZNX2PJ6QJWZK7RMCRV"
231+
"instance": "/api/v1/configs/01K72P60ZNX2PJ6QJWZK7RMCRV"
232232
}
233233
```
234234

@@ -276,10 +276,10 @@ curl http://127.0.0.1:8000/health
276276

277277
```bash
278278
# Without auth (fails with 401)
279-
curl http://127.0.0.1:8000/api/v1/config
279+
curl http://127.0.0.1:8000/api/v1/configs
280280

281281
# With valid API key (succeeds)
282-
curl -H "X-API-Key: sk_prod_abc123" http://127.0.0.1:8000/api/v1/config
282+
curl -H "X-API-Key: sk_prod_abc123" http://127.0.0.1:8000/api/v1/configs
283283
```
284284

285285
### Common Authentication Endpoints
@@ -291,7 +291,7 @@ curl -H "X-API-Key: sk_prod_abc123" http://127.0.0.1:8000/api/v1/config
291291
- `GET /openapi.json` - OpenAPI schema
292292

293293
#### Authenticated (Require X-API-Key header)
294-
- All `/api/v1/config` endpoints
294+
- All `/api/v1/configs` endpoints
295295
- All `/api/v1/artifacts` endpoints (if enabled)
296296
- All `/api/v1/jobs` endpoints (if enabled)
297297
- All `/api/v1/ml/*` endpoints (if enabled)

examples/docs/auth_basic.md

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ curl http://127.0.0.1:8000/health
4242
### 2. Try Accessing Config Without Auth (Fails)
4343

4444
```bash
45-
curl http://127.0.0.1:8000/api/v1/config
45+
curl http://127.0.0.1:8000/api/v1/configs
4646
```
4747

4848
**Response (401 Unauthorized):**
@@ -52,14 +52,14 @@ curl http://127.0.0.1:8000/api/v1/config
5252
"title": "Unauthorized",
5353
"status": 401,
5454
"detail": "Missing authentication header: X-API-Key",
55-
"instance": "/api/v1/config"
55+
"instance": "/api/v1/configs"
5656
}
5757
```
5858

5959
### 3. Access Config With Invalid Key (Fails)
6060

6161
```bash
62-
curl -H "X-API-Key: invalid_key" http://127.0.0.1:8000/api/v1/config
62+
curl -H "X-API-Key: invalid_key" http://127.0.0.1:8000/api/v1/configs
6363
```
6464

6565
**Response (401 Unauthorized):**
@@ -69,14 +69,14 @@ curl -H "X-API-Key: invalid_key" http://127.0.0.1:8000/api/v1/config
6969
"title": "Unauthorized",
7070
"status": 401,
7171
"detail": "Invalid API key",
72-
"instance": "/api/v1/config"
72+
"instance": "/api/v1/configs"
7373
}
7474
```
7575

7676
### 4. Access Config With Valid Key (Success)
7777

7878
```bash
79-
curl -H "X-API-Key: sk_dev_abc123" http://127.0.0.1:8000/api/v1/config
79+
curl -H "X-API-Key: sk_dev_abc123" http://127.0.0.1:8000/api/v1/configs
8080
```
8181

8282
**Response:**
@@ -89,7 +89,7 @@ curl -H "X-API-Key: sk_dev_abc123" http://127.0.0.1:8000/api/v1/config
8989
### 5. Create Configuration (With Auth)
9090

9191
```bash
92-
curl -X POST http://127.0.0.1:8000/api/v1/config \
92+
curl -X POST http://127.0.0.1:8000/api/v1/configs \
9393
-H "X-API-Key: sk_dev_abc123" \
9494
-H "Content-Type: application/json" \
9595
-d '{
@@ -120,7 +120,7 @@ curl -X POST http://127.0.0.1:8000/api/v1/config \
120120

121121
```bash
122122
curl -H "X-API-Key: sk_dev_abc123" \
123-
http://127.0.0.1:8000/api/v1/config/\$schema
123+
http://127.0.0.1:8000/api/v1/configs/\$schema
124124
```
125125

126126
**Response:**
@@ -147,7 +147,7 @@ curl -H "X-API-Key: sk_dev_abc123" \
147147

148148
```bash
149149
curl -H "X-API-Key: sk_dev_abc123" \
150-
http://127.0.0.1:8000/api/v1/config/01K79YAHJ7BR4E87VVTG8FNBMA
150+
http://127.0.0.1:8000/api/v1/configs/01K79YAHJ7BR4E87VVTG8FNBMA
151151
```
152152

153153
**Response:**
@@ -167,7 +167,7 @@ curl -H "X-API-Key: sk_dev_abc123" \
167167
### 8. Update Config
168168

169169
```bash
170-
curl -X PUT http://127.0.0.1:8000/api/v1/config/01K79YAHJ7BR4E87VVTG8FNBMA \
170+
curl -X PUT http://127.0.0.1:8000/api/v1/configs/01K79YAHJ7BR4E87VVTG8FNBMA \
171171
-H "X-API-Key: sk_dev_abc123" \
172172
-H "Content-Type: application/json" \
173173
-d '{
@@ -197,17 +197,17 @@ curl -X PUT http://127.0.0.1:8000/api/v1/config/01K79YAHJ7BR4E87VVTG8FNBMA \
197197

198198
```bash
199199
# Simple list
200-
curl -H "X-API-Key: sk_dev_abc123" http://127.0.0.1:8000/api/v1/config
200+
curl -H "X-API-Key: sk_dev_abc123" http://127.0.0.1:8000/api/v1/configs
201201

202202
# Paginated
203203
curl -H "X-API-Key: sk_dev_abc123" \
204-
"http://127.0.0.1:8000/api/v1/config?page=1&size=10"
204+
"http://127.0.0.1:8000/api/v1/configs?page=1&size=10"
205205
```
206206

207207
### 10. Delete Config
208208

209209
```bash
210-
curl -X DELETE http://127.0.0.1:8000/api/v1/config/01K79YAHJ7BR4E87VVTG8FNBMA \
210+
curl -X DELETE http://127.0.0.1:8000/api/v1/configs/01K79YAHJ7BR4E87VVTG8FNBMA \
211211
-H "X-API-Key: sk_dev_abc123"
212212
```
213213

@@ -219,8 +219,8 @@ Support multiple keys simultaneously for zero-downtime rotation:
219219

220220
```bash
221221
# Both keys work
222-
curl -H "X-API-Key: sk_dev_abc123" http://127.0.0.1:8000/api/v1/config
223-
curl -H "X-API-Key: sk_dev_xyz789" http://127.0.0.1:8000/api/v1/config
222+
curl -H "X-API-Key: sk_dev_abc123" http://127.0.0.1:8000/api/v1/configs
223+
curl -H "X-API-Key: sk_dev_xyz789" http://127.0.0.1:8000/api/v1/configs
224224
```
225225

226226
**Rotation workflow:**
@@ -312,7 +312,7 @@ sk_dev_test123 # Development
312312

313313
**Solution:** Add header to all protected endpoints:
314314
```bash
315-
curl -H "X-API-Key: sk_dev_abc123" http://127.0.0.1:8000/api/v1/config
315+
curl -H "X-API-Key: sk_dev_abc123" http://127.0.0.1:8000/api/v1/configs
316316
```
317317

318318
### "Invalid API key"
@@ -340,7 +340,7 @@ headers = {"X-API-Key": os.getenv("SERVICE_B_API_KEY")}
340340

341341
async with httpx.AsyncClient() as client:
342342
response = await client.get(
343-
"http://service-b:8000/api/v1/config",
343+
"http://service-b:8000/api/v1/configs",
344344
headers=headers
345345
)
346346
print(response.json())

0 commit comments

Comments
 (0)