@getnexorai/sdk 0.1.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nexor
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,281 @@
1
+ # @getnexorai/sdk
2
+
3
+ Official JavaScript SDK for [Nexor](https://www.getnexor.ai) — AI-led omni-channel contactability for your leads. One package, two things:
4
+
5
+ 1. **REST client.** `nexor.init({ apiKey })` then `nexor.createLead(...)`, `nexor.getLead(...)`, `nexor.sendMessage(...)`, etc. Works in Node 18+ and modern browsers.
6
+ 2. **Embeddable chat widget.** `nexor.initChat({ workflowId })` drops a chat bubble in the bottom-right of any web page. Visitors chat; you get a real Nexor lead + AI-driven conversation; cadence follow-ups happen on WhatsApp/email/voice as usual.
7
+
8
+ Full API reference: https://docs.getnexor.ai
9
+
10
+ ---
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ npm install @getnexorai/sdk
16
+ # or
17
+ pnpm add @getnexorai/sdk
18
+ # or
19
+ yarn add @getnexorai/sdk
20
+ ```
21
+
22
+ Or use it script-tag-style with no build:
23
+
24
+ ```html
25
+ <script src="https://unpkg.com/@getnexorai/sdk/dist/nexor.iife.js"></script>
26
+ <script>
27
+ Nexor.init({ apiKey: "nxr_live_…" });
28
+ </script>
29
+ ```
30
+
31
+ ---
32
+
33
+ ## Quick start — push a lead from Node
34
+
35
+ ```js
36
+ import nexor from "@getnexorai/sdk";
37
+
38
+ nexor.init({ apiKey: process.env.NEXOR_API_KEY });
39
+
40
+ const { lead, workflow_run } = await nexor.createLead({
41
+ first_name: "Ada",
42
+ last_name: "Lovelace",
43
+ email: "ada@example.com",
44
+ phone: "+1 555 0100",
45
+ workflow_id: "your-workflow-uuid",
46
+ metadata: { plan: "trial", utm_source: "google" },
47
+ });
48
+
49
+ console.log("Created lead:", lead.id);
50
+ console.log("Workflow run:", workflow_run?.id);
51
+ ```
52
+
53
+ That's it. Nexor's AI agent will now reach out on the channels configured in the workflow.
54
+
55
+ ---
56
+
57
+ ## Quick start — embed a chat widget
58
+
59
+ ```html
60
+ <script src="https://unpkg.com/@getnexorai/sdk/dist/nexor.iife.js"></script>
61
+ <script>
62
+ Nexor.init({ apiKey: "nxr_live_…" });
63
+
64
+ Nexor.initChat({
65
+ workflowId: "your-workflow-uuid",
66
+ title: "Talk to our team",
67
+ accentColor: "#4f46e5",
68
+ systemPrompt: "You are a friendly sales assistant for Acme Corp.",
69
+ capture: { fields: ["first_name", "email"] },
70
+ });
71
+ </script>
72
+ ```
73
+
74
+ A chat bubble appears in the bottom-right. Visitors fill the (configurable) capture form, chat with your AI agent, and become real leads in your Nexor account — primed for follow-up on WhatsApp/email/voice.
75
+
76
+ ---
77
+
78
+ ## API
79
+
80
+ ### Initialisation
81
+
82
+ ```ts
83
+ nexor.init({
84
+ apiKey: string; // required
85
+ baseUrl?: string; // default "https://api.getnexor.ai"
86
+ timeoutMs?: number; // default 30_000
87
+ maxRetries?: number; // default 2 (retries on 429 + 5xx + network errors)
88
+ fetch?: typeof fetch; // override (e.g. for tests / Node <18)
89
+ userAgentSuffix?: string;
90
+ });
91
+ ```
92
+
93
+ For multi-tenant / server-side use where a singleton doesn't fit, instantiate the client directly:
94
+
95
+ ```ts
96
+ import { NexorClient } from "@getnexorai/sdk";
97
+
98
+ const client = new NexorClient({ apiKey });
99
+ await client.createLead({ first_name: "Ada", … });
100
+ ```
101
+
102
+ ### Leads
103
+
104
+ ```ts
105
+ nexor.createLead(input)
106
+ nexor.createLeadsBulk(inputs) // up to 1,000 per call
107
+ nexor.updateLead(leadId, updates) // metadata is shallow-merged server-side
108
+ nexor.getLead(leadId) // lead + collected variables + per-channel engagement
109
+ nexor.getLeadHistory(leadId, { channel, limit, offset })
110
+
111
+ nexor.syncLeadTags({ lead_id | email, tags }) // tags param is the full active set; [] clears
112
+
113
+ nexor.isLeadPaused(leadId, { workflow_id })
114
+ nexor.stopAutomation(leadId, { workflow_id }) // human takeover
115
+ nexor.resumeAutomation(leadId, { workflow_id, resume_cadence })
116
+
117
+ nexor.listLeadMeetings(leadId, { status })
118
+ ```
119
+
120
+ `createLead` accepts an optional `force_first_message: { channel, content, subject?, sender_id? }` that pushes the very first message synchronously (WhatsApp or email) rather than waiting for cadence.
121
+
122
+ ### Workflows / Campaigns / Templates
123
+
124
+ ```ts
125
+ nexor.listWorkflows()
126
+ nexor.listCampaigns()
127
+ nexor.listTemplates({ status, category })
128
+ ```
129
+
130
+ ### Messages
131
+
132
+ ```ts
133
+ nexor.sendMessage({
134
+ lead_id, workflow_id,
135
+ channel: "whatsapp" | "email" | "call",
136
+ content?: string, // free-form text (whatsapp/email)
137
+ html?: string, // email body
138
+ subject?: string, // email subject
139
+ template_id?: string, // whatsapp template (alternative to content)
140
+ components?: unknown, // whatsapp template parameters
141
+ begin_message?: string, // first utterance for outbound calls
142
+ });
143
+ ```
144
+
145
+ ### Meetings
146
+
147
+ ```ts
148
+ nexor.createMeeting({ lead_email, title, starts_at, duration_minutes, … });
149
+ nexor.createMeetingNotes({ lead_email, notes, transcript_text, summary, action_items, … });
150
+ ```
151
+
152
+ ---
153
+
154
+ ## Chat widget
155
+
156
+ ```ts
157
+ nexor.initChat({
158
+ // Required
159
+ workflowId: string;
160
+
161
+ // Branding
162
+ title?: string; // header text
163
+ subtitle?: string; // small line below header
164
+ greeting?: string; // first bot message
165
+ accentColor?: string; // hex, default "#111827"
166
+ accentTextColor?: string; // hex, default "#ffffff"
167
+ showBranding?: boolean; // "Powered by Nexor" footer, default true
168
+
169
+ // Behaviour
170
+ position?: "bottom-right" | "bottom-left";
171
+ openOnLoad?: boolean;
172
+ container?: HTMLElement; // default document.body
173
+
174
+ // Per-widget prompt overrides — forwarded to the agent on every turn
175
+ systemPrompt?: string;
176
+ clientPrompt?: string;
177
+
178
+ // Lead linking
179
+ lead?: { first_name?, last_name?, email?, phone?, metadata? }; // pre-known visitor → skips capture
180
+ capture?: {
181
+ fields?: ("first_name" | "last_name" | "email" | "phone")[]; // default ["first_name", "email"]
182
+ mode?: "before" | "skip"; // default "before"
183
+ label?: string;
184
+ submitLabel?: string;
185
+ };
186
+ metadata?: Record<string, unknown>; // attached to every turn (page URL, UTM, …)
187
+
188
+ // Callbacks
189
+ onOpen?: () => void;
190
+ onClose?: () => void;
191
+ onMessage?: ({ role, text }) => void;
192
+ onLeadCaptured?: (leadId) => void;
193
+ onError?: (err) => void;
194
+ });
195
+ ```
196
+
197
+ Returns a handle:
198
+
199
+ ```ts
200
+ const chat = nexor.initChat({ … });
201
+
202
+ chat.open();
203
+ chat.close();
204
+ chat.toggle();
205
+ await chat.send("Hello from JS"); // programmatic message
206
+ chat.destroy();
207
+ chat.getSessionId(); // stable per-browser id (persisted to localStorage)
208
+ ```
209
+
210
+ ### How it works under the hood
211
+
212
+ Each turn POSTs to `/api/public/chat` with:
213
+
214
+ ```json
215
+ {
216
+ "workflow_id": "…",
217
+ "session_id": "sess_…", // generated + persisted by the SDK
218
+ "message": "user text",
219
+ "system_prompt": "…", // optional override
220
+ "client_prompt": "…", // optional override
221
+ "lead": { "first_name": "Ada", "email": "ada@example.com" },
222
+ "metadata": { "page_url": "…" }
223
+ }
224
+ ```
225
+
226
+ The server matches/creates a `web-chat` lead, runs the workflow's AI agent, and returns:
227
+
228
+ ```json
229
+ { "success": true, "reply": "…", "session_id": "…", "lead_id": "…", "workflow_run_id": "…" }
230
+ ```
231
+
232
+ Subsequent turns reuse the same session and lead — including across page reloads.
233
+
234
+ ---
235
+
236
+ ## Errors
237
+
238
+ All API failures throw a `NexorAPIError` (or one of its subclasses):
239
+
240
+ ```ts
241
+ import { NexorAPIError, NexorAuthError, NexorValidationError, NexorNetworkError } from "@getnexorai/sdk";
242
+
243
+ try {
244
+ await nexor.createLead({ first_name: "" });
245
+ } catch (err) {
246
+ if (err instanceof NexorValidationError) {
247
+ console.error("Bad input:", err.message);
248
+ } else if (err instanceof NexorAuthError) {
249
+ console.error("API key rejected");
250
+ } else if (err instanceof NexorAPIError) {
251
+ console.error(`HTTP ${err.status}: ${err.message}`, err.requestId);
252
+ } else if (err instanceof NexorNetworkError) {
253
+ console.error("Network problem:", err.cause);
254
+ }
255
+ }
256
+ ```
257
+
258
+ 429 and 5xx responses are automatically retried with exponential backoff (configurable via `maxRetries`). Honors `Retry-After`.
259
+
260
+ ---
261
+
262
+ ## Examples
263
+
264
+ - [`examples/node-create-lead.mjs`](./examples/node-create-lead.mjs) — push leads from a Node script.
265
+ - [`examples/browser-chat.html`](./examples/browser-chat.html) — embed the chat widget via script tag.
266
+
267
+ ---
268
+
269
+ ## Building from source
270
+
271
+ ```bash
272
+ npm install
273
+ npm run typecheck
274
+ npm run build # outputs dist/{index.js,index.cjs,chat.js,chat.cjs,nexor.iife.js} + .d.ts
275
+ ```
276
+
277
+ ---
278
+
279
+ ## License
280
+
281
+ MIT