FoxReach
Back to Blog
Product Updates

Introducing the FoxReach TypeScript SDK

Build type-safe integrations with zero dependencies using the official FoxReach TypeScript/JavaScript SDK.

FoxReach Team3 min read

Overview

The official FoxReach TypeScript SDK gives you type-safe access to the entire FoxReach API. It has zero dependencies, uses native fetch, and works everywhere — Node.js, Deno, Bun, and edge runtimes.

Install it with npm:

npm install foxreach

Quick Start

import { FoxReach } from "foxreach";

const client = new FoxReach({ apiKey: "otr_your_key" });

// List all active leads
const leads = await client.leads.list({ status: "active" });
for (const lead of leads.data) {
  console.log(`${lead.email} — ${lead.company}`);
}

// Create a new lead
const lead = await client.leads.create({
  email: "jane@example.com",
  firstName: "Jane",
  lastName: "Smith",
  company: "TechCorp",
});
console.log(`Created lead: ${lead.id}`);

What's Included

The SDK covers every FoxReach API endpoint:

  • Leadsclient.leads.list(), create(), get(), update(), delete()
  • Campaignscreate(), start(), pause(), resume(), delete()
  • Sequencesclient.campaigns.sequences.create(), update(), delete()
  • Templatesclient.templates.list(), create(), update(), delete()
  • Email Accountsclient.emailAccounts.list(), get(), delete()
  • Inboxclient.inbox.list(), get(), update(), reply()
  • Analyticsclient.analytics.overview(), campaign()
  • Webhooksclient.webhooks.list(), create(), update(), delete()

Full Type Safety

Every request and response is fully typed. Your editor gives you autocomplete, inline docs, and compile-time error checking:

const campaign = await client.campaigns.create({
  name: "Q1 Enterprise Outreach",
  timezone: "America/New_York",
  sendingDays: [1, 2, 3, 4, 5],
  sendingStartHour: 9,
  sendingEndHour: 17,
  dailyLimit: 50,
});
// campaign is typed as Campaign with all fields

Auto-Pagination

List endpoints return paginated results. Use the built-in pagination helpers:

// Get a single page
const page = await client.leads.list({ page: 1, limit: 50 });
console.log(`Total: ${page.total}, Page: ${page.page}`);

// Iterate all pages with async iterator
for await (const lead of client.leads.listAll({ status: "active" })) {
  console.log(lead.email);
}

Error Handling

API errors are thrown as typed exceptions:

import { FoxReachError, NotFoundError, ValidationError } from "foxreach";

try {
  const lead = await client.leads.get("cld_nonexistent");
} catch (error) {
  if (error instanceof NotFoundError) {
    console.log("Lead not found");
  } else if (error instanceof ValidationError) {
    console.log(`Invalid request: ${error.message}`);
  } else if (error instanceof FoxReachError) {
    console.log(`API error ${error.statusCode}: ${error.message}`);
  }
}

End-to-End Example: Campaign Setup

Here's a complete script that creates leads, builds a campaign, and starts it:

import { FoxReach } from "foxreach";

const client = new FoxReach({ apiKey: "otr_your_key" });

// 1. Create leads
const contacts = [
  { email: "sarah@techcorp.io", firstName: "Sarah", lastName: "Chen", company: "TechCorp" },
  { email: "mike@startupco.com", firstName: "Mike", lastName: "Johnson", company: "StartupCo" },
  { email: "lisa@enterprise.com", firstName: "Lisa", lastName: "Wang", company: "Enterprise Ltd" },
];

const leads = await Promise.all(
  contacts.map((contact) => client.leads.create(contact))
);
console.log(`Created ${leads.length} leads`);

// 2. Create a campaign
const campaign = await client.campaigns.create({
  name: "Q1 Outreach",
  timezone: "America/New_York",
  sendingDays: [1, 2, 3, 4, 5],
  sendingStartHour: 9,
  sendingEndHour: 17,
  dailyLimit: 50,
});

// 3. Add sequence steps
await client.campaigns.sequences.create(campaign.id, {
  subject: "Quick question about {{company}}",
  body: "Hi {{firstName}},\n\nI noticed {{company}} is growing fast...",
  delayDays: 0,
});

await client.campaigns.sequences.create(campaign.id, {
  subject: "Re: Quick question about {{company}}",
  body: "Hi {{firstName}},\n\nJust following up...",
  delayDays: 3,
});

// 4. Add leads to campaign
await client.campaigns.addLeads(campaign.id, leads.map((l) => l.id));

// 5. Assign email account
const accounts = await client.emailAccounts.list();
await client.campaigns.addAccounts(campaign.id, [accounts.data[0].id]);

// 6. Start the campaign
await client.campaigns.start(campaign.id);
console.log(`Campaign '${campaign.name}' is now active!`);

Use with Express for Webhook Handling

The SDK pairs well with Express for receiving webhook events:

import express from "express";
import crypto from "crypto";

const app = express();
const WEBHOOK_SECRET = "your_webhook_secret";

app.post("/webhooks/foxreach", express.raw({ type: "application/json" }), (req, res) => {
  const signature = req.headers["x-webhook-signature"] as string;
  const expected = crypto
    .createHmac("sha256", WEBHOOK_SECRET)
    .update(req.body)
    .digest("hex");

  if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature))) {
    return res.status(401).send("Invalid signature");
  }

  const event = JSON.parse(req.body.toString());
  console.log(`Received event: ${event.event}`);

  // Handle events
  switch (event.event) {
    case "reply.received":
      console.log(`New reply from ${event.data.leadEmail}`);
      break;
    case "email.bounced":
      console.log(`Bounce: ${event.data.leadEmail}`);
      break;
  }

  res.sendStatus(200);
});

app.listen(3000);

Resources

Stay ahead of the inbox

Get cold email tips, deliverability hacks, and product updates. No spam, unsubscribe anytime.