import express from 'express'; const app = express(); app.use(express.json()); const TWENTY_CRM_URL = process.env.TWENTY_CRM_URL || 'https://crm.ai-impress.com'; const TWENTY_CRM_API_KEY = process.env.TWENTY_CRM_API_KEY || ''; async function createLeadInCRM({ fullName, workEmail, companyName, jobTitle, phoneNumber, need, source }) { if (!TWENTY_CRM_API_KEY || !workEmail) return; const headers = { Authorization: `Bearer ${TWENTY_CRM_API_KEY}`, 'Content-Type': 'application/json' }; try { // Split name const parts = fullName.trim().split(/\s+/); const firstName = parts[0] || ''; const lastName = parts.slice(1).join(' ') || ''; // Create or find company let companyId = null; if (companyName) { const compRes = await fetch(`${TWENTY_CRM_URL}/rest/companies`, { headers, method: 'GET' }); // Search not reliable, just create const createComp = await fetch(`${TWENTY_CRM_URL}/rest/companies`, { method: 'POST', headers, body: JSON.stringify({ name: companyName }), }); if (createComp.status === 201) { const cd = await createComp.json(); companyId = cd.data?.createCompany?.id; } } // Create person const personBody = { name: { firstName, lastName }, emails: { primaryEmail: workEmail, additionalEmails: [] }, }; if (companyId) personBody.companyId = companyId; if (jobTitle) personBody.jobTitle = jobTitle; if (phoneNumber) personBody.phones = { primaryPhoneNumber: phoneNumber, primaryPhoneCountryCode: '', primaryPhoneCallingCode: '', additionalPhones: [], }; const personRes = await fetch(`${TWENTY_CRM_URL}/rest/people`, { method: 'POST', headers, body: JSON.stringify(personBody), }); if (personRes.status === 201) { const pd = await personRes.json(); const personId = pd.data?.createPerson?.id; // Create note if (personId && need) { const noteRes = await fetch(`${TWENTY_CRM_URL}/rest/notes`, { method: 'POST', headers, body: JSON.stringify({ title: `${source}: ${need}` }), }); if (noteRes.status === 201) { const nd = await noteRes.json(); const noteId = nd.data?.createNote?.id; if (noteId) { await fetch(`${TWENTY_CRM_URL}/rest/noteTargets`, { method: 'POST', headers, body: JSON.stringify({ noteId, personId }), }); } } } console.log(`CRM lead created: ${personId} (${fullName})`); // Create opportunity in NEW stage const oppBody = { name: `${fullName} — ${(need || 'Contact form').substring(0, 50)}`, stage: 'NEW' }; if (companyId) oppBody.companyId = companyId; if (personId) oppBody.pointOfContactId = personId; await fetch(`${TWENTY_CRM_URL}/rest/opportunities`, { method: 'POST', headers, body: JSON.stringify(oppBody), }); } } catch (err) { console.error('CRM error:', err.message); } } app.post('/api/contact', async (req, res) => { const { fullName, workEmail, companyName, jobTitle, automationNeed, phoneNumber } = req.body; if (!fullName || !workEmail) { return res.status(400).json({ error: 'Missing required fields' }); } try { const response = await fetch('https://api.resend.com/emails', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.RESEND_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ from: 'AImpress Website ', to: ['hello@ai-impress.com'], subject: `New lead: ${fullName} — ${companyName || 'N/A'}`, html: `

New Contact Form Submission

Name: ${fullName}

Email: ${workEmail}

Company: ${companyName || 'N/A'}

Job Title: ${jobTitle || 'N/A'}

Automation Need: ${automationNeed || 'N/A'}

Phone: ${phoneNumber || 'N/A'}

`, }), }); if (!response.ok) { const err = await response.text(); console.error('Resend error:', err); return res.status(502).json({ error: 'Email delivery failed' }); } // Create lead in CRM (async, don't block response) createLeadInCRM({ fullName, workEmail, companyName, jobTitle, phoneNumber, need: automationNeed, source: 'Contact form' }); res.json({ ok: true }); } catch (err) { console.error('Email error:', err); res.status(500).json({ error: 'Internal error' }); } }); app.post('/api/quote', async (req, res) => { const { fullName, workEmail, companyName, jobTitle, phoneNumber, service, projectDescription } = req.body; if (!fullName || !workEmail || !service || !projectDescription) { return res.status(400).json({ error: 'Missing required fields' }); } try { const response = await fetch('https://api.resend.com/emails', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.RESEND_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ from: 'AImpress Website ', to: ['hello@ai-impress.com'], subject: `Quote request: ${fullName} — ${service}`, html: `

New Quote Request

Name: ${fullName}

Email: ${workEmail}

Company: ${companyName || 'N/A'}

Job Title: ${jobTitle || 'N/A'}

Phone: ${phoneNumber || 'N/A'}


Service: ${service}

Project Description:

${projectDescription.replace(/\n/g, '
')}

`, }), }); if (!response.ok) { const err = await response.text(); console.error('Resend error:', err); return res.status(502).json({ error: 'Email delivery failed' }); } // Create lead in CRM (async, don't block response) createLeadInCRM({ fullName, workEmail, companyName, jobTitle, phoneNumber, need: `${service}: ${projectDescription}`, source: 'Quote request' }); res.json({ ok: true }); } catch (err) { console.error('Email error:', err); res.status(500).json({ error: 'Internal error' }); } }); app.listen(3001, () => console.log('Email API listening on :3001'));