import express from "express"; import cors from "cors"; import morgan from "morgan"; import axios from "axios"; import path from "path"; import { getAiCompletionServer } from "./src/lib/aiServiceServer"; // ... // Initial realistic state for fallback / offline / testing mode let mockDb = { campaigns: [ { id: "camp_9901", name: "Enterprise SaaS Outbound Q3", status: "ACTIVE", created_at: "2026-07-15T10:00:00.000Z", lead_count: 1420, sent_count: 3840, open_count: 2150, reply_count: 168, bounce_count: 24, click_count: 430, timezone: "America/New_York", start_schedule: "09:00", end_schedule: "18:00", track_settings: "TRACK_EMAIL_OPEN_AND_CLICK", send_as_plain_text: false, follow_up_percentage: 85, unsubscribe_text: "Reply unsubscribe to stop receiving emails.", stop_lead_settings: "REPLIED", sequences: [ { id: "seq_1", seq_number: 1, delay_days: 0, subject: "Quick question regarding {{company_name}}'s outbound infrastructure", email_body: "

Hi {{first_name}},

Noticed you are scaling your growth team at {{company_name}}. Are you currently looking to optimize your cold outreach deliverability and warmup automation?

Best,
Alex

", variant_distribution_percentage: 50, variants: [ { id: "var_1a", variant_label: "Variant A", subject: "Quick question regarding {{company_name}}'s outbound infrastructure", email_body: "

Hi {{first_name}},

Noticed you are scaling your growth team at {{company_name}}. Are you currently looking to optimize your cold outreach deliverability and warmup automation?

Best,
Alex

" }, { id: "var_1b", variant_label: "Variant B (Shorter)", subject: "{{first_name}} - {{company_name}} outbound efficiency", email_body: "

Hey {{first_name}},

We helped similar SaaS leaders double their positive response rates without hitting spam filters. Open to a 3-min loom?

Alex

" } ] }, { id: "seq_2", seq_number: 2, delay_days: 3, subject: "Re: Quick question regarding {{company_name}}", email_body: "

Hi {{first_name}}, following up on my previous note. Did you have a chance to look at this?

", variant_distribution_percentage: 100, variants: [] } ], email_account_ids: ["acc_101", "acc_102"] }, { id: "camp_9902", name: "Fintech Growth & Compliance Sequence", status: "PAUSED", created_at: "2026-07-20T14:30:00.000Z", lead_count: 850, sent_count: 1200, open_count: 620, reply_count: 42, bounce_count: 11, click_count: 98, timezone: "Europe/London", start_schedule: "08:30", end_schedule: "17:30", track_settings: "TRACK_EMAIL_OPEN", send_as_plain_text: true, follow_up_percentage: 90, unsubscribe_text: "Click here to unsubscribe", stop_lead_settings: "REPLIED", sequences: [ { id: "seq_21", seq_number: 1, delay_days: 0, subject: "Compliance streamline for {{company_name}}", email_body: "

Hi {{first_name}}, wanted to share our automated compliance blueprint tailored for {{company_name}}.

", variant_distribution_percentage: 100, variants: [] } ], email_account_ids: ["acc_103"] }, { id: "camp_9903", name: "AI Tech Founders Pilot", status: "ACTIVE", created_at: "2026-08-01T09:15:00.000Z", lead_count: 2400, sent_count: 6100, open_count: 3890, reply_count: 310, bounce_count: 45, click_count: 820, timezone: "America/Los_Angeles", start_schedule: "09:00", end_schedule: "17:00", track_settings: "TRACK_EMAIL_OPEN_AND_CLICK", send_as_plain_text: false, follow_up_percentage: 100, unsubscribe_text: "Unsubscribe", stop_lead_settings: "REPLIED", sequences: [ { id: "seq_31", seq_number: 1, delay_days: 0, subject: "{{first_name}}, accelerating inference pipelines", email_body: "

Hi {{first_name}}, saw your launch on Product Hunt! Curious how {{company_name}} is handling model inference latency?

