Сначала, конечно, тянет сделать что-то такое:
`
/countries/{id}/regions/{id}/cities/{id}`Красиво же! Иерархично! Прямо видно структуру данных!
Но это ощущение проходит примерно через пять минут — как только начинаешь думать о реальном использовании.
Во-первых, все эти сущности живут сами по себе: у страны есть ID, у региона есть ID, у города есть ID.
Зачем же закапывать их друг в друга, если каждый можно получить напрямую?
Во-вторых, фильтрация потом превращается в цирк:
если тебе нужны «все города страны с населением больше 100к и без метро», то в лесенке из URL это выглядит максимально странно.
Поэтому финальный, рабочий и жизненный вариант у меня такой:
1. Каноничные ресурсы — плоские
GET /countries
GET /countries/{country_id}
GET /regions
GET /regions/{region_id}
GET /cities
GET /cities/{city_id}
Каждая сущность доступна сама по себе. Это убирает лишние проверки, упрощает клиентам жизнь и делает API устойчивым.
2. Отношения — через коллекции
GET /countries/{country_id}/regions
GET /regions/{region_id}/cities
GET /countries/{country_id}/cities
Каждая сущность доступна сама по себе. Это убирает лишние проверки, упрощает клиентам
Это удобно для навигации — но не обязательно для CRUD.
3. Фильтры — через параметры
```
GET /cities?country_id=1&population_gt=100000
GET /cities?region_id=42&has_metro=true```
Это гибче, чище и не ломается от каждого нового поля.
Но в общем — вот так.