TypeScript SDK
Install and use the @misar/reach-sdk to search leads, verify emails, score leads, and manage deals from Node.js or the browser.
Installation
pnpm add @misar/reach-sdkSetup
import { MisarReachClient } from "@misar/reach-sdk";
export const reach = new MisarReachClient({
apiKey: process.env.MISARREACH_API_KEY!,
// baseUrl defaults to "https://api.misar.io/reach"
});Lead Finder
Search leads
client.leads.search() creates an async search job and returns a jobId. The search processes in the background — poll client.leads.getJob() for results.
const { jobId } = await reach.leads.search({
query: "CTOs at B2B SaaS startups with 10-50 employees in India",
filters: {
location: "India",
industry: "B2B SaaS",
companySize: "10-50",
},
useAI: true, // enable AI enrichment
});Poll for job completion
async function waitForJob(jobId: string) {
let job = await reach.leads.getJob(jobId);
while (job.status === "pending" || job.status === "running") {
await new Promise((r) => setTimeout(r, 2000));
job = await reach.leads.getJob(jobId);
}
if (job.status === "failed") {
throw new Error(`Search job failed: ${jobId}`);
}
return job;
}
const job = await waitForJob(jobId);
console.log(`Found ${job.result_count} leads`);List leads
const { leads, total } = await reach.leads.list({
jobId, // filter by job
page: 1,
limit: 50,
search: "CTO", // optional text filter
});
for (const lead of leads) {
console.log(`${lead.name} <${lead.email}> — ${lead.company} (score: ${lead.score})`);
}Discover companies
Synchronous endpoint — returns results immediately.
const { companies, leads } = await reach.leads.discover({
industry: ["SaaS", "Fintech"],
location: ["India", "Singapore"],
headcount_min: 10,
headcount_max: 100,
fetch_emails: true,
limit: 20,
});Verify emails
Verify up to 20 emails per call. Returns deliverability status and confidence score.
const { results, verified } = await reach.leads.verify({
emails: ["[email protected]", "[email protected]"],
});
const validEmails = results.filter((r) => r.status === "valid" && !r.pending);
console.log(`${verified} verified, ${validEmails.length} valid`);Verification result shape:
interface VerifyResult {
email: string;
status: "valid" | "risky" | "invalid" | "unknown" | null;
score: number | null; // 0–100
pending: boolean; // true if Hunter.io is still processing
}Score leads
Background scoring — returns immediately. Fetch updated score and score_reason from leads.list() after a few seconds.
// Score all unscored leads for a job
const { scored } = await reach.leads.score({ jobId });
console.log(`Scoring ${scored} leads...`);
// Or score specific leads
await reach.leads.score({ leadIds: ["uuid-1", "uuid-2"] });Manage lead lists
// List all saved lists
const { lists } = await reach.lists.list();
// Create a new list
const { list } = await reach.lists.create({ name: "India CTOs — May 2026" });
console.log(`Created list ${list.id}`);Deals
Create a deal
const { deal } = await reach.deals.create({
leadEmail: "[email protected]",
leadName: "Priya Sharma",
value: 15000, // in currency's base unit
currency: "USD",
notes: "Responded positively to cold email. Demo scheduled.",
conversationId: "uuid", // optional — links deal to conversation
});
console.log(`Deal ${deal.id} created with status: ${deal.status}`);List deals
const { deals, total, revenue } = await reach.deals.list({
status: "proposal", // optional filter
limit: 20,
offset: 0,
});
console.log(`Pipeline value: $${revenue.pipeline}`);
console.log(`Closed revenue: $${revenue.closed}`);Update a deal
// Move to next stage
await reach.deals.update(dealId, { status: "meeting" });
// Mark closed
await reach.deals.update(dealId, {
status: "closed",
notes: "Contract signed — $15,000.",
});Pipeline
Get the board
Returns all deals grouped by stage.
const { board, revenue, stages } = await reach.pipeline.get();
for (const stage of stages) {
const deals = board[stage];
console.log(`${stage}: ${deals.length} deals`);
}Move a deal
await reach.pipeline.move({
dealId: "uuid",
newStage: "meeting",
});Full example — lead-to-deal workflow
import { MisarReachClient } from "@misar/reach-sdk";
const reach = new MisarReachClient({
apiKey: process.env.MISARREACH_API_KEY!,
});
async function main() {
// 1. Search for leads
const { jobId } = await reach.leads.search({
query: "Founders at fintech startups in Southeast Asia",
filters: { location: "Southeast Asia", industry: "Fintech" },
useAI: true,
});
console.log(`Search started: ${jobId}`);
// 2. Wait for results
let job = await reach.leads.getJob(jobId);
while (job.status === "pending" || job.status === "running") {
await new Promise((r) => setTimeout(r, 2000));
job = await reach.leads.getJob(jobId);
}
console.log(`Found ${job.result_count} leads`);
// 3. Get leads
const { leads } = await reach.leads.list({ jobId, limit: 20 });
// 4. Verify top 10 emails
const emailsToVerify = leads.slice(0, 10).map((l) => l.email);
const { results } = await reach.leads.verify({ emails: emailsToVerify });
const validEmails = new Set(
results.filter((r) => r.status === "valid").map((r) => r.email)
);
// 5. Create deals for verified leads
const validLeads = leads.filter((l) => validEmails.has(l.email));
for (const lead of validLeads) {
const { deal } = await reach.deals.create({
leadEmail: lead.email,
leadName: lead.name ?? undefined,
value: 0,
currency: "USD",
notes: `Lead from: ${lead.company} (score: ${lead.score})`,
});
console.log(`Deal created: ${deal.id} for ${lead.email}`);
}
console.log(`Created ${validLeads.length} deals from ${leads.length} leads`);
}
main().catch(console.error);Error handling
The SDK throws typed errors for HTTP failures:
import { MisarReachError } from "@misar/reach-sdk";
try {
const result = await reach.leads.search({ query: "..." });
} catch (err) {
if (err instanceof MisarReachError) {
console.error(`API error ${err.status}: ${err.message}`);
if (err.status === 429 && err.data.upgrade) {
console.log("Credit limit reached — upgrade at dashboard.misar.io");
}
}
}TypeScript types
All request and response types are exported from @misar/reach-sdk:
import type {
LeadSearchRequest,
LeadSearchJob,
Lead,
VerifyResult,
Deal,
PipelineBoard,
PipelineDeal,
} from "@misar/reach-sdk";