", variant_distribution_percentage: 100, variants: [] } ], email_account_ids: ["acc_101", "acc_102", "acc_104"] } ], leads: [ { id: "lead_1001", campaign_id: "camp_9901", first_name: "Sarah", last_name: "Jenkins", email: "sarah.jenkins@acmepartner.io", phone_number: "+1 415-555-0182", company_name: "Acme Partner Labs", website: "https://acmepartner.io", location: "San Francisco, CA", linkedin_profile: "https://linkedin.com/in/sarahjenkins-sample", status: "INTERESTED", open_count: 4, click_count: 2, created_at: "2026-07-16T11:20:00.000Z", custom_fields: { tech_stack: "Node/React", team_size: "45", funding_round: "Series B" } }, { id: "lead_1002", campaign_id: "camp_9901", first_name: "Marcus", last_name: "Vance", email: "m.vance@vanguardflow.co", phone_number: "+1 212-555-0199", company_name: "Vanguard Flow Systems", website: "https://vanguardflow.co", location: "New York, NY", linkedin_profile: "https://linkedin.com/in/marcusvance-sample", status: "MEETING_BOOKED", open_count: 6, click_count: 3, created_at: "2026-07-16T12:45:00.000Z", custom_fields: { tech_stack: "AWS/Python", team_size: "120", funding_round: "Series C" } }, { id: "lead_1003", campaign_id: "camp_9901", first_name: "Elena", last_name: "Rostova", email: "elena@cybercorebiotech.com", phone_number: "+44 20 7946 0912", company_name: "CyberCore Biotech", website: "https://cybercorebiotech.com", location: "London, UK", linkedin_profile: "https://linkedin.com/in/elenarostova", status: "REPLIED", open_count: 3, click_count: 1, created_at: "2026-07-17T09:10:00.000Z", custom_fields: { tech_stack: "NextJS", team_size: "80", funding_round: "Series A" } }, { id: "lead_1004", campaign_id: "camp_9902", first_name: "David", last_name: "Chen", email: "david.chen@horizonpay.net", phone_number: "+1 650-555-0144", company_name: "Horizon Pay", website: "https://horizonpay.net", location: "Palo Alto, CA", linkedin_profile: "https://linkedin.com/in/davidchen-sample", status: "NOT_INTERESTED", open_count: 1, click_count: 0, created_at: "2026-07-21T15:00:00.000Z", custom_fields: { tech_stack: "Go/Postgres", team_size: "200", funding_round: "Series D" } }, { id: "lead_1005", campaign_id: "camp_9903", first_name: "Amina", last_name: "Diallo", email: "amina@synapseai.tech", phone_number: "+1 312-555-0177", company_name: "Synapse AI Global", website: "https://synapseai.tech", location: "Chicago, IL", linkedin_profile: "https://linkedin.com/in/aminadiallo", status: "INTERESTED", open_count: 5, click_count: 4, created_at: "2026-08-02T10:14:00.000Z", custom_fields: { tech_stack: "PyTorch/Ray", team_size: "30", funding_round: "Seed" } } ], email_accounts: [ { id: "acc_101", from_name: "Alex Rivera", from_email: "alex@outbound-alchemist.io", provider: "GOOGLE", status: "CONNECTED", daily_limit: 50, sent_today: 34, warmup_enabled: true, warmup_reputation: "EXCELLENT", warmup_score: 98, warmup_daily_count: 25, ramp_day: 14, ramp_up_increment: 2, reply_rate_percentage: 45, campaigns_assigned: ["Enterprise SaaS Outbound Q3", "AI Tech Founders Pilot"], created_at: "2026-05-10T08:00:00.000Z" }, { id: "acc_102", from_name: "Alex Rivera (Secondary)", from_email: "alex.rivera@growthmatrix.cc", provider: "MICROSOFT", status: "CONNECTED", daily_limit: 45, sent_today: 28, warmup_enabled: true, warmup_reputation: "GOOD", warmup_score: 89, warmup_daily_count: 20, ramp_day: 9, ramp_up_increment: 3, reply_rate_percentage: 40, campaigns_assigned: ["Enterprise SaaS Outbound Q3", "AI Tech Founders Pilot"], created_at: "2026-06-01T08:00:00.000Z" }, { id: "acc_103", from_name: "Elena Rostova", from_email: "elena@fintechoutreach.com", provider: "SMTP", smtp_host: "mail.fintechoutreach.com", smtp_port: 587, status: "CONNECTED", daily_limit: 60, sent_today: 18, warmup_enabled: true, warmup_reputation: "EXCELLENT", warmup_score: 96, warmup_daily_count: 30, ramp_day: 22, ramp_up_increment: 2, reply_rate_percentage: 50, campaigns_assigned: ["Fintech Growth & Compliance Sequence"], created_at: "2026-06-15T08:00:00.000Z" }, { id: "acc_104", from_name: "Growth Ops Lead", from_email: "ops@aifoundryoutreach.io", provider: "GOOGLE", status: "RECONNECTING", daily_limit: 40, sent_today: 0, warmup_enabled: false, warmup_reputation: "POOR", warmup_score: 62, warmup_daily_count: 0, ramp_day: 1, ramp_up_increment: 1, reply_rate_percentage: 30, campaigns_assigned: ["AI Tech Founders Pilot"], created_at: "2026-07-28T08:00:00.000Z" } ], inbox: [ { id: "msg_501", campaign_id: "camp_9901", lead_id: "lead_1001", lead_name: "Sarah Jenkins", lead_email: "sarah.jenkins@acmepartner.io", company_name: "Acme Partner Labs", subject: "Re: Quick question regarding Acme Partner Labs's outbound infrastructure", category: "INTERESTED", unread: true, received_at: "2026-08-14T19:30:00.000Z", messages: [ { id: "m_sub_1", from: "alex@outbound-alchemist.io", to: "sarah.jenkins@acmepartner.io", direction: "OUTBOUND", timestamp: "2026-08-14T14:00:00.000Z", body_html: "

Hi Sarah, Noticed you are scaling your growth team at Acme Partner Labs. Are you currently looking to optimize your cold outreach deliverability and warmup automation?

" }, { id: "m_sub_2", from: "sarah.jenkins@acmepartner.io", to: "alex@outbound-alchemist.io", direction: "INBOUND", timestamp: "2026-08-14T19:30:00.000Z", body_html: "

Hi Alex,

