VIDEO
Prerequisites
A Next.js application (version 13 or higher recommended)
Your SixtyFour AI API credentials:
SIXTYFOUR_INBOUND_API_KEY
SIXTYFOUR_ORG_ID
Step 1: Set Up Environment Variables
First, add your SixtyFour AI credentials to your .env.local
file:
SIXTYFOUR_INBOUND_API_KEY = your_api_key_here
SIXTYFOUR_ORG_ID = your_organization_id_here
NEXT_PUBLIC_API_ENDPOINT = https://api.inbound.sixtyfour.ai/enrich-lead
Once you have an active subscription, you will see your API Key in the api-keys tab like this:
Your org-id is visible on the sidebar when you hover over your profile picture.
Note : While we’re using NEXT_PUBLIC_
prefix for simplicity in this example, in production you should handle the API key server-side only.
Step 2: Create the API Route
Create a new API route in your Next.js application at app/api/interestForm/route.ts
:
import { NextResponse } from 'next/server' ;
export async function POST ( request : Request ) {
try {
const formData = await request . json ();
// Generate unique IDs for tracking
const submission_id = Math . random (). toString ( 36 ). substring ( 2 , 8 );
const respondent_id = Math . random (). toString ( 36 ). substring ( 2 , 8 );
// These coould be any fields of your choice
// We recommend collecting atleast the name + company email + company name for best results
const payload = {
lead_data: {
submission_id ,
respondent_id ,
submitted_at: new Date (). toISOString (),
name: formData . name ,
email: formData . email ,
phone_number: null ,
inquiry: null ,
upload_link: null ,
role: null ,
role_other: null ,
heard_about_us: "Website Form" ,
heard_about_us_other: null ,
terms_agreed: null
},
// Make sure to pass this
customer_id: process . env . SIXTYFOUR_ORG_ID
};
const response = await fetch ( process . env . NEXT_PUBLIC_API_ENDPOINT ! , {
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
'x-api-key' : process . env . SIXTYFOUR_INBOUND_API_KEY !
},
body: JSON . stringify ( payload )
});
if ( ! response . ok ) {
const errorData = await response . json (). catch (() => ({}));
const statusCode = response . status ;
throw new Error ( `Failed to submit lead: API responded with status ${ statusCode } . ${ JSON . stringify ( errorData ) } ` );
}
return NextResponse . json ({ success: true });
} catch ( error ) {
console . error ( 'Error submitting lead:' , error );
return NextResponse . json (
{ error: 'Failed to submit lead' },
{ status: 500 }
);
}
}
Create a new component for your lead capture form. Here’s an example using React and Shadcn UI:
'use client'
import { useState , useEffect } from 'react'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { Card } from '@/components/ui/card'
import { CheckCircle } from 'lucide-react'
export default function LeadCaptureForm () {
const [ isSubmitting , setIsSubmitting ] = useState ( false )
const [ isSubmitted , setIsSubmitted ] = useState ( false )
const [ formDisabled , setFormDisabled ] = useState ( false )
// Check if form was already submitted in this session
useEffect (() => {
const hasSubmitted = sessionStorage . getItem ( 'formSubmitted' ) === 'true'
if ( hasSubmitted ) {
setFormDisabled ( true )
setIsSubmitted ( true )
}
}, [])
const handleSubmit = async ( e : React . FormEvent < HTMLFormElement >) => {
e . preventDefault ();
setIsSubmitting ( true );
const form = e . currentTarget ;
const formData = {
name: ( form . elements . namedItem ( 'name' ) as HTMLInputElement ). value ,
email: ( form . elements . namedItem ( 'email' ) as HTMLInputElement ). value ,
company: ( form . elements . namedItem ( 'company' ) as HTMLInputElement ). value ,
};
try {
const response = await fetch ( '/api/interestForm' , {
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
},
body: JSON . stringify ( formData ),
});
if ( ! response . ok ) {
throw new Error ( 'Submission failed' );
}
// Clear form and update state
form . reset ();
setIsSubmitted ( true );
setFormDisabled ( true );
sessionStorage . setItem ( 'formSubmitted' , 'true' );
} catch ( error ) {
console . error ( 'Error:' , error );
} finally {
setIsSubmitting ( false );
}
};
return (
< Card className = "mx-auto max-w-lg p-8 shadow-md" >
< form onSubmit = { handleSubmit } className = "space-y-6" >
< div className = "space-y-3" >
< Label htmlFor = "name" > Full name </ Label >
< Input type = "text" id = "name" required disabled = { formDisabled } />
</ div >
< div className = "space-y-3" >
< Label htmlFor = "email" > Work Email </ Label >
< Input type = "email" id = "email" required disabled = { formDisabled } />
</ div >
< div className = "space-y-3" >
< Label htmlFor = "company" > Company </ Label >
< Input type = "text" id = "company" required disabled = { formDisabled } />
</ div >
< Button
type = "submit"
className = "w-full bg-gradient-to-r from-[#5FA5F9] to-[#2463EB] hover:opacity-90 hover:shadow-lg"
disabled = {isSubmitting || formDisabled }
>
{ isSubmitting ? (
< span className = "flex items-center justify-center" >
< svg className = "animate-spin -ml-1 mr-2 h-4 w-4 text-white" xmlns = "http://www.w3.org/2000/svg" fill = "none" viewBox = "0 0 24 24" >
< circle className = "opacity-25" cx = "12" cy = "12" r = "10" stroke = "currentColor" strokeWidth = "4" > </ circle >
< path className = "opacity-75" fill = "currentColor" d = "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" > </ path >
</ svg >
Submitting ...
</ span >
) : isSubmitted ? (
< span className = "flex items-center justify-center" >
< CheckCircle className = "mr-2 h-4 w-4" />
Submitted !
</ span >
) : (
" Talk to Sales "
)}
</ Button >
</ form >
</ Card >
);
}
Step 4: Add the Form to Your Page
Import and use the LeadCaptureForm
component in your page:
import LeadCaptureForm from '@/components/LeadCaptureForm'
export default function ContactPage () {
return (
< section className = "py-16" >
< div className = "mx-auto max-w-3xl px-6" >
< h2 className = "text-center text-4xl font-semibold" >
Ready to discover prospects your competitors can 't see ?
</ h2 >
< p className = "mt-4 text-center" >
If traditional lead sources aren 't delivering the quality or quantity of prospects you need, we' d be glad to explore how our approach might help .
</ p >
< div className = "mt-12" >
< LeadCaptureForm />
</ div >
</ div >
</ section >
);
}
How It Works
When a user submits the form, the data is sent to your Next.js API route
The API route adds tracking information and forwards the data to SixtyFour AI
SixtyFour AI processes the lead and:
If qualified, sends an enriched profile to your email within ~60 seconds
All leads (qualified or not) appear on your SixtyFour dashboard
The form prevents duplicate submissions using session storage
Best Practices
Security : In production, consider moving the API key to server-side only
Error Handling : Implement proper error messages for users
Validation : Add client-side validation before submission
Loading States : Show appropriate loading states during submission
Success States : Provide clear feedback when submission is successful
Troubleshooting
If you encounter issues:
Check your environment variables are correctly set
Verify the API endpoint is correct
Ensure your API key has the necessary permissions
Check the browser console and server logs for errors
Contact support at saarth@sixtyfour.ai for assistance