Reply.io is a multichannel sales engagement platform built for automated email, LinkedIn, SMS, and call sequences. When you connect it to GitLeads, every developer who stars a tracked repo or matches a keyword on GitHub can be automatically enrolled in a Reply.io sequence — enriched with their GitHub profile, bio, company, top languages, and the exact signal that triggered the lead.
Why Reply.io + GitLeads?
Most Reply.io users import contacts from a CSV or CRM. GitLeads gives you a live feed of high-intent developer leads sourced directly from GitHub activity — no cold lists, no guessing. The combination means your sequences reach developers at the moment of peak interest, not weeks after they moved on.
- Stargazer signals: new stars on your repo or a competitor repo trigger lead creation
- Keyword signals: GitHub issues/PRs/discussions mentioning your target keywords create contacts
- Enriched data: name, email (if public), GitHub username, company, location, followers, top languages, signal context
- Reply.io receives contacts via API, webhook, or Zapier — your choice
Integration Method 1: Webhook → Reply.io via Zapier
The simplest path is through Zapier. GitLeads fires a webhook for each new lead; Zapier catches it and creates a Reply.io contact or adds them to a sequence.
- In GitLeads dashboard → Integrations → Webhook, copy your webhook URL
- In Zapier, create a new Zap: Trigger = Webhooks by Zapier (Catch Hook)
- Paste your GitLeads webhook URL into the Zapier trigger
- Action = Reply.io: Create or Update a Contact
- Map fields: email → email, name → first/last name, bio → custom field "GitHub Bio", company → company
- Add a second action: Reply.io → Add Contact to Sequence, pick your developer-targeted sequence
- Turn the Zap on
Integration Method 2: Reply.io API directly
For tighter control, use GitLeads webhooks to call the Reply.io REST API directly. This lets you set custom fields, assign sequences, and add tags without a middleware layer.
import crypto from 'crypto';
// GitLeads webhook payload shape
interface GitLeadsPayload {
event: 'lead.created';
lead: {
name: string;
email?: string;
githubUsername: string;
profileUrl: string;
bio?: string;
company?: string;
location?: string;
followers: number;
topLanguages: string[];
signalType: 'stargazer' | 'keyword';
signalContext: string;
};
}
// Verify GitLeads webhook signature
function verifySignature(payload: string, signature: string, secret: string): boolean {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
// Push lead to Reply.io
async function pushToReply(lead: GitLeadsPayload['lead']): Promise<void> {
const REPLY_API_KEY = process.env.REPLY_API_KEY!;
const SEQUENCE_ID = process.env.REPLY_SEQUENCE_ID!; // numeric sequence ID
// Step 1: Create/update contact
const contactRes = await fetch('https://api.reply.io/v1/people', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': REPLY_API_KEY,
},
body: JSON.stringify({
firstName: lead.name.split(' ')[0] ?? lead.githubUsername,
lastName: lead.name.split(' ').slice(1).join(' ') || '',
email: lead.email ?? `${lead.githubUsername}@github-noreply.com`,
company: lead.company ?? '',
title: '',
// Custom fields — configure these in Reply.io Settings → Custom fields
customFields: {
github_username: lead.githubUsername,
github_bio: lead.bio ?? '',
top_languages: lead.topLanguages.join(', '),
signal_type: lead.signalType,
signal_context: lead.signalContext,
github_followers: lead.followers,
},
}),
});
if (!contactRes.ok) {
const err = await contactRes.text();
throw new Error(`Reply.io create contact failed: ${err}`);
}
// Step 2: Add contact to sequence
const addRes = await fetch(
`https://api.reply.io/v1/actions/addtosequence?api_key=${REPLY_API_KEY}`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
sequenceId: parseInt(SEQUENCE_ID, 10),
email: lead.email,
}),
}
);
if (!addRes.ok) {
const err = await addRes.text();
console.warn(`Reply.io add to sequence failed: ${err}`);
}
}
// Next.js / Express webhook handler
export async function POST(req: Request): Promise<Response> {
const rawBody = await req.text();
const sig = req.headers.get('x-gitleads-signature') ?? '';
if (!verifySignature(rawBody, sig, process.env.GITLEADS_WEBHOOK_SECRET!)) {
return new Response('Unauthorized', { status: 401 });
}
const payload: GitLeadsPayload = JSON.parse(rawBody);
if (payload.event === 'lead.created' && payload.lead.email) {
await pushToReply(payload.lead);
}
return new Response('ok');
}Sequence Strategy for Developer Leads
Developer leads respond differently than typical B2B contacts. Keep sequences short (3–4 steps), lead with technical value, and reference the GitHub signal explicitly. A message that says "I noticed you starred X repo" gets 2–3x the reply rate of a generic opener.
- Step 1 (Day 0): Personalized email referencing the signal — "Saw you starred [repo], thought you might be evaluating [problem category]..."
- Step 2 (Day 3): Technical content — link to a relevant doc, benchmark, or comparison post
- Step 3 (Day 7): Direct ask — short CTA for a demo or free trial
- Step 4 (Day 14): Breakup email — keep it brief, leave the door open
Tips: Filtering Before Reply.io
Not every GitHub signal warrants a sequence. Filter in your webhook handler before calling Reply.io:
- Only enroll leads with a public email (higher deliverability)
- Skip bots: filter githubUsername patterns ending in [bot] or containing -bot
- Prioritize leads with followers > 50 or company field set — these are likely decision-makers
- Use signalType to route: stargazer leads go to "Evaluation" sequence, keyword leads to "Pain Point" sequence