@signaliz/sdk 1.0.21 → 1.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,732 +1,67 @@
1
1
  # @signaliz/sdk
2
2
 
3
- The official Signaliz SDK for JavaScript/TypeScript GTM intelligence for AI agents.
4
-
5
- Current surfaces include the GTM Kernel, Campaign Builder, provider routing,
6
- Nango-managed customer API connections, MCP/Ops control-plane methods, and
7
- enrichment primitives. Available data is returned before fresh enrichment;
8
- live email verification is 0.02 fresh enrichment credits when a new verification is needed.
9
- Builder includes unlimited cache search, Campaign Builder, API, MCP, CLI, Ops,
10
- and integrations. Team is the $499/month public plan and adds unlimited live
11
- Find People and Find Companies in Signaliz; Agency stays $999/month with higher
12
- credits and throughput.
13
-
14
- ## Which Surface Should I Use?
15
-
16
- Signaliz is the GTM brain over any stack. The SDK is for application code,
17
- scripts, and agent runtimes that need typed access to the same GTM Kernel, Ops,
18
- integration, and approval primitives exposed through MCP and CLI.
19
-
20
- - Use MCP or Codex when an agent should reason, choose tools, and build or audit
21
- a campaign from a plain-English goal.
22
- - Use the CLI when a human operator or local agent needs a repeatable command,
23
- JSON receipt, readiness check, or debug trail. Start with `signaliz start`.
24
- - Use the SDK when product code or automation needs typed methods.
25
- - Use the UI as the human cockpit to inspect state, connect tools, approve gated
26
- actions, and monitor results.
27
-
28
- ## Installation
3
+ Typed JavaScript/TypeScript access to the four Signaliz products.
29
4
 
30
5
  ```bash
31
6
  npm install @signaliz/sdk
32
7
  ```
33
8
 
34
- ## Production REST Endpoints
35
-
36
- - Find Email: `https://api.signaliz.com/functions/v1/find-verified-email-v2`
37
- - Email Verification: `https://api.signaliz.com/functions/v1/email-verification-2`
38
- - Company Signal Enrichment: `https://api.signaliz.com/functions/v1/company-signal-enrichment-v2`
39
- - Signal to Copy: `https://api.signaliz.com/functions/v1/api/v1/signal-to-copy`
40
-
41
- ## Quick Start - Ops
42
-
43
- Use Ops when a script or agent needs to turn a plain-English GTM outcome into
44
- durable work, wait for completion, and retrieve rows in one flow.
45
-
46
- ```typescript
47
- import { Signaliz } from '@signaliz/sdk';
48
-
49
- const signaliz = new Signaliz({ apiKey: process.env.SIGNALIZ_API_KEY });
50
-
51
- const result = await signaliz.ops.executeAndWait({
52
- prompt: 'Build 50 approved ICP leads and return reviewed rows',
53
- targetCount: 50,
54
- confirmSpend: true,
55
- limit: 50,
56
- });
57
-
58
- console.log(result.status.status);
59
- console.log(result.results?.results);
60
- ```
61
-
62
- If the Op already exists, queue it and wait for results with `runAndWait()`:
63
-
64
- ```typescript
65
- const run = await signaliz.ops.runAndWait({
66
- opId: 'op_123',
67
- limit: 100,
68
- });
69
- ```
70
-
71
- For manual polling or partial-output recovery, use `waitForResults()` directly:
72
-
73
- ```typescript
74
- const waited = await signaliz.ops.waitForResults({
75
- opId: 'op_123',
76
- maxPolls: 60,
77
- intervalMs: 5000,
78
- includeFailedRuns: true,
79
- });
80
- ```
81
-
82
- ## Quick Start — Campaign Builder
9
+ Production REST endpoints:
83
10
 
84
- Build a targeted lead list, wait for completion, then retrieve rows and CSV:
11
+ - `https://api.signaliz.com/functions/v1/api/v1/find-email`
12
+ - `https://api.signaliz.com/functions/v1/api/v1/verify-email`
13
+ - `https://api.signaliz.com/functions/v1/api/v1/company-signals`
14
+ - `https://api.signaliz.com/functions/v1/api/v1/signal-to-copy`
85
15
 
86
- ```typescript
16
+ ```ts
87
17
  import { Signaliz } from '@signaliz/sdk';