Yes, perfect timing. We are actually evaluating mailbox warmup tools right now since our SDR team just doubled. Can you send over a brief demo or pricing overview?

Thanks,
Sarah Jenkins | Head of Growth

" } ] }, { id: "msg_502", campaign_id: "camp_9901", lead_id: "lead_1002", lead_name: "Marcus Vance", lead_email: "m.vance@vanguardflow.co", company_name: "Vanguard Flow Systems", subject: "Re: Quick question regarding Vanguard Flow Systems", category: "MEETING_BOOKED", unread: false, received_at: "2026-08-14T16:15:00.000Z", messages: [ { id: "m_sub_3", from: "alex@outbound-alchemist.io", to: "m.vance@vanguardflow.co", direction: "OUTBOUND", timestamp: "2026-08-13T10:00:00.000Z", body_html: "

Hey Marcus, We helped similar SaaS leaders double their positive response rates without hitting spam filters. Open to a 3-min loom?

" }, { id: "m_sub_4", from: "m.vance@vanguardflow.co", to: "alex@outbound-alchemist.io", direction: "INBOUND", timestamp: "2026-08-14T16:15:00.000Z", body_html: "

Alex, grabbed a slot on your calendar for Tuesday at 2 PM EST. Talk soon!

" } ] }, { id: "msg_503", campaign_id: "camp_9903", lead_id: "lead_1005", lead_name: "Amina Diallo", lead_email: "amina@synapseai.tech", company_name: "Synapse AI Global", subject: "Re: Amina, accelerating inference pipelines", category: "INTERESTED", unread: true, received_at: "2026-08-14T21:05:00.000Z", messages: [ { id: "m_sub_5", from: "ops@aifoundryoutreach.io", to: "amina@synapseai.tech", direction: "OUTBOUND", timestamp: "2026-08-14T15:00:00.000Z", body_html: "

Hi Amina, saw your launch on Product Hunt! Curious how Synapse AI Global is handling model inference latency?

" }, { id: "m_sub_6", from: "amina@synapseai.tech", to: "ops@aifoundryoutreach.io", direction: "INBOUND", timestamp: "2026-08-14T21:05:00.000Z", body_html: "

Thanks! We've built an in-house caching proxy, but always curious to learn about specialized acceleration clusters. Let's connect next week.

