TypeScript SDK
@selda/sdk is a typed client for the Selda API. It’s a thin wrapper over the HTTP API, same auth and org scoping, so you can push leads, create campaigns, run the pipeline and draft messages from your own code without writing fetch calls by hand.
Zero dependencies, uses the global fetch, works in Node 18+, Bun, Deno, edge runtimes and the browser.
Install
npm i @selda/sdkUsing an AI coding tool? You don’t have to write the integration yourself. Paste the prompt from the package’s
AI-INSTALL.mdinto Claude Code / Cursor / Lovable / Bolt and it wires Selda into your app for you.
Authenticate
Create an API key in the app (Settings → API keys, format sk_live_…) with the scopes you need (read, write, pipeline). Pass it to the client along with a default workspace id:
import { createSelda } from "@selda/sdk";
const selda = createSelda({
apiKey: process.env.SELDA_API_KEY!, // sk_live_…
projectId: process.env.SELDA_PROJECT_ID!, // default workspace (optional per call)
});The key resolves your org, so you never send orgId or userId. Keys are revocable anytime, and pipeline runs consume credits, the same as in the app.
Push leads
The whole integration can be a single call. Selda dedups by email, so re-running is safe.
const { leadId, duplicate } = await selda.leads.add({
company: "Acme Oy",
email: "owner@acme.fi",
companyDomain: "acme.fi",
source: "my-app",
});Wire it into your signup handler or a daily cron and your app’s data flows into Selda automatically.
Create campaigns
Two ways. A) you bring the leads:
const c = await selda.campaigns.create({ name: "Summer 2026", channels: ["email"], leadCount: 30 });
await selda.campaigns.addLeads(c.campaignId, [leadId]);B) you bring company names, the engine does the rest, finding decision-makers, writes hooks and messages:
await selda.engine.start({ idea: "Helsinki SaaS companies hiring sales", campaignId: c.campaignId });Both produce drafts. Nothing sends until you approve.
Generate, approve, send
await selda.messages.generate({ leadId }); // draft a message
await selda.messages.approve(messageId); // human approval
await selda.messages.send(messageId); // only works after approveSurface area
| Namespace | Methods | Scope |
|---|---|---|
selda.projects | list · get · create · updateContext | read / write |
selda.leads | add · list · get · updateStatus · update | read / write |
selda.campaigns | list · get · stats · create · addLeads | read / write |
selda.messages | byProject · byLead · approve · generate · send | read / write / pipeline |
selda.credits | info | read |
selda.engine | start | pipeline |
selda.company | lookup | pipeline |
selda.replies | classify · draft | pipeline |
Errors
Failed calls throw SeldaError with .status and .fn. Never let a Selda failure break your own flow:
import { SeldaError } from "@selda/sdk";
try {
await selda.leads.add({ company: "Acme" });
} catch (e) {
if (e instanceof SeldaError) console.error(e.status, e.fn, e.message);
}.status | Meaning |
|---|---|
401 | Bad / revoked key |
403 | Key lacks the scope for that call |
400 | Unknown function |
500 | The function threw (e.g. unauthorized project) |
→ Underlying endpoints and payloads: HTTP API & webhooks reference.