88
18
 
89
- const signaliz = new Signaliz({ apiKey: process.env.SIGNALIZ_API_KEY });
90
-
91
- // 1. Start a campaign build
92
- const { campaignBuildId } = await signaliz.campaigns.build({
93
- name: 'Q3 SaaS Outbound',
94
- prompt: 'Series A-C SaaS companies in fintech hiring SDRs',
95
- targetCount: 500,
96
- confirmSpend: true,
97
- delivery: { destinationType: 'csv' },
98
- });
99
-
100
- // 2. Wait for completion with progress updates
101
- const final = await signaliz.campaigns.wait(campaignBuildId, {
102
- onProgress: (s) => console.log(`${s.recordsProcessed}/${s.recordsTotal} rows`),
103
- });
104
-
105
- // 3. Retrieve structured rows
106
- const { rows } = await signaliz.campaigns.rows(campaignBuildId, { limit: 100 });
107
- rows.forEach((r) => console.log(r.data.email, r.data.company_name));
108
-
109
- // 4. Download CSV artifact
110
- const artifacts = await signaliz.campaigns.artifacts(campaignBuildId);
111
- const csv = artifacts.find((a) => a.artifactType === 'csv');
112
- console.log('Download:', csv?.signedUrl);
113
- ```
114
-
115
- > **Downstream routing:** Signaliz outputs JSON, CSV, and webhook. Your agent routes rows to CRMs, outreach tools, or warehouses using their own APIs/MCPs.
116
-
117
- ## Campaign Builder Agent
118
-
119
- Use `campaignBuilderAgent` when application code should compose the same
120
- strategy-template MCP flow exposed in the CLI: strategy-memory readiness,
121
- Signaliz-native sourcing, email finding, verification, signals, Brain risk, and
122
- BYO tool routes.
123
-
124
- ```typescript
125
- const plan = await signaliz.campaignBuilderAgent.createPlan({
126
- goal: 'Build a strategy-template campaign for mature local operators',
127
- strategyTemplate: 'non-medical-home-care',
128
- targetCount: 500,
129
- builtIns: ['lead_generation', 'local_leads', 'email_finding', 'email_verification', 'signals'],
130
- integrations: [{
131
- provider: 'workspace_mcp',
132
- layer: 'enrichment',
133
- gtmLayers: ['company_enrichment'],
134
- toolName: 'account_enrich',
135
- mcpServerName: 'workspace-mcp',
136
- mode: 'required',
137
- approvalRequired: true,
138
- }],
139
- agencyContext: {
140
- strategyModel: 'strategy_template',
141
- includeStrategyPatterns: true,
142
- includeWorkflowPatterns: true,
143
- includeNangoCatalog: true,
144
- },
145
- });
146
-
147
- const dryRun = await signaliz.campaignBuilderAgent.dryRunPlan(plan);
148
- const readiness = await signaliz.campaignBuilderAgent.readiness({
149
- goal: 'Build a strategy-template campaign for mature local operators',
150
- strategyTemplate: 'non-medical-home-care',
151
- targetCount: 500,
152
- builtIns: ['lead_generation', 'local_leads', 'email_finding', 'email_verification', 'signals'],
153
- });
154
- const proof = await signaliz.campaignBuilderAgent.proof({
155
- goal: 'Build a strategy-template campaign for mature local operators',
156
- strategyTemplate: 'non-medical-home-care',
157
- targetCount: 25,
158
- builtIns: ['lead_generation', 'local_leads', 'email_finding', 'email_verification', 'signals'],
159
- });
160
- const kit = signaliz.campaignBuilderAgent.buildKit({
161
- goal: 'Build a strategy-template campaign for mature local operators',
162
- strategyTemplate: 'non-medical-home-care',
163
- targetCount: 250,
164
- includeLocalLeads: true,
165
- includeCustomToolPlaceholder: true,
166
- });
167
- const memoryKit = signaliz.campaignBuilderAgent.memoryKit({
168
- goal: 'Build a strategy-template campaign for mature local operators',
169
- strategyTemplate: 'non-medical-home-care',
170
- targetCount: 250,
171
- includeLocalLeads: true,
172
- source: 'agency',
173
- });
174
-
175
- console.log(plan.strategyMemoryStatus?.ready);
176
- console.log(readiness.summary.ready);
177
- console.log(proof.success);
178
- console.log(kit.mcp_calls.find((call) => call.tool === 'gtm_campaign_agent_proof'));
179
- console.log(memoryKit.mcp_calls.find((call) => call.tool === 'gtm_campaign_strategy_memory_status'));
180
- console.log(plan.mcpFlow.filter((step) =>
181
- ['gtm_provider_recipe_prepare', 'gtm_provider_route_activate'].includes(step.tool)
182
- ));
183
-
184
- // After an approved launch, keep review and delivery in the agent surface.
185
- const review = await signaliz.campaignBuilderAgent.reviewBuild('campaign_build_id', {
186
- limit: 100,
187
- });
188
- const finalStatus = await signaliz.campaignBuilderAgent.getBuildStatus('campaign_build_id');
189
- const reviewRows = await signaliz.campaignBuilderAgent.getBuildRows('campaign_build_id', {
190
- limit: 100,
191
- qualified: true,
192
- });
193
- const artifacts = await signaliz.campaignBuilderAgent.listBuildArtifacts('campaign_build_id');
194
- console.log(review.summary.readyForDeliveryApproval);
195
- ```
196
-
197
- The CLI can run the same request shape from a reusable JSON file, with flags
198
- overriding file fields:
199
-
200
- ```bash
201
- npx @signaliz/sdk campaign-agent init \
202
- --strategy-template non-medical-home-care \
203
- --target-count 250 \
204
- --use-local-leads \
205
- --with-byo-placeholder \
206
- --output-file campaign-request.json
207
-
208
- npx @signaliz/sdk campaign-agent kit \
209
- --strategy-template non-medical-home-care \
210
- --target-count 250 \
211
- --use-local-leads \
212
- --with-byo-placeholder \
213
- --json
214
-
215
- npx @signaliz/sdk campaign-agent memory-kit \
216
- --strategy-template non-medical-home-care \
217
- --target-count 250 \
218
- --use-local-leads \
219
- --source agency \
220
- --json
221
-
222
- npx @signaliz/sdk campaign-agent plan \
223
- --request-file campaign-request.json \
224
- --target-count 250 \
225
- --json
226
-
227
- npx @signaliz/sdk campaign-agent doctor \
228
- --request-file campaign-request.json \
229
- --json
230
-
231
- npx @signaliz/cli build "Build a strategy-template campaign for local operators" \
232
- --strategy-template non-medical-home-care \
233
- --target-count 25 \
234
- --use-local-leads
235
-
236
- npx @signaliz/sdk campaign-agent status campaign_build_id --json
237
- npx @signaliz/sdk campaign-agent review campaign_build_id --limit 100 --json
238
- npx @signaliz/sdk campaign-agent rows campaign_build_id --limit 100 --json
239
- ```
240
-
241
- Use the hosted MCP campaign-agent planner when you want Signaliz to return the
242
- same strategy-template runbook exposed through MCP:
243
-
244
- ```typescript
245
- const memoryStatus = await signaliz.gtm.campaignStrategyMemoryStatus({
246
- strategyTemplate: 'non-medical-home-care',
247
- includeSamples: true,
248
- });
249
-
250
- const hostedTemplate = await signaliz.gtm.campaignAgentRequestTemplate({
251
- goal: 'Build a reusable strategy-template campaign request',
252
- strategyTemplate: 'non-medical-home-care',
253
- targetCount: 250,
254
- includeLocalLeads: true,
255
- includeByoPlaceholder: true,
256
- privacyMode: 'workspace_only',
257
- });
258
-
259
- const hostedPlan = await signaliz.gtm.campaignAgentPlan({
260
- goal: 'Build a strategy-template campaign for local operators',
261
- strategyTemplate: 'non-medical-home-care',
262
- targetCount: 500,
263
- builtIns: ['lead_generation', 'local_leads', 'email_finding', 'email_verification', 'signals'],
264
- customTools: [{
265
- provider: 'workspace_mcp',
266
- layer: 'enrichment',
267
- tool: 'account_enrich',
268
- mcp: 'workspace-mcp',
269
- }],
270
- });
271
- ```
272
-
273
- ## GTM Kernel + Brain
274
-
275
- Use `signaliz.gtm` when an agent needs the substrate directly: workspace context, first-class campaign objects, ranked memory, Brain patterns/defaults, and provider routes.
276
-
277
- ```typescript
278
- const context = await signaliz.gtm.context({
279
- includeCampaigns: true,
280
- includeMemory: true,
281
- includeBrain: true,
282
- includeConnections: true,
283
- });
284
-
285
- const campaign = await signaliz.gtm.createCampaign({
286
- name: 'Series B Engineering Leaders',
287
- targetIcp: { personas: ['VP Engineering'], segment: 'Series B SaaS' },
288
- leadListRefs: [{ source: 'signaliz_cache' }],
289
- sendConfig: { daily_cap: 50 },
290
- providerLinks: [{ provider: 'instantly', providerCampaignId: 'instantly_123' }],
291
- });
292
-
293
- const seed = await signaliz.gtm.seedBrainDefaults({
294
- campaignId: campaign.campaign?.id,
295
- campaignBrief: 'Heads of engineering at Series B SaaS',
296
- layers: ['icp', 'lead_generation', 'copy_enrichment'],
297
- includeGlobal: true,
298
- });
299
- console.log({
300
- workspacePatterns: seed.seed?.evidence?.workspace_pattern_count,
301
- networkPatterns: seed.seed?.evidence?.global_pattern_count,
302
- activeRoutes: seed.seed?.recommended_defaults?.provider_strategy?.active_layer_routes?.length ?? 0,
303
- privacyPolicy: seed.privacy_policy,
304
- });
305
-
306
- const failures = await signaliz.gtm.failurePatterns({
307
- campaignId: campaign.campaign?.id,
308
- dimensions: ['provider_chain', 'icp_shape', 'copy_pattern'],
309
- days: 90,
310
- });
311
-
312
- const aggregate = await signaliz.gtm.aggregateBrainPatterns({
313
- patternTypes: ['icp', 'provider_chain', 'failure'],
314
- minWorkspaceCount: 3,
315
- minPrivacyK: 20,
316
- dryRun: true,
317
- });
318
-
319
- const calibrationAggregate = await signaliz.gtm.aggregateBrainCalibrations({
320
- dimensionTypes: ['email_domain', 'verification_source', 'provider_chain'],
321
- minWorkspaceCount: 3,
322
- minPrivacyK: 20,
323
- dryRun: true,
324
- });
325
-
326
- const learningCycle = await signaliz.gtm.learningCyclePlan({
327
- campaignId: campaign.campaign?.id,
328
- campaignBrief: 'Heads of engineering at Series B SaaS',
329
- includeNetwork: true,
330
- writeMode: 'dry_run',
331
- });
332
-
333
- const campaignLearning = await signaliz.gtm.campaignLearningStatus({
334
- campaignId: campaign.campaign?.id,
335
- campaignBuildId: campaign.campaign?.campaign_build_id,
336
- writeMode: 'dry_run',
337
- });
338
-
339
- const readyLanes = campaignLearning.learning_lanes?.filter((lane) => lane.state === 'ready') ?? [];
340
- const networkLane = campaignLearning.learning_lanes?.find((lane) => lane.id === 'network_patterns');
341
-
342
- const memory = await signaliz.gtm.searchMemory({
343
- query: 'subject lines that worked for SaaS engineering leaders',
344
- outcomeType: 'meeting_booked',
345
- targetIcp: { persona: 'Head of Engineering', segment: 'Series B SaaS' },
346
- layers: ['copy_enrichment', 'sender'],
347
- limit: 5,
348
- });
349
- const topMemory = memory.memories?.[0];
350
- console.log({
351
- title: topMemory?.title,
352
- outcomeClass: Array.isArray(topMemory?.match_reasons) ? undefined : topMemory?.match_reasons?.outcome_class,
353
- requestedOutcomeMatch: Array.isArray(topMemory?.match_reasons) ? false : topMemory?.match_reasons?.requested_outcome_match,
354
- outcomeScore: Array.isArray(topMemory?.match_reasons) ? undefined : topMemory?.match_reasons?.outcome_score,
355
- });
356
-
357
- await signaliz.gtm.createIntegrationRecipe({
358
- providerId: 'clay_webhook',
359
- providerName: 'Clay Webhook',
360
- layerCapabilities: ['find_company', 'find_people', 'lead_generation'],
361
- invocationType: 'webhook',
362
- authStrategy: 'webhook_secret',
363
- endpointUrl: 'https://hooks.example.com/clay',
364
- status: 'active',
365
- });
366
-
367
- const routeProof = await signaliz.gtm.previewLayerRoute({
368
- layer: 'lead_generation',
369
- campaignId: campaign.campaign?.id,
370
- sampleRecords: [{ email: 'buyer@example.com' }],
371
- context: { source: 'sdk_quickstart' },
372
- });
373
-
374
- console.log(routeProof.next_action);
375
- console.log(failures.failure_patterns?.[0]?.recommendation?.next_step);
376
- console.log({ readyLanes: readyLanes.length, networkPolicy: networkLane?.raw_data_policy });
377
- ```
378
-
379
- Provider routes can point to Signaliz native tools, Clay webhooks, Airbyte,
380
- Nango-managed customer APIs, Apollo, AI Ark, Octave, Instantly, HeyReach,
381
- Smartlead, custom APIs, custom MCP servers, or manual review gates. Nango routes
382
- keep customer credentials in Nango while Signaliz stores only the workspace
383
- connection reference and approval/audit context.
384
-
385
- ### Nango-Managed API Tools
386
-
387
- Use Nango when a workspace brings its own provider account and the action should
388
- run through Nango-managed auth. If the vendor is not connected yet, create a
389
- Connect session and send the user to the returned auth link. Then list tools for
390
- the saved workspace connection, dry-run the action, and confirm the write only
391
- after the preview is approved.
392
-
393
- ```typescript
394
- const session = await signaliz.gtm.createNangoConnectSession({
395
- providerId: 'apollo',
396
- integrationId: 'apollo',
397
- });
398
- console.log(session.connect_link);
399
-
400
- const tools = await signaliz.gtm.listNangoTools({
401
- workspaceConnectionId: 'workspace_conn_nango_hubspot',
402
- providerConfigKey: 'hubspot',
403
- includeRaw: false,
404
- });
405
-
406
- const preview = await signaliz.gtm.callNangoTool({
407
- workspaceConnectionId: 'workspace_conn_nango_hubspot',
408
- actionName: 'upsert-contact',
409
- input: { email: 'buyer@example.com', company: 'Acme' },
410
- dryRun: true,
411
- confirm: false,
412
- });
413
-
414
- if (preview.ready_for_confirmation) {
415
- const confirmed = await signaliz.gtm.callNangoTool({
416
- workspaceConnectionId: 'workspace_conn_nango_hubspot',
417
- actionName: 'upsert-contact',
418
- input: { email: 'buyer@example.com', company: 'Acme' },
419
- dryRun: false,
420
- confirm: true,
421
- async: true,
422
- });
423
-
424
- if (confirmed.action_id || confirmed.status_url) {
425
- await signaliz.gtm.getNangoActionResult({
426
- actionId: confirmed.action_id,
427
- statusUrl: confirmed.status_url,
428
- });
429
- }
430
- }
431
- ```
432
-
433
- The Ops namespace exposes the same Nango bridge, plus a one-call helper backed
434
- by `nango_mcp_tool_call_and_wait` when an agent needs the result packet
435
- immediately:
436
-
437
- ```typescript
438
- const nangoResult = await signaliz.ops.callNangoToolAndWait({
439
- workspaceConnectionId: 'workspace_conn_nango_hubspot',
440
- actionName: 'upsert-contact',
441
- input: { email: 'buyer@example.com', company: 'Acme' },
442
- dryRun: false,
443
- confirm: true,
444
- maxPolls: 6,
445
- });
446
- console.log(nangoResult.result);
447
- ```
448
-
449
- For recurring Ops, use the schedule-and-wait helper to activate the Op and
450
- retrieve the first result packet in one call. This maps to native MCP
451
- `ops_schedule_and_wait`:
452
-
453
- ```typescript
454
- const recurring = await signaliz.ops.scheduleAndWait({
455
- prompt: 'Monitor strategic accounts daily and send new funding signals to Slack',
456
- destinations: [{ type: 'slack' }],
457
- wakeOnEvents: ['company_funded'],
458
- confirmSpend: true,
459
- limit: 100,
460
- });
461
- console.log(recurring.results?.results);
462
- ```
463
-
464
- For Nango-backed recurrence, the Ops SDK sends the natural Nango fields through
465
- native `ops_nango_schedule` / `ops_nango_schedule_and_wait`:
466
-
467
- ```typescript
468
- const hubspotOp = await signaliz.ops.scheduleNangoActionAndWait({
469
- prompt: 'Monitor strategic accounts daily and upsert approved rows to HubSpot',
470
- workspaceConnectionId: 'workspace_conn_nango_hubspot',
471
- providerConfigKey: 'hubspot',
472
- actionName: 'upsert-contact',
473
- writeConfirmed: true,
474
- confirmSpend: true,
475
- maxPolls: 6,
476
- limit: 100,
477
- });
478
- console.log(hubspotOp.results?.results);
479
- ```
480
-
481
- ### GTM Kernel Smoke Test
482
-
483
- After strategy imports or Campaign Builder backfills, run the read-only/dry-run
484
- smoke harness before launching spendful provider work:
485
-
486
- Run the internal smoke harness with `SIGNALIZ_API_KEY` and
487
- `--campaign-build-id <campaign_build_id>` or `--campaign-id <campaign_id>`.
488
-
489
- The receipt includes campaign/build/workspace IDs, execution stage, feedback and
490
- memory counts, workspace bootstrap gate readiness, Brain phase readiness,
491
- blockers/warnings, the next safe MCP action, and explicit
492
- no-spend/no-write/no-sender/no-delivery confirmation.
493
-
494
- ## MCP/Ops Control Plane
495
-
496
- Fresh-enrichment throughput is now higher across every plan: Free 60/min,
497
- Builder 300/min, Team 600/min, Agency 1,000/min, and Pay-As-You-Go 1,000/min,
498
- with a 5,000/hour per-workspace safety cap. Cache hits, API/MCP reads, and
499
- cache search do not count against those
500
- fresh-enrichment ceilings.
501
-
502
- ```typescript
503
- // Workspace and platform health
504
- const workspace = await signaliz.getWorkspace();
505
- const health = await signaliz.getPlatformHealth();
506
-
507
- // Tool/capability discovery
508
- const tools = await signaliz.listTools();
509
- const opsMatches = await signaliz.discover('campaign build with webhook delivery', 'ops');
510
-
511
- // North-star Ops loop: recommend, dry-run, schedule/run, poll, retrieve
512
- const autopilot = await signaliz.ops.autopilot();
513
- console.log(autopilot.primaryMotion?.operatingPacket?.northStar);
514
- console.log(autopilot.primaryMotion?.operatingPacket?.nangoRoute?.dryRunArguments);
515
-
516
- const plan = await signaliz.ops.plan(
517
- 'Monitor stripe.com and plaid.com every day and Slack me new hiring signals',
518
- );
519
- console.log(plan.executionContract?.sequence.map((step) => step.tool).join(' -> '));
520
- console.log(plan.executionContract?.nangoRoute?.writeGate);
521
- const nangoPreview = await signaliz.ops.execute({
522
- prompt: 'Build 50 approved ICP leads and upsert them to HubSpot',
523
- destinations: [{
524
- type: 'nango',
525
- connectionId: 'workspace_conn_nango_hubspot',
526
- providerConfigKey: 'hubspot',
527
- nangoConnectionId: 'connection_123',
528
- actionName: 'upsert-contact',
529
- }],
530
- dry_run: true,
531
- });
532
- const op = await signaliz.ops.schedule({
533
- prompt: plan.goal,
534
- blueprint: plan.blueprint,
535
- target_count: plan.target_count,
536
- cadence: plan.cadence === 'manual' ? 'daily' : plan.cadence,
537
- timezone: 'America/Phoenix',
538
- wakeOnEvents: ['company_funded', 'crm.updated'],
539
- confirm_spend: true,
540
- });
541
- await signaliz.ops.run(op.op_id);
542
- const status = await signaliz.ops.status(op.op_id);
543
- const results = await signaliz.ops.results({ op_id: op.op_id, limit: 100 });
544
-
545
- // Spendful lead generation requires explicit approval
546
- try {
547
- await signaliz.leads.generate({
548
- prompt: 'VP Sales at B2B SaaS companies, 50-500 employees',
549
- maxLeads: 100,
550
- });
551
- } catch (error) {
552
- // APPROVAL_REQUIRED includes estimated_credits and retry_arguments in details.
553
- }
554
-
555
- const leadJob = await signaliz.leads.generate({
556
- prompt: 'VP Sales at B2B SaaS companies, 50-500 employees',
557
- maxLeads: 100,
558
- confirmSpend: true,
559
- });
560
- const leadStatus = await signaliz.leads.checkStatus(leadJob.jobId);
561
- ```
562
-
563
- ## Custom AI Enrichment - Multi Model
564
-
565
- Use the Signaliz-hosted default model and attach images, PDFs, audio, or video when needed. The response includes model readback metadata for auditing.
566
-
567
- ```typescript
568
- const result = await signaliz.ai.multiModel({
569
- prompt: 'Research {{company_name}} and score whether they match our ICP.',
570
- records: [{ company_name: 'Stripe', company_domain: 'stripe.com' }],
571
- outputFields: [
572
- { name: 'fit_score', type: 'number', description: 'ICP fit from 1-10' },
573
- { name: 'reasoning', type: 'text', description: 'Short evidence-backed rationale' },
574
- ],
575
- });
576
-
577
- console.log(result.model, result.results);
578
- ```
579
-
580
- ## Campaigns API
581
-
582
- ### `campaigns.build(request, options?)`
583
-
584
- Start an async campaign build. Returns immediately with a `campaignBuildId`.
585
-
586
- ```typescript
587
- const result = await signaliz.campaigns.build(
588
- {
589
- name: 'Test',
590
- prompt: 'Find CFOs at mid-market healthcare companies',
591
- dryRun: true,
592
- allowDownscale: true,
593
- confirmSpend: true,
594
- },
595
- { idempotencyKey: 'my-unique-key-123' } // prevent duplicate builds
596
- );
597
- ```
598
-
599
- When `dryRun: true` is passed, the result is a plan (`status: 'dry_run'`) with
600
- `campaignBuildId: null`, planned target count, estimated credits, and duration.
601
-
602
- ### `campaigns.status(id)`
603
-
604
- Get a concise status snapshot — ideal for polling.
605
-
606
- ### `campaigns.get(id)`
607
-
608
- Get the full campaign build record including delivery details.
609
-
610
- ### `campaigns.rows(id, options?)`
611
-
612
- Retrieve paginated rows from a completed build.
613
-
614
- ```typescript
615
- const page = await signaliz.campaigns.rows(buildId, {
616
- limit: 50,
617
- segment: 'signal',
618
- qualified: true,
619
- });
620
- // page.rows, page.nextCursor, page.hasMore
621
- ```
622
-
623
- ### `campaigns.artifacts(id)`
624
-
625
- List all artifacts (CSV exports, signed URLs).
626
-
627
- ### `campaigns.cancel(id, reason?)`
628
-
629
- Cancel a queued or running build.
630
-
631
- ### `campaigns.wait(id, options?)`
632
-
633
- Poll until completed, failed, or canceled.
634
-
635
- ```typescript
636
- const final = await signaliz.campaigns.wait(buildId, {
637
- intervalMs: 3000,
638
- timeoutMs: 300_000,
639
- onProgress: (s) => console.log(s.status, s.recordsProcessed),
640
- });
641
- ```
642
-
643
- ## Other Resources
644
-
645
- ```typescript
646
- // Find and verify an email with the V3 waterfall
647
- const email = await signaliz.emails.find({
648
- fullName: 'Jane Smith',
649
- companyDomain: 'stripe.com',
19
+ const signaliz = new Signaliz({
20
+ apiKey: process.env.SIGNALIZ_API_KEY,
650
21
  });
651
22
 
652
- // Submit batch email jobs at scale, then poll status
653
- const job = await signaliz.emails.verifyBatch([
654
- 'jane@example.com',
655
- { email: 'sam@example.com' },
656
- ]);
657
- const status = await signaliz.emails.checkStatus(job.jobId);
658
-
659
- // Local-business lead generation
660
- const localJob = await signaliz.leads.generateLocal({
661
- prompt: 'dentists in Phoenix, AZ',
662
- targetVerified: 50,
663
- confirmSpend: true,
23
+ const found = await signaliz.findEmail({
24
+ companyDomain: 'example.com',
25
+ fullName: 'Jane Doe',
26
+ // Optional: bypass cached email and verification data for a fresh-provider run.
27
+ skipCache: true,
664
28
  });
665
29
 
666
- // Company signals
667
- const signals = await signaliz.signals.enrich({
668
- companyName: 'Stripe',
669
- researchPrompt: 'Find recent hiring activities',
670
- });
30
+ const verified = await signaliz.verifyEmail(found.email!);
671
31
 
672
- // Systems (pipelines)
673
- const system = await signaliz.systems.create({
674
- name: 'Email Pipeline',
675
- capabilities: ['mcp_input', 'find_emails_with_verification', 'mcp_output'],
32
+ const signals = await signaliz.enrichCompanySignals({
33
+ companyDomain: 'example.com',
34
+ researchPrompt: 'expansion priorities',
676
35
  });
677
36
 
678
- // HTTP proxy
679
- const response = await signaliz.http.request({
680
- url: 'https://api.example.com/data',
681
- method: 'GET',
37
+ const copy = await signaliz.signalToCopy({
38
+ companyDomain: 'example.com',
39
+ personName: 'Jane Doe',
40
+ title: 'VP Sales',
41
+ campaignOffer: 'pipeline intelligence',
42
+ researchPrompt: 'expansion priorities',
682
43
  });
683
-
684
- // Ops routines and output sinks
685
- const sinks = await signaliz.ops.listOutputSinks();
686
- const routines = await signaliz.ops.listRoutines({ status: 'active' });
687
- ```
688
-
689
- ## MCP Setup
690
-
691
- ```bash
692
- npx -p @signaliz/sdk signaliz-mcp
693
44
  ```
694
45
 
695
- The setup helper writes a local stdio MCP config that runs `@signaliz/mcp-server`
696
- with `SIGNALIZ_API_KEY` in the environment. It does not put API keys in a
697
- query-string URL.
46
+ All four products support bounded batch execution over the same REST endpoints.
47
+ Results stay in input order, failures are isolated per item, and concurrency is
48
+ limited to `1-50` (default `10`):
698
49
 
699
- ## Authentication
700
-
701
- ### API Key (simplest)
702
- ```typescript
703
- const signaliz = new Signaliz({ apiKey: 'sk_...' });
50
+ ```ts
51
+ const verifiedBatch = await signaliz.verifyEmails(emails, { concurrency: 20 });
52
+ const foundBatch = await signaliz.findEmails(contacts, { concurrency: 20 });
53
+ const signalBatch = await signaliz.enrichCompanies(companies, { concurrency: 5 });
54
+ const copyBatch = await signaliz.createSignalCopyBatch(copyRequests, { concurrency: 5 });
704
55
  ```
705
56
 
706
- ### M2M OAuth
707
- ```typescript
708
- const signaliz = new Signaliz({
709
- clientId: process.env.SIGNALIZ_CLIENT_ID,
710
- clientSecret: process.env.SIGNALIZ_CLIENT_SECRET,
711
- });
712
- ```
713
-
714
- ## Error Handling
715
-
716
- ```typescript
717
- import { Signaliz, SignalizError } from '@signaliz/sdk';
718
-
719
- try {
720
- await signaliz.campaigns.build({ name: 'Test', prompt: '...' });
721
- } catch (e) {
722
- if (e instanceof SignalizError) {
723
- console.log(e.errorType); // 'rate_limited' | 'validation' | 'timeout' | ...
724
- console.log(e.retryAfter); // seconds to wait (for 429s)
725
- console.log(e.isRetryable); // boolean — SDK retries 429 and 5xx automatically
726
- }
727
- }
728
- ```
57
+ Each batch accepts up to 5,000 items. Company Signal Enrichment transparently
58
+ resumes long-running research through the same `/company-signals` endpoint;
59
+ callers never need an internal Trigger.dev status URL.
729
60
 
730
- ## License
61
+ Company Signal Enrichment defaults `online` and `enableDeepSearch` to `true`
62
+ unless the caller explicitly disables them. Signal to Copy AI returns three
63
+ complete, evidence-backed email variations when supported signals are available.
64
+ Unclassified evidence is returned by signal enrichment but is not used to
65
+ generate outreach copy.
731
66
 
732
- MIT
67
+ `listTools()` and `health()` are connection helpers, not additional products.