" } ] } ], webhooks: [ { id: "wh_801", name: "Slack Lead Alerts & Zapier Sync", webhook_url: "https://hooks.zapier.com/hooks/catch/912837/b8120a", event_types: ["REPLY", "LEAD_CATEGORY_UPDATED", "CAMPAIGN_COMPLETED"], campaign_id: null, status: "ACTIVE", last_triggered: "2026-08-14T21:05:12.000Z", created_at: "2026-06-20T10:00:00.000Z" }, { id: "wh_802", name: "HubSpot CRM Bi-directional Sync", webhook_url: "https://api.hubapi.com/webhooks/v3/custom-lead-sync", event_types: ["REPLY", "BOUNCE", "UNSUBSCRIBE", "LEAD_CATEGORY_UPDATED"], campaign_id: "camp_9901", status: "ACTIVE", last_triggered: "2026-08-14T19:30:22.000Z", created_at: "2026-07-01T12:00:00.000Z" } ], webhook_logs: [ { id: "whlog_1", webhook_id: "wh_801", event_type: "REPLY", status_code: 200, timestamp: "2026-08-14T21:05:12.000Z", payload_preview: { lead_email: "amina@synapseai.tech", category: "INTERESTED", sentiment: "positive" } }, { id: "whlog_2", webhook_id: "wh_802", event_type: "LEAD_CATEGORY_UPDATED", status_code: 200, timestamp: "2026-08-14T19:30:22.000Z", payload_preview: { lead_email: "sarah.jenkins@acmepartner.io", status: "INTERESTED" } } ], clients: [ { id: "cli_101", name: "Nexus AI Ventures", email: "growth@nexusventures.ai", company: "Nexus AI Ventures Inc.", campaigns_count: 2, leads_count: 3820, created_at: "2026-05-15T09:00:00.000Z" }, { id: "cli_102", name: "Apex Velocity B2B", email: "contact@apexvelocity.io", company: "Apex Velocity Marketing", campaigns_count: 1, leads_count: 1200, created_at: "2026-06-10T11:30:00.000Z" } ], block_list: { emails: [ { id: "bl_1", email: "competitor-bot@spamtrap.org", reason: "Spam trap detected", added_at: "2026-07-01T10:00:00.000Z" }, { id: "bl_2", email: "ceo@opt-out-forever.com", reason: "Direct legal opt-out", added_at: "2026-07-12T14:20:00.000Z" } ], domains: [ { id: "bld_1", domain: "mailinator.com", reason: "Disposable email service", added_at: "2026-06-10T09:00:00.000Z" }, { id: "bld_2", domain: "guerrillamail.com", reason: "Temporary inbox", added_at: "2026-06-11T11:00:00.000Z" }, { id: "bld_3", domain: "10minutemail.com", reason: "Temporary inbox", added_at: "2026-06-15T15:00:00.000Z" } ] }, billing: { credits: 0, auto_topup: { enabled: false, threshold: 500, amount: 10000 }, invoices: [] as any[], packages: [ { id: "pkg_2k", name: "2 000 cr", credits: 2000, price: 4.90, unit_price: 0.00245, features: ["Zero Expiry", "Verified results only consume credits"] }, { id: "pkg_10k", name: "10 000 cr", credits: 10000, price: 39.00, unit_price: 0.00390, features: ["Zero Expiry"] }, { id: "pkg_25k", name: "25 000 cr", credits: 25000, price: 59.00, unit_price: 0.00236, popular: true, features: ["Most Popular", "Zero Expiry"] }, { id: "pkg_50k", name: "50 000 cr", credits: 50000, price: 89.00, unit_price: 0.00178, popular: true, features: ["Most Popular", "Zero Expiry"] }, { id: "pkg_100k", name: "100 000 cr", credits: 100000, price: 149.00, unit_price: 0.00149, features: ["Zero Expiry"] }, { id: "pkg_500k", name: "500 000 cr", credits: 500000, price: 299.00, unit_price: 0.00060, features: ["Zero Expiry"] }, { id: "pkg_1m", name: "1 000 000 cr", credits: 1000000, price: 449.00, unit_price: 0.00045, features: ["Zero Expiry"] } ] } }; let stripeClient: any = null; function getStripe() { if (!stripeClient && process.env.STRIPE_SECRET_KEY) { import("stripe").then(({ default: Stripe }) => { stripeClient = new Stripe(process.env.STRIPE_SECRET_KEY as string); }); } return stripeClient; } async function startServer() { const app = express(); const PORT = Number(process.env.PORT) || 3000; app.use(cors({ origin: process.env.CORS_ORIGIN ? process.env.CORS_ORIGIN.split(',') : false, credentials: true })); app.use(morgan("dev")); app.use(express.json()); app.get(["/api/health", "/api/v1/health"], (req, res) => { res.json({ status: "ok", timestamp: new Date().toISOString(), uptime: process.uptime() }); }); app.get(["/api/ping", "/api/v1/ping"], (req, res) => { res.json({ pong: true, timestamp: new Date().toISOString() }); }); // Platform health probe (carried over from Module S prod) app.get("/api/health", (req, res) => { res.json({ status: "ok", platform: "BRIDGE Modules", modules: ["e", "s"], timestamp: new Date().toISOString() }); }); // Helper to check if real Smartlead API call should be attempted const shouldProxyToSmartlead = (apiKey: string | undefined) => { return Boolean(apiKey && apiKey.length > 10 && !apiKey.startsWith("demo_") && !apiKey.startsWith("mock_")); }; // ========================================== // MODULE 1: CAMPAIGNS API // ========================================== app.get("/api/campaigns", async (req, res) => { const apiKey = req.headers["x-api-key"] as string; if (shouldProxyToSmartlead(apiKey)) { try { const response = await axios.get("https://server.smartlead.ai/api/v1/campaigns", { params: { ...req.query, api_key: apiKey }, timeout: 8000 }); return res.json(response.data); } catch (err: any) { console.warn("Smartlead API live proxy failed, falling back to database mode:", err.message); } } return res.json(mockDb.campaigns); }); app.post("/api/campaigns", async (req, res) => { const apiKey = req.headers["x-api-key"] as string; if (shouldProxyToSmartlead(apiKey)) { try { const response = await axios.post("https://server.smartlead.ai/api/v1/campaigns", req.body, { params: { api_key: apiKey }, timeout: 8000 }); return res.status(201).json(response.data); } catch (err: any) { console.warn("Live create campaign failed, recording in local database:", err.message); } } const newCampaign = { id: "camp_" + Math.random().toString(36).substring(2, 9), name: req.body.name || "Untitled Campaign", status: "PAUSED", created_at: new Date().toISOString(), lead_count: 0, sent_count: 0, open_count: 0, reply_count: 0, bounce_count: 0, click_count: 0, timezone: req.body.timezone || "America/New_York", start_schedule: req.body.start_schedule || "09:00", end_schedule: req.body.end_schedule || "17:00", track_settings: req.body.track_settings || "TRACK_EMAIL_OPEN", send_as_plain_text: Boolean(req.body.send_as_plain_text), follow_up_percentage: req.body.follow_up_percentage || 80, unsubscribe_text: req.body.unsubscribe_text || "Unsubscribe", stop_lead_settings: req.body.stop_lead_settings || "REPLIED", sequences: [ { id: "seq_" + Math.random().toString(36).substring(2, 7), seq_number: 1, delay_days: 0, subject: req.body.initial_subject || "Connecting with {{first_name}}", email_body: req.body.initial_body || "

Hi {{first_name}}, let's connect!

