API endpoints should be properly organized around resources and follow RESTful principles. Avoid placing aggregation or utility endpoints in viewsets where they don’t belong conceptually.

Each viewset should represent a specific resource type, and endpoints within that viewset should operate on that resource. When you need aggregation endpoints or cross-resource operations, create dedicated API endpoints rather than forcing them into existing viewsets.

Example of what to avoid:

# DON'T: Adding aggregation endpoint to external_data_source viewset
class ExternalDataSourceViewSet(ModelViewSet):
    @action(methods=["GET"], detail=False)
    def dwh_scene_stats(self, request):  # This doesn't belong here
        # Returns aggregated data warehouse statistics
        pass

Example of proper organization:

# DO: Create dedicated endpoint for aggregations
class DataWarehouseViewSet(ModelViewSet):
    @action(methods=["GET"], detail=False) 
    def scene_stats(self, request):
        # Returns aggregated data warehouse statistics
        pass

For individual vs collection resources, handle both cases properly:

# Handle both individual survey and survey collection
def surveys(request: Request):
    if survey_id:
        # Return individual survey with proper error handling
        try:
            survey = Survey.objects.get(id=survey_id, team=team)
            return JsonResponse({"survey": serialized_survey})
        except Survey.DoesNotExist:
            return JsonResponse({"error": "Survey not found"}, status=404)
    
    # Return collection of surveys
    return JsonResponse(get_surveys_response(team))

This approach makes APIs more intuitive, maintainable, and follows REST conventions that frontend developers expect.