AI Integration · CRM Automation
CRM AI Sales Automation Platform
Pipedrive + OpenAI GPT-4 Integration
AI-powered system that automatically identifies 50,000+ inactive CRM contacts and sends them personalized follow-up emails — fully automated, daily, without human intervention.
- Role
- Solo Full-Stack Developer
- Year
- 2025
- Client
- Easy Logistics Management — U.S.-based freight, warehousing, and parcel shipping company
- Type
- Client Work — Web Application
- 50,000+
- Contacts handled
- 23
- API endpoints
- 8
- UI pages
- 5
- Database tables
Overview
A full-stack AI automation platform that connects to Pipedrive CRM, identifies contacts who haven't been reached in 60–90 days, generates personalized follow-up emails using GPT-4, and sends them — automatically every day or manually after human review.
The problem
The client runs a logistics company with 50,000+ contacts in Pipedrive, growing by ~1,000 every week. Their team had no way to:
- Know which contacts had gone cold (no activity in 60–90 days)
- Write hundreds of personalized follow-up emails without copying templates
- Track whether contacts had been followed up with
- Maintain their brand voice across all outreach at scale
They had tried to build this automation in Make.com — it didn't work. They needed a custom solution.
"I want AI to identify contacts we have not followed up with and help us stay on top of them so that leads/contacts are not falling through the cracks." — Jeremy Curran, Founder, Easy Logistics Management
The solution
A two-milestone project delivered in full.
Milestone 1 — Dashboard UI & Pipedrive Integration
- Full responsive dashboard (stats, lead table, calendar, AI insights panel)
- Live data from Pipedrive (leads, deals, activities, contacts)
- Authentication system (JWT, httpOnly cookies, route protection)
- 8 pages, 7-item sidebar navigation
Milestone 2 — AI Integration & Email Automation
- GPT-4 powered personalized email generation per contact
- Stale contact detection engine (configurable 60–90 day threshold)
- Paginated processing (50k+ contacts handled without timeouts)
- Email draft review UI — view, edit, select, bulk send
- Office 365 SMTP sending via the client's own email account
- Complete email audit trail (every send logged to the database)
- System prompt editor — client customizes AI tone without code
- Daily cron automation — fully unattended operation
How it works
Manual mode (human reviews first)
- User opens the Stale Contacts page
- System fetches contacts from Pipedrive, page by page
- Filters contacts inactive 90+ days
- GPT-4 writes a personalized email per contact, using conversation history
- AI drafts shown in the UI — user can edit before sending
- User selects contacts and sends
- Emails sent via Office 365 SMTP
- Every send logged to the database
Auto mode (fully unattended)
- Cron job fires daily and calls
/api/cron /api/run-automationprocesses page 0- Generates email suggestions, reusing cached drafts
- Auto-sends if
settings.autoSendEmails = true - Fires the next page asynchronously (chain continues)
- Processes all 50k contacts across multiple pages
- Updates
lastRunDatein settings
Technical challenges and solutions
50,000+ contacts without timeouts. Pipedrive's API caps at 500 records per request, and processing everything in one request would time out. Solved with three-layer pagination — 100 contacts per page from Pipedrive, batched 20 at a time for AI generation, with async page-chaining for background automation. No single request takes more than a few seconds.
OpenAI rate limits at scale. Sending 50+ simultaneous GPT-4 requests hits rate limits instantly. Solved with batched processing and delays (20/batch at 500ms for the UI path, 3/batch at 2s for automation), plus retry logic that reads the Retry-After-Ms header from 429 responses and waits precisely instead of guessing.
GPT-4 returns unpredictable JSON. Despite prompting for {"subject": "...", "body": "..."}, GPT-4 sometimes returns markdown-wrapped JSON, malformed JSON, or plain text. Solved with a four-layer parsing pipeline: try JSON.parse → regex-extract a JSON block → manually extract fields with regex → detect a Subject: line → hardcoded template fallback. It never crashes and never returns null.
Preventing duplicate emails. Both the manual UI and the cron job process the same contacts, so without coordination a contact could get emailed twice. Solved with two independent deduplication checks — an EmailSuggestion.isUsed flag set true immediately on send, plus an EmailLog date check that skips contacts emailed within the inactivity window.
Brand voice mismatch. Early AI emails were generic and didn't match the client's tone (fun, sassy, logistics-focused, strong CTAs). Solved by building a full system-prompt management UI — the client writes, edits, and activates custom AI prompts from the dashboard with no code changes. The default prompt is a 500-word company brief covering services, selling points, and tone guidelines.
Context-aware personalization. Generic emails ignore a contact's previous conversations with the client. Solved by fetching Pipedrive's mail-threads API before each generation, retrieving the 3 most recent messages, stripping HTML, and injecting that conversation history into the GPT-4 prompt so the AI naturally references past interactions.
Key features
| Feature | Description |
|---|---|
| Stale Contact Detection | Finds contacts inactive 60–90 days (configurable) |
| AI Email Generation | GPT-4 writes personalized emails using contact data + conversation history |
| Email Suggestion Cache | Generated drafts stored in DB — no redundant API calls |
| Bulk Send | Select all or individual contacts, send in one click |
| Email Audit Trail | Every send attempt logged (success/failure/error message) |
| System Prompt Editor | Client customizes AI behavior from the UI, no code needed |
| Cron Automation | Daily unattended run — auto-generates + auto-sends |
| Settings Control | Inactivity threshold, auto-send toggle, active prompt selection |
| Authentication | JWT sessions, bcrypt passwords, httpOnly cookies, middleware protection |
Database schema
User— authentication (email, bcrypt password)Settings— inactivity days, auto-send toggle, active prompt IDEmailLog— every send attempt (contactId, subject, body, success, errorMessage)EmailSuggestion— AI-generated drafts cached per contact (isUsed flag)SystemPrompt— custom AI prompts stored in the database
Codebase stats
- 23 API endpoints
- 8 UI pages
- 5 database tables
- 4 external integrations
- ~2,500 lines of TypeScript application logic
- 100% TypeScript (frontend + backend)
Client feedback and iterations
The client gave two rounds of detailed feedback. Every item was implemented.
| Feedback | What I built |
|---|---|
| "Focus on contacts, not leads — we have 72k" | Switched to Pipedrive's /persons endpoint |
| "I can't see the AI-generated emails" | Email logs page + expandable email preview UI |
| "Not tracking 60–90 day inactive contacts" | Full stale detection engine |
| "AI emails don't match our brand voice" | System prompt editor with brand brief |
| "No way to approve before sending" | Draft review step + per-contact edit |
| "Emails all sound the same" | GPT temperature 0.8 + conversation history context |
| "Auto-send not working" | autoSendEmails setting wired into cron automation |
Result
Fully automated daily email campaigns running without human intervention. The client can review AI drafts before sending or enable full auto-send.
Client: Easy Logistics Management, USA. Project developed as full-time company work.