", variant_distribution_percentage: 100, variants: [] } ], email_account_ids: req.body.email_account_ids || [] }; mockDb.campaigns.unshift(newCampaign); return res.status(201).json(newCampaign); }); app.get("/api/campaigns/:id", (req, res) => { const campaign = mockDb.campaigns.find(c => c.id === req.params.id); if (!campaign) return res.status(404).json({ error: "Campaign not found" }); return res.json(campaign); }); app.post("/api/campaigns/:id", (req, res) => { const index = mockDb.campaigns.findIndex(c => c.id === req.params.id); if (index === -1) return res.status(404).json({ error: "Campaign not found" }); mockDb.campaigns[index] = { ...mockDb.campaigns[index], ...req.body }; return res.json(mockDb.campaigns[index]); }); app.delete("/api/campaigns/:id", (req, res) => { mockDb.campaigns = mockDb.campaigns.filter(c => c.id !== req.params.id); return res.json({ success: true, message: "Campaign deleted successfully" }); }); app.post("/api/campaigns/:id/status", (req, res) => { const { status } = req.body; // START / PAUSE / STOP const campaign = mockDb.campaigns.find(c => c.id === req.params.id); if (!campaign) return res.status(404).json({ error: "Campaign not found" }); campaign.status = status === "START" ? "ACTIVE" : status === "PAUSE" ? "PAUSED" : "STOPPED"; return res.json({ success: true, status: campaign.status, campaign }); }); app.post("/api/campaigns/:id/schedule", (req, res) => { const campaign = mockDb.campaigns.find(c => c.id === req.params.id); if (!campaign) return res.status(404).json({ error: "Campaign not found" }); campaign.start_schedule = req.body.start_schedule || campaign.start_schedule; campaign.end_schedule = req.body.end_schedule || campaign.end_schedule; campaign.timezone = req.body.timezone || campaign.timezone; return res.json({ success: true, campaign }); }); app.get("/api/campaigns/:id/sequences", (req, res) => { const campaign = mockDb.campaigns.find(c => c.id === req.params.id); if (!campaign) return res.status(404).json({ error: "Campaign not found" }); return res.json(campaign.sequences || []); }); app.post("/api/campaigns/:id/sequences", (req, res) => { const campaign = mockDb.campaigns.find(c => c.id === req.params.id); if (!campaign) return res.status(404).json({ error: "Campaign not found" }); campaign.sequences = req.body.sequences || []; return res.json({ success: true, sequences: campaign.sequences }); }); app.get("/api/campaigns/:id/email-accounts", (req, res) => { const campaign = mockDb.campaigns.find(c => c.id === req.params.id); if (!campaign) return res.status(404).json({ error: "Campaign not found" }); const accounts = mockDb.email_accounts.filter(a => campaign.email_account_ids?.includes(a.id)); return res.json(accounts); }); app.post("/api/campaigns/:id/email-accounts", (req, res) => { const campaign = mockDb.campaigns.find(c => c.id === req.params.id); if (!campaign) return res.status(404).json({ error: "Campaign not found" }); const { email_account_id } = req.body; if (!campaign.email_account_ids) campaign.email_account_ids = []; if (!campaign.email_account_ids.includes(email_account_id)) { campaign.email_account_ids.push(email_account_id); } return res.json({ success: true, email_account_ids: campaign.email_account_ids }); }); app.delete("/api/campaigns/:id/email-accounts/:eid", (req, res) => { const campaign = mockDb.campaigns.find(c => c.id === req.params.id); if (!campaign) return res.status(404).json({ error: "Campaign not found" }); campaign.email_account_ids = (campaign.email_account_ids || []).filter(id => id !== req.params.eid); return res.json({ success: true, email_account_ids: campaign.email_account_ids }); }); app.get("/api/campaigns/:id/analytics", (req, res) => { const campaign = mockDb.campaigns.find(c => c.id === req.params.id); if (!campaign) return res.status(404).json({ error: "Campaign not found" }); return res.json({ sent: campaign.sent_count, opens: campaign.open_count, replies: campaign.reply_count, bounces: campaign.bounce_count, clicks: campaign.click_count, open_rate: ((campaign.open_count / (campaign.sent_count || 1)) * 100).toFixed(1), reply_rate: ((campaign.reply_count / (campaign.sent_count || 1)) * 100).toFixed(1), bounce_rate: ((campaign.bounce_count / (campaign.sent_count || 1)) * 100).toFixed(1) }); }); app.get("/api/campaigns/:id/analytics-by-date", (req, res) => { const days = 14; const history = []; const now = new Date(); for (let i = days; i >= 0; i--) { const d = new Date(now.getTime() - i * 24 * 60 * 60 * 1000); const dayLabel = d.toLocaleDateString("en-US", { month: "short", day: "numeric" }); history.push({ date: dayLabel, sent: Math.floor(120 + Math.random() * 80), opens: Math.floor(65 + Math.random() * 40), clicks: Math.floor(18 + Math.random() * 15), replies: Math.floor(8 + Math.random() * 10), bounces: Math.floor(1 + Math.random() * 3) }); } return res.json(history); }); app.get("/api/campaigns/:id/leads-export", (req, res) => { const campaignLeads = mockDb.leads.filter(l => l.campaign_id === req.params.id); let csv = "first_name,last_name,email,company_name,status,open_count,reply_count\n"; campaignLeads.forEach(l => { csv += `"${l.first_name}","${l.last_name}","${l.email}","${l.company_name}","${l.status}",${l.open_count},${l.click_count}\n`; }); res.setHeader("Content-Type", "text/csv"); res.setHeader("Content-Disposition", `attachment; filename=leads-${req.params.id}.csv`); return res.send(csv); }); // ========================================== // MODULE 2: LEADS API // ========================================== app.get("/api/campaigns/:id/leads", (req, res) => { const leads = mockDb.leads.filter(l => l.campaign_id === req.params.id); return res.json(leads); }); app.post("/api/campaigns/:id/leads", (req, res) => { const leadsToAdd = Array.isArray(req.body) ? req.body : req.body.leads || [req.body]; const created = leadsToAdd.map((item: any) => { const newLead = { id: "lead_" + Math.random().toString(36).substring(2, 9), campaign_id: req.params.id, first_name: item.first_name || "", last_name: item.last_name || "", email: item.email || "lead@sample.io", phone_number: item.phone_number || "", company_name: item.company_name || "", website: item.website || "", location: item.location || "", linkedin_profile: item.linkedin_profile || "", status: item.status || "INTERESTED", open_count: 0, click_count: 0, created_at: new Date().toISOString(), custom_fields: item.custom_fields || {} }; mockDb.leads.unshift(newLead); return newLead; }); const campaign = mockDb.campaigns.find(c => c.id === req.params.id); if (campaign) campaign.lead_count += created.length; return res.status(201).json({ success: true, count: created.length, leads: created }); }); app.get("/api/leads/search", (req, res) => { const query = (req.query.q as string || "").toLowerCase(); const status = req.query.status as string; let results = mockDb.leads; if (query) { results = results.filter(l => l.first_name.toLowerCase().includes(query) || l.last_name.toLowerCase().includes(query) || l.email.toLowerCase().includes(query) || l.company_name.toLowerCase().includes(query) ); } if (status && status !== "ALL") { results = results.filter(l => l.status === status); } return res.json(results); }); app.post("/api/campaigns/:id/leads/status", (req, res) => { const { lead_id, status } = req.body; const lead = mockDb.leads.find(l => l.id === lead_id); if (!lead) return res.status(404).json({ error: "Lead not found" }); lead.status = status; return res.json({ success: true, lead }); }); app.delete("/api/campaigns/:id/leads/:lead_id", (req, res) => { mockDb.leads = mockDb.leads.filter(l => l.id !== req.params.lead_id); const campaign = mockDb.campaigns.find(c => c.id === req.params.id); if (campaign && campaign.lead_count > 0) campaign.lead_count--; return res.json({ success: true }); }); // Blocklist routes app.get("/api/leads/block-list", (req, res) => res.json(mockDb.block_list.emails)); app.post("/api/leads/block-list", (req, res) => { const item = { id: "bl_" + Date.now(), email: req.body.email, reason: req.body.reason || "Manual add", added_at: new Date().toISOString() }; mockDb.block_list.emails.unshift(item); res.status(201).json(item); }); app.delete("/api/leads/block-list/:id", (req, res) => { mockDb.block_list.emails = mockDb.block_list.emails.filter(e => e.id !== req.params.id && e.email !== req.params.id); res.json({ success: true }); }); app.get("/api/leads/domain-block-list", (req, res) => res.json(mockDb.block_list.domains)); app.post("/api/leads/domain-block-list", (req, res) => { const item = { id: "bld_" + Date.now(), domain: req.body.domain, reason: req.body.reason || "Manual add", added_at: new Date().toISOString() }; mockDb.block_list.domains.unshift(item); res.status(201).json(item); }); app.delete("/api/leads/domain-block-list/:id", (req, res) => { mockDb.block_list.domains = mockDb.block_list.domains.filter(d => d.id !== req.params.id && d.domain !== req.params.id); res.json({ success: true }); }); // ========================================== // MODULE 3: EMAIL ACCOUNTS API // ========================================== app.get("/api/email-accounts", (req, res) => res.json(mockDb.email_accounts)); app.post("/api/email-accounts", (req, res) => { const newAcc = { id: "acc_" + Math.random().toString(36).substring(2, 8), from_name: req.body.from_name || "Outbound Rep", from_email: req.body.from_email || "rep@sampledomain.com", provider: req.body.provider || "SMTP", smtp_host: req.body.smtp_host, smtp_port: req.body.smtp_port, status: "CONNECTED", daily_limit: req.body.max_email_per_day || 50, sent_today: 0, warmup_enabled: true, warmup_reputation: "GOOD", warmup_score: 85, warmup_daily_count: 10, ramp_day: 1, ramp_up_increment: 2, reply_rate_percentage: 40, campaigns_assigned: [], created_at: new Date().toISOString() }; mockDb.email_accounts.push(newAcc); res.status(201).json(newAcc); }); app.post("/api/email-accounts/reconnect", (req, res) => { const { account_id } = req.body; const acc = mockDb.email_accounts.find(a => a.id === account_id); if (acc) acc.status = "CONNECTED"; res.json({ success: true, message: "Account reconnected successfully", account: acc }); }); app.delete("/api/email-accounts/:id", (req, res) => { mockDb.email_accounts = mockDb.email_accounts.filter(a => a.id !== req.params.id); res.json({ success: true }); }); // ========================================== // MODULE 4: EMAIL WARMUP API // ========================================== app.post("/api/email-accounts/:id/warmup/enable", (req, res) => { const acc = mockDb.email_accounts.find(a => a.id === req.params.id); if (!acc) return res.status(404).json({ error: "Account not found" }); acc.warmup_enabled = true; res.json({ success: true, account: acc }); }); app.post("/api/email-accounts/:id/warmup/disable", (req, res) => { const acc = mockDb.email_accounts.find(a => a.id === req.params.id); if (!acc) return res.status(404).json({ error: "Account not found" }); acc.warmup_enabled = false; res.json({ success: true, account: acc }); }); app.get("/api/email-accounts/:id/warmup/stats", (req, res) => { const acc = mockDb.email_accounts.find(a => a.id === req.params.id); if (!acc) return res.status(404).json({ error: "Account not found" }); res.json({ score: acc.warmup_score, reputation: acc.warmup_reputation, sent_warmup: acc.warmup_daily_count, received_warmup: Math.floor(acc.warmup_daily_count * 0.45), spam_rescued: 2, ramp_day: acc.ramp_day, history: [ { day: "Day 1", score: 70 }, { day: "Day 3", score: 78 }, { day: "Day 7", score: 85 }, { day: "Day 10", score: 92 }, { day: "Day 14", score: acc.warmup_score } ] }); }); app.post("/api/email-accounts/:id/warmup/settings", (req, res) => { const acc = mockDb.email_accounts.find(a => a.id === req.params.id); if (!acc) return res.status(404).json({ error: "Account not found" }); acc.ramp_up_increment = req.body.ramp_up_increment || acc.ramp_up_increment; acc.reply_rate_percentage = req.body.reply_rate_percentage || acc.reply_rate_percentage; res.json({ success: true, account: acc }); }); // ========================================== // MODULE 5: UNIFIED INBOX API // ========================================== app.get("/api/inbox", (req, res) => { const { category, campaign_id } = req.query; let threads = mockDb.inbox; if (category && category !== "ALL") { threads = threads.filter(t => t.category === category); } if (campaign_id) { threads = threads.filter(t => t.campaign_id === campaign_id); } res.json(threads); }); app.get("/api/inbox/unread-count", (req, res) => { const unread = mockDb.inbox.filter(t => t.unread).length; res.json({ count: unread }); }); app.post("/api/campaigns/:id/reply-email-thread", (req, res) => { const { thread_id, reply_body } = req.body; const thread = mockDb.inbox.find(t => t.id === thread_id || t.campaign_id === req.params.id); if (thread) { thread.unread = false; thread.messages.push({ id: "m_rep_" + Date.now(), from: "alex@outbound-alchemist.io", to: thread.lead_email, direction: "OUTBOUND", timestamp: new Date().toISOString(), body_html: `

