Work/HoodBox
Four to five hours of daily email became twenty minutes
Email that took three people now takes one person 20 minutes a day, and nobody copies between three sales tools any more.
- 18 hours a week back
- From 3 people to 1
- 12 weeks to hand over
- Industry
- Lead generation
- Email work
- From 3 people to 1, 20 minutes a day
- Time to hand over
- 12 weeks
- Time back
- 18 hours a week
In one paragraph
A small team ran outbound email across 200+ mailboxes using three tools that did not talk to each other: HubSpot for deals, SmartLead for campaigns and Apollo for prospects. Copying between them by hand took two to three hours a day, and no tool could answer "who did we talk to about this." HoodBox pulls all three into one database and lets the team search 50,000+ communications by what was said rather than by field. It also enriches leads automatically, and an admin panel shows the team every sync and every failure. Daily email work went from four to five hours, shared by three people, to twenty minutes for one person. The copying stopped. I delivered it in twelve weeks with documentation and training, and it is hosted on infrastructure I run.
The problem I started from
Each tool had its own data model, and there was no single view across them. Most tasks needed all three sources, which meant a person copying rows. The team was at 50 campaigns and 10,000 leads and growing, so the copying was going to stop scaling before the outreach did.
The second problem was search. Every tool searched by fields such as name, company and stage. Nobody could search by conversation. So "Which leads mentioned pricing" was a question with no place to ask it.
What I decided
One database for three sources, with the original IDs kept on every row. Everything from HubSpot, SmartLead and Apollo maps onto the same record types, but each record keeps the ID it had in the system it came from. So anything can be traced back, and updates can flow back the other way. A layer like this costs effort up front, and it pays that back the first time a vendor changes its data format.
Search by meaning and by keyword, not by meaning alone. Vector embeddings handle meaning, keyword filters handle exact matches, and reciprocal rank fusion combines the two rankings. On its own, vector search returned answers that were plausible but wrong. Paired with metadata filters, it returned the right lead.
A cap on simultaneous calls to every outside API. All three vendors limit how often their APIs can be called, so each API gets its own semaphore that caps how many calls run at once. Work runs in batches with its progress tracked, and the code uses async I/O throughout. That is how 50 campaigns sync without hitting a limit.
An admin panel from week one. Everything inside the system is visible there: the sync status of each source, logs that can be filtered and searched, and a drill-down into any failure. I built it for the team's troubleshooting, and it ended up speeding up my own development more than anything else in the project.
Progress by polling, not WebSockets. Some syncs run for minutes. For those, a progress endpoint that the page polls proved more reliable than a socket, and it was simpler to recover when a browser tab went away.
What exists
| Scale | 200+ mailboxes, 50+ campaigns, 10,000+ leads, 50,000+ communications from three systems in one Postgres database with pgvector |
|---|---|
| Search | Sub-second over 50K+ records, vector plus keyword |
| Sync | Background workers per source, 98% success with automatic retry |
| Code | ~15,000 lines, Python (async, FastAPI) and TypeScript (React), 65% test coverage |
| Delivered | Architecture diagrams, OpenAPI docs, setup and deployment guides, troubleshooting guide, integration reference |
| Training | Two hours for engineers, one hour for the product team, both recorded, plus a developer handbook |
| Time | Twelve weeks: two of design, three of integrations, two of search and enrichment, two of frontend, two of hardening, one of handoff |
What the client said
"This is exactly what we needed. Before, we were copying data between 3 tools constantly. Now everything is in one place and we can find leads by what we talked about. The admin UI makes it easy to see when something's wrong and fix it quickly."
What I would do differently
Ship search first, enrichment later. Search was what the team wanted most, and it was ready by week seven. But it waited for enrichment, and it should have shipped without it.