ldm-sdk
v0.1.0
Published
Official Node/TypeScript SDK for LDM (Live Direct Marketing) — agent-grade CRM + cold-email + inbox-placement API
Maintainers
Readme
ldm-sdk
Official Node / TypeScript SDK for the LDM API — agent-grade CRM, cold-email, and inbox-placement.
npm install ldm-sdkQuick start
import { LdmClient } from 'ldm-sdk';
const ldm = new LdmClient({
apiKey: process.env.LDM_API_KEY!, // ldm_pk_…
defaultTenantId: process.env.LDM_TENANT_ID, // optional
});
// CRM
const { data: companies } = await ldm.companies.list({ pageSize: 25 });
const lead = await ldm.leads.create({
title: 'Acme demo',
pipelineId: 'pipeline-id',
stageId: 'stage-id',
amount: 50000,
});
// Deal forecast
const f = await ldm.leads.deal.forecast({ pipelineId: lead.pipelineId });
console.log(f.totalWeighted);
// Email verify (single + batch)
const v = await ldm.verify.one('[email protected]');
const vs = await ldm.verify.batch(['[email protected]', '[email protected]']);
// Inbox snooze + forward
await ldm.dialogs.snooze(dialogId, { until: '2026-12-31T09:00:00Z' });
await ldm.dialogs.forward(dialogId, { toEmail: '[email protected]' });
// Mailbox warmup
const w = await ldm.emailAccounts.warmup.stats(accountId);
await ldm.emailAccounts.warmup.configure(accountId, { target: 200 });
// Webhooks: subscribe + replay
const ep = await ldm.webhooks.create({ url: 'https://you.example/cb', events: ['*'] });
await ldm.webhooks.retrigger(ep.id, { limit: 10, status: 'failed' });
// Subsequences
const branch = await ldm.tasks.branches.create(parentTaskId, {
methodId: 12,
methodName: 'Email',
branchTrigger: { event: 'reply.positive' },
});
await ldm.tasks.branches.enroll(parentTaskId, branch.id, {
contactIds: ['contact-1', 'contact-2'],
});Idempotency
Pass idempotencyKey on any mutating call. The server caches the
response for 24h — retrying with the same key (and same body) returns
the cached row instead of double-creating.
await ldm.companies.create(
{ name: 'Acme' },
{ idempotencyKey: `acme-import-${batchId}` },
);If the same key is used with a different body the server returns HTTP 409 Conflict.
A2A (agent-to-agent)
const card = await ldm.a2a.agentCard();
const task = await ldm.a2a.sendMessage({
message: {
role: 'user',
parts: [{ kind: 'data', data: { skillId: 'companies.list', args: { query: { pageSize: 5 } } } }],
},
});For SSE streaming (message/stream), use the raw fetch:
const res = await fetch('https://api.live-direct-marketing.online/a2a', {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.LDM_API_KEY}`, Accept: 'text/event-stream', 'Content-Type': 'application/json' },
body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'message/stream', params: { /* … */ } }),
});
// res.body is a ReadableStream of `data: {...}\n\n` frames.Errors
All non-2xx responses throw LdmError with status, code, and
the parsed body for inspection.
import { LdmError } from 'ldm-sdk';
try { await ldm.companies.create({ name: '' }); }
catch (e) {
if (e instanceof LdmError && e.status === 400) console.warn(e.message);
else throw e;
}Auth
Issue an API key at: https://app.live-direct-marketing.online/settings/api-keys
The key carries a fixed scope set; the API enforces scopes
per-endpoint. Keys are per-tenant — pass defaultTenantId if your
deployment serves multiple tenants under one key, or override per
request with { tenantId: '…' }.
Compatibility
- Node ≥ 18 (uses native
fetch). - Browsers: works with
importfrom a bundler.LDM_API_KEYshould never ship to a public client; use a backend proxy. - ESM only. For CommonJS consumers, use
await import('ldm-sdk').
Links
- API docs: https://developers.live-direct-marketing.online/
- A2A agent card: https://api.live-direct-marketing.online/.well-known/agent.json
- MCP server (separate package): https://www.npmjs.com/package/ldm-crm-mcp