${reply_body}

` }); return res.json({ success: true, message: "Reply sent successfully", thread }); } res.json({ success: true, message: "Reply delivered" }); }); app.post("/api/inbox/categorize", (req, res) => { const { thread_id, category } = req.body; const thread = mockDb.inbox.find(t => t.id === thread_id); if (thread) { thread.category = category; const lead = mockDb.leads.find(l => l.email === thread.lead_email); if (lead) lead.status = category; } res.json({ success: true, category }); }); // ========================================== // MODULE 6: WEBHOOKS API // ========================================== app.get("/api/webhooks", (req, res) => res.json(mockDb.webhooks)); app.post("/api/webhooks", (req, res) => { const newWh = { id: "wh_" + Math.random().toString(36).substring(2, 8), name: req.body.name || "Custom Webhook Endpoint", webhook_url: req.body.webhook_url || "https://api.domain.com/webhook", event_types: req.body.event_types || ["REPLY"], campaign_id: req.body.campaign_id || null, status: "ACTIVE", last_triggered: null, created_at: new Date().toISOString() }; mockDb.webhooks.unshift(newWh); res.status(201).json(newWh); }); app.delete("/api/webhooks/:id", (req, res) => { mockDb.webhooks = mockDb.webhooks.filter(w => w.id !== req.params.id); res.json({ success: true }); }); app.post("/api/webhooks/:id/test", (req, res) => { const wh = mockDb.webhooks.find(w => w.id === req.params.id); if (!wh) return res.status(404).json({ error: "Webhook not found" }); const logItem = { id: "whlog_" + Date.now(), webhook_id: wh.id, event_type: wh.event_types[0] || "REPLY", status_code: 200, timestamp: new Date().toISOString(), payload_preview: { lead_email: "test.lead@domain.com", category: "INTERESTED", sentiment: "positive" } } as const; mockDb.webhook_logs.unshift(logItem); wh.last_triggered = new Date().toISOString(); res.json({ success: true, message: "Test payload sent to endpoint", log: logItem }); }); app.get("/api/webhooks/logs", (req, res) => res.json(mockDb.webhook_logs)); // ========================================== // MODULE 7: ANALYTICS API // ========================================== app.get("/api/analytics/campaigns", (req, res) => { const totalSent = mockDb.campaigns.reduce((acc, c) => acc + c.sent_count, 0); const totalOpens = mockDb.campaigns.reduce((acc, c) => acc + c.open_count, 0); const totalReplies = mockDb.campaigns.reduce((acc, c) => acc + c.reply_count, 0); const totalBounces = mockDb.campaigns.reduce((acc, c) => acc + c.bounce_count, 0); const totalClicks = mockDb.campaigns.reduce((acc, c) => acc + c.click_count, 0); const totalLeads = mockDb.campaigns.reduce((acc, c) => acc + c.lead_count, 0); res.json({ total_campaigns: mockDb.campaigns.length, total_leads: totalLeads, total_sent: totalSent, total_opens: totalOpens, total_replies: totalReplies, total_bounces: totalBounces, total_clicks: totalClicks, open_rate: ((totalOpens / (totalSent || 1)) * 100).toFixed(1), reply_rate: ((totalReplies / (totalSent || 1)) * 100).toFixed(1), click_rate: ((totalClicks / (totalSent || 1)) * 100).toFixed(1), bounce_rate: ((totalBounces / (totalSent || 1)) * 100).toFixed(1) }); }); // ========================================== // MODULE 8: CLIENT MANAGEMENT API // ========================================== app.get("/api/clients", (req, res) => res.json(mockDb.clients)); // ========================================== // MODULE 9: BILLING & STRIPE API // ========================================== app.get("/api/billing", (req, res) => res.json(mockDb.billing)); app.post("/api/billing/purchase", (req, res) => { const { package_id } = req.body; const pkg = mockDb.billing.packages.find(p => p.id === package_id); if (!pkg) return res.status(404).json({ error: "Package not found" }); // In a real app, this would be handled via Stripe Webhook after payment // For this environment, we'll simulate the credit addition mockDb.billing.credits += pkg.credits; const invoice = { id: "inv_" + Math.random().toString(36).substring(2, 9), description: `${pkg.name} Package Purchase`, credits: pkg.credits, amount: pkg.price, status: "PAID", created_at: new Date().toISOString() }; mockDb.billing.invoices.unshift(invoice); res.json({ success: true, message: `Successfully added ${pkg.credits} credits.`, credits: mockDb.billing.credits }); }); app.post("/api/billing/autotopup", (req, res) => { mockDb.billing.auto_topup = { ...mockDb.billing.auto_topup, ...req.body }; res.json({ success: true, auto_topup: mockDb.billing.auto_topup }); }); app.post("/api/billing/create-checkout-session", async (req, res) => { const { package_id } = req.body; const pkg = mockDb.billing.packages.find(p => p.id === package_id); if (!pkg) return res.status(404).json({ error: "Package not found" }); const stripe = getStripe(); if (!stripe) { // Fallback for demo mode if no key is set return res.json({ url: `${req.headers.origin}/pricing?success=true&package_id=${package_id}`, mode: "demo" }); } try { const session = await stripe.checkout.sessions.create({ payment_method_types: ['card'], line_items: [{ price_data: { currency: 'usd', product_data: { name: `BRIDGEModulE - ${pkg.name}`, description: `${pkg.credits.toLocaleString()} credits for email verification.`, }, unit_amount: Math.round(pkg.price * 100), }, quantity: 1, }], mode: 'payment', success_url: `${req.headers.origin}/pricing?success=true&session_id={CHECKOUT_SESSION_ID}`, cancel_url: `${req.headers.origin}/pricing?canceled=true`, }); res.json({ url: session.url }); } catch (error: any) { res.status(500).json({ error: error.message }); } }); app.post("/api/ai/completion", async (req, res) => { try { const { prompt } = req.body; if (!prompt) { return res.status(400).json({ error: "Prompt is required" }); } const response = await getAiCompletionServer(prompt); res.json({ response }); } catch (error) { res.status(500).json({ error: "Failed to get AI completion" }); } }); app.post("/api/clients", (req, res) => { const newClient = { id: "cli_" + Math.random().toString(36).substring(2, 7), name: req.body.name || "New Client", email: req.body.email || "client@company.com", company: req.body.company || "Client Company Ltd", campaigns_count: 0, leads_count: 0, created_at: new Date().toISOString() }; mockDb.clients.push(newClient); res.status(201).json(newClient); }); app.delete("/api/clients/:id", (req, res) => { mockDb.clients = mockDb.clients.filter(c => c.id !== req.params.id); res.json({ success: true }); }); // Proxy Catch-All for any other direct Smartlead API calls app.use("/api", async (req, res) => { const apiKey = req.headers["x-api-key"] as string; if (!apiKey) { return res.status(401).json({ error: "Missing x-api-key header" }); } try { const targetUrl = `https://server.smartlead.ai/api/v1${req.path}`; const response = await axios({ method: req.method, url: targetUrl, data: Object.keys(req.body).length > 0 ? req.body : undefined, params: { ...req.query, api_key: apiKey }, timeout: 10000 }); res.status(response.status).json(response.data); } catch (error: any) { if (error.response) { res.status(error.response.status).json(error.response.data); } else { res.status(500).json({ error: "Proxy connection error", details: error.message }); } } }); // Vite development middleware or production static serving if (process.env.NODE_ENV !== "production") { const { createServer: createViteServer } = await import("vite"); const vite = await createViteServer({ server: { middlewareMode: true }, appType: "spa", }); app.use(vite.middlewares); } else { const distPath = path.join(process.cwd(), "dist"); app.use(express.static(distPath)); app.get("*", (req, res) => { res.sendFile(path.join(distPath, "index.html")); }); } app.listen(PORT, "0.0.0.0", () => { console.log(`Smartlead Command Hub Server listening on http://0.0.0.0:${PORT}`); }); } startServer();