93:        "total_recipients": c.total_recipients, "sent_count": c.sent_count,
290:    """Preview: generate the campaign plan for a sample of recipients and render
309:        raise HTTPException(status_code=400, detail="Recipient list has no valid recipients")
380:        # materialize campaign_recipients on first start
391:            raise HTTPException(status_code=400, detail="No valid recipients in list")
394:                                detail=f"Too many recipients ({len(recipient_rows)}); max {cfg.MAX_RECIPIENTS_PER_CAMPAIGN}")
396:        c.total_recipients = result.get("total", 0)
459:    total = c.total_recipients or 0
546:@router.get("/{cid}/recipients")
547:async def campaign_recipients(cid: int, status: str = Query(""),
