lewsearch
v0.1.0
Published
Query a calibrated panel of synthetic respondents from your code — the official Lewsearch (Lewis) SDK.
Maintainers
Readme
lewsearch
Poll a calibrated panel of synthetic respondents from your code. Ask any question, get back how a population actually splits — with an honest confidence read and panel composition. Benchmarked against Pew, Gallup & UT/TPP (~7.5 pp MAE on structured items).
npm install lewsearchQuick start
import { Lewsearch } from "lewsearch";
const ls = new Lewsearch({ apiKey: process.env.LEWSEARCH_API_KEY! });
const res = await ls.poll({
question: "Would you switch brands at $4.99?",
options: ["Definitely", "Probably", "Probably not", "No"],
audience: { market: "national_us", n: 500 },
});
console.log(res.summary);
// "Among US adults (n=500), Probably leads at 38% (vs No 27%...). Directional read."
console.log(res.distribution);
// [ { option: "Probably", pct: 38.0, count: 190 }, ... ]
console.log(res.confidence); // { score: 0.74, label: "Directional", tier: "amber" }
console.log(res.panel_composition); // { n_real: 500, n_synthetic: 0, n_total: 500, ... }res.summary is a ready-to-print sentence — great for logging or handing straight to a coding agent. Everything else (res.distribution, res.confidence, res.panel_composition) is the structured detail.
Get an API key at https://lewsearch.com/developers.
Calibrated vs. free-form
- Pass 2–6
options→ a calibrated multiple-choice read (the trustworthy path; benchmarked against Pew/Gallup). - Omit
options→ an uncalibrated free-form read (directional only, no numeric accuracy claim).
Always check res.confidence.tier before leaning on a number.
Example: a price demand curve
const prices = [2.99, 3.99, 4.99, 5.99];
for (const price of prices) {
const res = await ls.poll({
question: "Would you buy this at $" + price + "?",
options: ["Yes", "No"],
audience: { market: "national_us", n: 1000 },
});
const yes = res.distribution.find((d) => d.option === "Yes")?.pct ?? 0;
console.log("$" + price + " -> " + yes + "% would buy");
}API
new Lewsearch({ apiKey, baseUrl?, timeout? })
apiKey— yoursk-lew-...key (required).baseUrl— defaults tohttps://lewsearch.com/api/v1.timeout— ms, default60000.
ls.poll(params) → Promise<PollResult>
question: string(required)options?: string[]— 2–6 for calibrated MCaudience?: { market?: string; n?: number }— e.g.market: "national_us" | "columbus" | "texas";nis clamped to your plan's per-query maxrequestId?: string— idempotency key (a retried request bills once)
Errors throw LewsearchError with .status and .code (UNAUTHORIZED, FORBIDDEN, RATE_LIMITED, TIMEOUT, API_ERROR, …).
Billing
Metered by respondents queried against your plan's monthly pool. res.usage shows respondents_billed, month_used, and month_limit. Enterprise deployments run on dedicated inference with no per-call cost. Full docs: https://lewsearch.com/api-docs.
Made by Lewsearch · synthetic respondents are estimates, not guarantees.
