Push GitHub Developer Leads to Close CRM

Route GitHub intent signals — stargazers, keyword mentions — directly into Close CRM as new leads. Step-by-step integration guide using GitLeads webhooks and the Close REST API.

Published: May 10, 2026Updated: May 10, 20268 min read

Why Close CRM for Developer Leads?

Close CRM is built for inside sales teams that do high-velocity outreach. Its built-in email sequencing, calling, and SMS make it ideal for teams selling developer tools who want to run outbound directly from their CRM — no additional sales engagement tool required. Combined with GitHub signal data from GitLeads, Close becomes a developer-focused outreach engine where every new contact has a known intent signal attached.

Architecture: GitLeads to Close via Webhook

GitLeads fires a signed webhook for every new developer signal. Your webhook endpoint calls the Close REST API to create or update a lead and contact record. The signal context — which repo, which keyword, when — gets stored as a note on the Close lead.

# Flow overview
GitLeads signal fires
  → POST /webhook (your endpoint, HMAC verified)
    → Close API: POST /lead (create with embedded contact)
    → Close API: POST /activity/note (signal context)
    → [Optional] Close API: POST /sequence_subscription

Step 1: Configure GitLeads Webhook

In GitLeads dashboard → Integrations → Webhooks, add your endpoint URL and copy the signing secret. GitLeads signs every payload with HMAC-SHA256 via the x-gitleads-signature header.

Step 2: Create the Webhook Receiver

import express from 'express';
import crypto from 'crypto';

const app = express();
app.use(express.json());

const GITLEADS_SECRET = process.env.GITLEADS_WEBHOOK_SECRET!;
const CLOSE_API_KEY = process.env.CLOSE_API_KEY!;
const CLOSE_BASE = 'https://api.close.com/api/v1';

function verifySignature(payload: string, signature: string): boolean {
  const expected = crypto
    .createHmac('sha256', GITLEADS_SECRET)
    .update(payload)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from('sha256=' + expected)
  );
}

app.post('/gitleads/close', async (req, res) => {
  const raw = JSON.stringify(req.body);
  const sig = req.headers['x-gitleads-signature'] as string;
  if (!verifySignature(raw, sig)) {
    return res.status(401).json({ error: 'Invalid signature' });
  }
  await processLead(req.body);
  res.json({ ok: true });
});

Step 3: Create a Lead in Close

interface GitLeadsPayload {
  signal_type: 'stargazer' | 'keyword';
  repo?: string;
  keyword?: string;
  developer: {
    github_username: string;
    name: string;
    email?: string;
    company?: string;
    bio?: string;
    followers: number;
    top_languages: string[];
  };
}

async function processLead(payload: GitLeadsPayload) {
  const dev = payload.developer;
  const auth = Buffer.from(CLOSE_API_KEY + ':').toString('base64');
  const headers = {
    'Authorization': `Basic ${auth}`,
    'Content-Type': 'application/json',
  };

  // Create lead with embedded contact
  const leadRes = await fetch(`${CLOSE_BASE}/lead/`, {
    method: 'POST',
    headers,
    body: JSON.stringify({
      name: dev.company || dev.name,
      contacts: [{
        name: dev.name,
        emails: dev.email ? [{ email: dev.email, type: 'office' }] : [],
        urls: [{ url: `https://github.com/${dev.github_username}`, label: 'GitHub' }],
      }],
      custom: {
        'GitHub Username': dev.github_username,
        'Followers': dev.followers,
        'Top Languages': dev.top_languages.join(', '),
        'Signal Type': payload.signal_type,
        'Signal Source': payload.repo || payload.keyword,
      },
    }),
  });
  const lead = await leadRes.json();

  // Add note with signal context
  await fetch(`${CLOSE_BASE}/activity/note/`, {
    method: 'POST',
    headers,
    body: JSON.stringify({
      lead_id: lead.id,
      note: `GitLeads: ${payload.signal_type} on ${payload.repo || payload.keyword}. ${dev.followers} followers. Bio: ${dev.bio || 'n/a'}`,
    }),
  });
}

Step 4: Enroll in a Close Sequence

// Enroll contact in a Close email sequence
async function enrollInSequence(
  contactId: string,
  sequenceId: string,
  senderEmail: string
) {
  const auth = Buffer.from(CLOSE_API_KEY + ':').toString('base64');
  await fetch(`${CLOSE_BASE}/sequence_subscription/`, {
    method: 'POST',
    headers: {
      'Authorization': `Basic ${auth}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      contact_id: contactId,
      sequence_id: sequenceId,
      sender_account: { email: senderEmail },
    }),
  });
}

// Only enroll leads with email + company (higher qualification)
if (dev.email && dev.company) {
  await enrollInSequence(contactId, SEQUENCE_ID, 'outreach@yourco.com');
}

Using Zapier or n8n Instead

GitLeads also supports native Zapier and n8n integrations. Connect GitLeads → Zapier → Close via Close's Zapier app and configure field mapping in the editor. This covers the most common case: create a Close lead for every new GitHub stargazer without writing any code.

GitLeads captures GitHub developer intent signals and routes enriched profiles to Close CRM, HubSpot, Salesforce, Pipedrive, Apollo, and 12 other tools. We find the leads — Close handles the outreach. Start free at [gitleads.app](https://gitleads.app). Related: [push GitHub leads to HubSpot](/blog/push-github-leads-to-hubspot), [push GitHub leads to Pipedrive](/blog/push-github-leads-to-pipedrive), [push GitHub leads to Apollo](/blog/push-github-leads-to-apollo).

Want more like this? Get the weekly developer lead playbook.

No spam. 5 emails over 2 weeks. Unsubscribe anytime.

Related Articles

How to Find Leads on GitHub: The Complete Guide (2026)
10 min read
GitHub Leads vs LinkedIn Leads: When to Use Which (2026)
9 min read
GDPR Compliance for GitHub Lead Scraping: What You Must Know
8 min read