Skip to main content

JavaScript / Node.js Examples

These examples use the built-in fetch API (Node.js 18+). No additional dependencies required.

Setup

const API_KEY = process.env.NATURALEAD_API_KEY;
const BASE_URL = "https://api.naturalead.ai/api";

async function apiRequest(method, path, body) {
  const response = await fetch(`${BASE_URL}${path}`, {
    method,
    headers: {
      "X-API-Key": API_KEY,
      "Content-Type": "application/json",
    },
    body: body ? JSON.stringify(body) : undefined,
  });

  if (response.status === 429) {
    const retryAfter = response.headers.get("Retry-After") || "5";
    throw new Error(`Rate limited. Retry after ${retryAfter}s`);
  }

  if (!response.ok) {
    const { error } = await response.json();
    throw new Error(`${response.status}: ${error}`);
  }

  if (response.status === 204) return null;
  return response.json();
}

Lead Management

List all leads

const leads = await apiRequest("GET", "/leads");

for (const lead of leads) {
  console.log(`#${lead.id} ${lead.name} (${lead.status})`);
}

Create a lead

try {
  const lead = await apiRequest("POST", "/leads", {
    name: "Jane Smith",
    phone: "+14155551234",
    email: "[email protected]",
    tags: ["inbound", "demo"],
  });

  console.log(`Created lead #${lead.id}`);
} catch (error) {
  if (error.message.includes("409")) {
    console.log("Lead with this phone already exists");
  } else {
    throw error;
  }
}

Search leads

const results = await apiRequest("GET", "/leads/search?q=john&limit=10");
console.log(`Found ${results.leads.length} leads`);

Bulk sync from CRM

const result = await apiRequest("POST", "/leads/sync", {
  leads: [
    {
      lead_id: "crm-001",
      name: "Alice Johnson",
      phone: "+14155551111",
      email: "[email protected]",
      custom_fields: { company: "Acme Corp", deal_size: "50000" },
    },
    {
      lead_id: "crm-002",
      name: "Bob Wilson",
      phone: "+14155552222",
    },
  ],
});

console.log(`Created: ${result.created}, Updated: ${result.updated}`);

for (const error of result.errors) {
  console.error(`Error for ${error.lead_id}: ${error.error}`);
}

Conversations

Start a conversation

try {
  const conversation = await apiRequest("POST", "/conversations/start", {
    leadId: 1,
    channel: "whatsapp",
  });

  console.log(`Conversation started: ${conversation._id}`);
} catch (error) {
  if (error.message.includes("503")) {
    console.log("Messaging not configured. Set up integration first.");
  }
}

List active conversations

const conversations = await apiRequest("GET", "/conversations?status=active");

for (const conv of conversations) {
  console.log(`${conv._id}: ${conv.status} (${conv.messages?.length || 0} messages)`);
}

Campaigns

Create and launch a campaign

// Create
const campaign = await apiRequest("POST", "/campaigns", {
  name: "Q1 Outreach",
  agentConfigId: "AGENT_ID",
  channel: "whatsapp",
  leadFilter: { statuses: ["new"], tags: ["inbound"] },
  schedule: {
    rateLimit: 10,
    activeHours: {
      start: "09:00",
      end: "17:00",
      timezone: "America/New_York",
    },
    activeDays: [1, 2, 3, 4, 5], // Monday-Friday
  },
});

// Launch
const launched = await apiRequest("POST", `/campaigns/${campaign._id}/launch`);
console.log(`Campaign status: ${launched.status}`);

CSV Import

Two-step CSV import

const csvContent = `Name,Phone,Email,Company
Jane Smith,+14155551234,[email protected],Acme Corp
Bob Jones,+14155555678,[email protected],Widget Inc`;

// Step 1: Preview
const preview = await apiRequest("POST", "/leads/upload/preview", {
  content: csvContent,
});

console.log(`Headers: ${preview.headers.join(", ")}`);
console.log(`Total rows: ${preview.totalRows}`);

// Step 2: Confirm with mapping
const result = await apiRequest("POST", "/leads/upload/confirm", {
  content: csvContent,
  mapping: {
    Name: "name",
    Phone: "phone",
    Email: "email",
    Company: "companyName", // becomes custom field
  },
  tags: ["csv-import", "q1-2026"],
});

console.log(`Imported: ${result.imported}, Duplicates: ${result.duplicatesSkipped}`);

Rate Limit Handling

async function apiRequestWithRetry(method, path, body, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const response = await fetch(`${BASE_URL}${path}`, {
      method,
      headers: {
        "X-API-Key": API_KEY,
        "Content-Type": "application/json",
      },
      body: body ? JSON.stringify(body) : undefined,
    });

    if (response.status !== 429) {
      if (!response.ok) {
        const { error } = await response.json();
        throw new Error(`${response.status}: ${error}`);
      }
      return response.status === 204 ? null : response.json();
    }

    const retryAfter = parseInt(response.headers.get("Retry-After") || String(2 ** attempt));
    console.log(`Rate limited. Waiting ${retryAfter}s...`);
    await new Promise((resolve) => setTimeout(resolve, retryAfter * 1000));
  }

  throw new Error("Max retries exceeded");
}