---
estimated_steps: 21
estimated_files: 2
skills_used: []
---

# T01: Add last_technique_at to creators API endpoint

Add a correlated subquery for MAX(technique_pages.created_at) to the list_creators endpoint, expose it via the CreatorBrowseItem schema, and rebuild+deploy the API container.

## Steps

1. In `backend/schemas.py`, add `last_technique_at: datetime | None = None` to `CreatorBrowseItem` (after `video_count`).
2. In `backend/routers/creators.py`:
   - Add a `last_technique_sq` correlated subquery: `select(func.max(TechniquePage.created_at)).where(TechniquePage.creator_id == Creator.id).correlate(Creator).scalar_subquery()`
   - Add it to the `select()` call with `.label("last_technique_at")`
   - Update the row unpacking to read index [3] as `last_technique_at`
   - Pass `last_technique_at=last_technique_at` to the `CreatorBrowseItem(...)` constructor
3. SSH to ub01, rebuild and restart the API container:
   ```
   ssh ub01 'cd /vmPool/r/repos/xpltdco/chrysopedia && git pull && docker compose build chrysopedia-api && docker compose up -d chrysopedia-api'
   ```
4. Verify the field appears in the API response.

## Must-Haves

- [ ] `last_technique_at` field present on every item in `/api/v1/creators` response
- [ ] Field is a datetime string for creators with techniques, null for creators with 0 techniques
- [ ] Existing sort/filter/pagination behavior unchanged

## Verification

- `ssh ub01 'curl -s http://localhost:8096/api/v1/creators?limit=5' | python3 -m json.tool | grep last_technique_at` shows the field on each item
- At least one item has a non-null datetime value
- At least one item (if any creator has 0 techniques) has null

## Inputs

- `backend/schemas.py`
- `backend/routers/creators.py`
- `backend/models.py`

## Expected Output

- `backend/schemas.py`
- `backend/routers/creators.py`

## Verification

ssh ub01 'curl -s http://localhost:8096/api/v1/creators?limit=5' | python3 -m json.tool | grep last_technique_at
