@graph8/sdk 0.5.3 → 0.7.2
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 +13 -5
- package/dist/index.d.mts +608 -68
- package/dist/index.d.ts +608 -68
- package/dist/index.js +940 -907
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +930 -906
- package/dist/index.mjs.map +1 -1
- package/dist/react.d.mts +483 -52
- package/dist/react.d.ts +483 -52
- package/dist/react.js +910 -905
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +910 -905
- package/dist/react.mjs.map +1 -1
- package/package.json +24 -7
package/dist/index.js
CHANGED
|
@@ -20,7 +20,16 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
-
|
|
23
|
+
G8Error: () => G8Error,
|
|
24
|
+
KNOWN_WEBHOOK_EVENTS: () => KNOWN_WEBHOOK_EVENTS,
|
|
25
|
+
WebhookSignatureError: () => WebhookSignatureError,
|
|
26
|
+
backoffDelayMs: () => backoffDelayMs,
|
|
27
|
+
constructEvent: () => constructEvent,
|
|
28
|
+
g8: () => g8,
|
|
29
|
+
isRetryableStatus: () => isRetryableStatus,
|
|
30
|
+
paginate: () => paginate,
|
|
31
|
+
parseRetryAfter: () => parseRetryAfter,
|
|
32
|
+
request: () => request
|
|
24
33
|
});
|
|
25
34
|
module.exports = __toCommonJS(index_exports);
|
|
26
35
|
|
|
@@ -272,11 +281,11 @@ var createCalendarClient = (apiUrl) => {
|
|
|
272
281
|
return data.slots || data.data || [];
|
|
273
282
|
},
|
|
274
283
|
/** Book a meeting programmatically. */
|
|
275
|
-
async book(
|
|
284
|
+
async book(request2) {
|
|
276
285
|
const resp = await fetch(`${baseUrl}/appointments/public/bookings`, {
|
|
277
286
|
method: "POST",
|
|
278
287
|
headers: { "Content-Type": "application/json" },
|
|
279
|
-
body: JSON.stringify(
|
|
288
|
+
body: JSON.stringify(request2)
|
|
280
289
|
});
|
|
281
290
|
if (!resp.ok) return null;
|
|
282
291
|
const data = await resp.json();
|
|
@@ -292,54 +301,174 @@ var createCalendarClient = (apiUrl) => {
|
|
|
292
301
|
};
|
|
293
302
|
};
|
|
294
303
|
|
|
304
|
+
// src/http.ts
|
|
305
|
+
var G8Error = class _G8Error extends Error {
|
|
306
|
+
constructor(args) {
|
|
307
|
+
super(args.message);
|
|
308
|
+
this.name = "G8Error";
|
|
309
|
+
this.status = args.status;
|
|
310
|
+
this.type = args.type;
|
|
311
|
+
this.code = args.code;
|
|
312
|
+
this.requestId = args.requestId;
|
|
313
|
+
this.detail = args.detail;
|
|
314
|
+
this.retryable = args.retryable ?? false;
|
|
315
|
+
Object.setPrototypeOf(this, _G8Error.prototype);
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
function isRetryableStatus(status) {
|
|
319
|
+
return status === 429 || status >= 500 && status <= 599;
|
|
320
|
+
}
|
|
321
|
+
function parseRetryAfter(header, nowMs = Date.now()) {
|
|
322
|
+
if (!header) return null;
|
|
323
|
+
const secs = Number(header);
|
|
324
|
+
if (Number.isFinite(secs) && secs >= 0) return Math.round(secs * 1e3);
|
|
325
|
+
const dateMs = Date.parse(header);
|
|
326
|
+
if (!Number.isNaN(dateMs)) {
|
|
327
|
+
const delta = dateMs - nowMs;
|
|
328
|
+
return delta > 0 ? delta : 0;
|
|
329
|
+
}
|
|
330
|
+
return null;
|
|
331
|
+
}
|
|
332
|
+
function backoffDelayMs(attempt, baseMs = 200, rand = Math.random) {
|
|
333
|
+
const expo = Math.min(baseMs * 2 ** attempt, 1e4);
|
|
334
|
+
return Math.floor(expo / 2 + rand() * (expo / 2));
|
|
335
|
+
}
|
|
336
|
+
function defaultSleep(ms) {
|
|
337
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
338
|
+
}
|
|
339
|
+
function buildQuery(query) {
|
|
340
|
+
if (!query) return "";
|
|
341
|
+
const qs = new URLSearchParams();
|
|
342
|
+
for (const [k, v] of Object.entries(query)) {
|
|
343
|
+
if (v != null) qs.set(k, String(v));
|
|
344
|
+
}
|
|
345
|
+
const s = qs.toString();
|
|
346
|
+
return s ? `?${s}` : "";
|
|
347
|
+
}
|
|
348
|
+
async function toG8Error(resp) {
|
|
349
|
+
let body = void 0;
|
|
350
|
+
try {
|
|
351
|
+
const text = await resp.text();
|
|
352
|
+
body = text ? JSON.parse(text) : void 0;
|
|
353
|
+
} catch {
|
|
354
|
+
body = void 0;
|
|
355
|
+
}
|
|
356
|
+
const env = body ?? {};
|
|
357
|
+
const message = typeof env.message === "string" && env.message || typeof env.error === "string" && env.error || `Request failed with status ${resp.status}`;
|
|
358
|
+
return new G8Error({
|
|
359
|
+
message,
|
|
360
|
+
status: resp.status,
|
|
361
|
+
type: typeof env.type === "string" && env.type || typeof env.error === "string" && env.error || "api_error",
|
|
362
|
+
code: typeof env.code === "string" ? env.code : String(resp.status),
|
|
363
|
+
requestId: typeof env.request_id === "string" && env.request_id || resp.headers.get("x-request-id") || void 0,
|
|
364
|
+
detail: env.detail,
|
|
365
|
+
retryable: isRetryableStatus(resp.status)
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
async function request(baseUrl, path, apiKey, opts = {}) {
|
|
369
|
+
const {
|
|
370
|
+
method = "GET",
|
|
371
|
+
body,
|
|
372
|
+
headers = {},
|
|
373
|
+
query,
|
|
374
|
+
idempotencyKey,
|
|
375
|
+
maxRetries = 2,
|
|
376
|
+
retryBaseMs = 200,
|
|
377
|
+
signal,
|
|
378
|
+
fetchImpl = fetch,
|
|
379
|
+
sleepImpl = defaultSleep
|
|
380
|
+
} = opts;
|
|
381
|
+
const url = baseUrl.replace(/\/+$/, "") + path + buildQuery(query);
|
|
382
|
+
const finalHeaders = {
|
|
383
|
+
"Content-Type": "application/json",
|
|
384
|
+
Authorization: `Bearer ${apiKey}`,
|
|
385
|
+
...headers
|
|
386
|
+
};
|
|
387
|
+
if (idempotencyKey) finalHeaders["Idempotency-Key"] = idempotencyKey;
|
|
388
|
+
let attempt = 0;
|
|
389
|
+
for (; ; ) {
|
|
390
|
+
let resp;
|
|
391
|
+
try {
|
|
392
|
+
resp = await fetchImpl(url, {
|
|
393
|
+
method,
|
|
394
|
+
headers: finalHeaders,
|
|
395
|
+
body: body == null ? void 0 : JSON.stringify(body),
|
|
396
|
+
signal
|
|
397
|
+
});
|
|
398
|
+
} catch (err) {
|
|
399
|
+
if (attempt < maxRetries) {
|
|
400
|
+
await sleepImpl(backoffDelayMs(attempt, retryBaseMs));
|
|
401
|
+
attempt++;
|
|
402
|
+
continue;
|
|
403
|
+
}
|
|
404
|
+
throw new G8Error({
|
|
405
|
+
message: `Network error: ${err?.message ?? "request failed"}`,
|
|
406
|
+
status: 0,
|
|
407
|
+
type: "network_error",
|
|
408
|
+
retryable: true
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
if (resp.ok) {
|
|
412
|
+
const text = await resp.text();
|
|
413
|
+
return text ? JSON.parse(text) : void 0;
|
|
414
|
+
}
|
|
415
|
+
if (isRetryableStatus(resp.status) && attempt < maxRetries) {
|
|
416
|
+
const retryAfter = parseRetryAfter(resp.headers.get("retry-after"));
|
|
417
|
+
const delay = retryAfter != null ? retryAfter : backoffDelayMs(attempt, retryBaseMs);
|
|
418
|
+
await sleepImpl(delay);
|
|
419
|
+
attempt++;
|
|
420
|
+
continue;
|
|
421
|
+
}
|
|
422
|
+
throw await toG8Error(resp);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
async function* paginate(fetchPage) {
|
|
426
|
+
let cursor = void 0;
|
|
427
|
+
for (; ; ) {
|
|
428
|
+
const page = await fetchPage(cursor);
|
|
429
|
+
for (const item of page.data ?? []) yield item;
|
|
430
|
+
const next = page.pagination?.next_cursor;
|
|
431
|
+
if (!next) break;
|
|
432
|
+
cursor = next;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
295
436
|
// src/enrich.ts
|
|
296
437
|
var DEFAULT_API6 = "https://be.graph8.com";
|
|
297
438
|
var createEnrichClient = (apiKey, apiUrl) => {
|
|
298
439
|
const baseUrl = apiUrl || DEFAULT_API6;
|
|
299
|
-
const headers = () => ({
|
|
300
|
-
"Content-Type": "application/json",
|
|
301
|
-
Authorization: `Bearer ${apiKey}`
|
|
302
|
-
});
|
|
303
440
|
return {
|
|
304
441
|
/** Look up a person by email, LinkedIn, or name + company. Costs 1 credit. */
|
|
305
442
|
async person(params) {
|
|
306
|
-
const resp = await
|
|
443
|
+
const resp = await request(baseUrl, "/api/v1/enrichment/lookup/person", apiKey, {
|
|
307
444
|
method: "POST",
|
|
308
|
-
|
|
309
|
-
body: JSON.stringify(params)
|
|
445
|
+
body: params
|
|
310
446
|
});
|
|
311
|
-
|
|
312
|
-
return data.data || data;
|
|
447
|
+
return resp.data ?? resp;
|
|
313
448
|
},
|
|
314
449
|
/** Look up a company by domain or name. Costs 1 credit. */
|
|
315
450
|
async company(params) {
|
|
316
|
-
const resp = await
|
|
451
|
+
const resp = await request(baseUrl, "/api/v1/enrichment/lookup/company", apiKey, {
|
|
317
452
|
method: "POST",
|
|
318
|
-
|
|
319
|
-
body: JSON.stringify(params)
|
|
453
|
+
body: params
|
|
320
454
|
});
|
|
321
|
-
|
|
322
|
-
return data.data || data;
|
|
455
|
+
return resp.data ?? resp;
|
|
323
456
|
},
|
|
324
457
|
/** Verify an email address. Costs 1 credit. */
|
|
325
458
|
async verifyEmail(email) {
|
|
326
|
-
const resp = await
|
|
459
|
+
const resp = await request(baseUrl, "/api/v1/enrichment/verify-email", apiKey, {
|
|
327
460
|
method: "POST",
|
|
328
|
-
|
|
329
|
-
body: JSON.stringify({ email })
|
|
461
|
+
body: { email }
|
|
330
462
|
});
|
|
331
|
-
|
|
332
|
-
return data.data || data;
|
|
463
|
+
return resp.data ?? resp;
|
|
333
464
|
},
|
|
334
465
|
/** Search 300M+ contacts with filters. Credits charged per result. */
|
|
335
466
|
async search(filters, page = 1, limit = 25) {
|
|
336
|
-
const resp = await
|
|
467
|
+
const resp = await request(baseUrl, "/api/v1/search/contacts", apiKey, {
|
|
337
468
|
method: "POST",
|
|
338
|
-
|
|
339
|
-
body: JSON.stringify({ filters, page, limit })
|
|
469
|
+
body: { filters, page, limit }
|
|
340
470
|
});
|
|
341
|
-
|
|
342
|
-
return data.data || data;
|
|
471
|
+
return resp.data ?? resp;
|
|
343
472
|
}
|
|
344
473
|
};
|
|
345
474
|
};
|
|
@@ -348,15 +477,6 @@ var createEnrichClient = (apiKey, apiUrl) => {
|
|
|
348
477
|
var DEFAULT_API7 = "https://be.graph8.com";
|
|
349
478
|
var createSequencesClient = (apiKey, apiUrl) => {
|
|
350
479
|
const baseUrl = apiUrl || DEFAULT_API7;
|
|
351
|
-
const headers = () => ({ "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` });
|
|
352
|
-
const toQuery = (params) => {
|
|
353
|
-
const qs = new URLSearchParams();
|
|
354
|
-
for (const [k, v] of Object.entries(params)) {
|
|
355
|
-
if (v != null) qs.set(k, String(v));
|
|
356
|
-
}
|
|
357
|
-
const s = qs.toString();
|
|
358
|
-
return s ? `?${s}` : "";
|
|
359
|
-
};
|
|
360
480
|
async function list(pageOrParams, limit) {
|
|
361
481
|
let params;
|
|
362
482
|
if (typeof pageOrParams === "number") {
|
|
@@ -364,118 +484,130 @@ var createSequencesClient = (apiKey, apiUrl) => {
|
|
|
364
484
|
} else {
|
|
365
485
|
params = pageOrParams ?? {};
|
|
366
486
|
}
|
|
367
|
-
const resp = await
|
|
368
|
-
|
|
369
|
-
|
|
487
|
+
const resp = await request(baseUrl, "/api/v1/sequences", apiKey, {
|
|
488
|
+
query: params
|
|
489
|
+
});
|
|
490
|
+
return resp.data ?? resp;
|
|
370
491
|
}
|
|
371
492
|
return {
|
|
372
493
|
/** List sequences with pagination + optional status filter. */
|
|
373
494
|
list,
|
|
374
495
|
/** Get full sequence details by ID. */
|
|
375
496
|
async get(sequenceId) {
|
|
376
|
-
const resp = await
|
|
377
|
-
|
|
378
|
-
return data.data || data;
|
|
497
|
+
const resp = await request(baseUrl, `/api/v1/sequences/${sequenceId}`, apiKey);
|
|
498
|
+
return resp.data ?? resp;
|
|
379
499
|
},
|
|
380
500
|
/** List contacts enrolled in a sequence. Filter by state (e.g. "active", "replied"). */
|
|
381
501
|
async contacts(sequenceId, params = {}) {
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
{ headers: headers() }
|
|
385
|
-
);
|
|
386
|
-
return resp.json();
|
|
387
|
-
},
|
|
388
|
-
/** Add contacts to a sequence (V2 queuing). Live or drafted sequences only. */
|
|
389
|
-
async add(config) {
|
|
390
|
-
const resp = await fetch(`${baseUrl}/api/v1/sequences/${config.sequenceId}/contacts`, {
|
|
391
|
-
method: "POST",
|
|
392
|
-
headers: headers(),
|
|
393
|
-
body: JSON.stringify({ contact_ids: config.contactIds, list_id: config.listId })
|
|
502
|
+
return request(baseUrl, `/api/v1/sequences/${sequenceId}/contacts`, apiKey, {
|
|
503
|
+
query: params
|
|
394
504
|
});
|
|
395
|
-
const data = await resp.json();
|
|
396
|
-
return data.data || data;
|
|
397
505
|
},
|
|
398
|
-
/**
|
|
399
|
-
|
|
400
|
-
|
|
506
|
+
/**
|
|
507
|
+
* Add contacts to a sequence (V2 queuing). Live or drafted sequences only.
|
|
508
|
+
* Pass `idempotencyKey` to make a retry safe — the same key returns the
|
|
509
|
+
* first result instead of re-enrolling on a 5xx-then-success (A6).
|
|
510
|
+
*/
|
|
511
|
+
async add(config, idempotencyKey) {
|
|
512
|
+
const resp = await request(
|
|
513
|
+
baseUrl,
|
|
514
|
+
`/api/v1/sequences/${config.sequenceId}/contacts`,
|
|
515
|
+
apiKey,
|
|
516
|
+
{ method: "POST", body: { contact_ids: config.contactIds, list_id: config.listId }, idempotencyKey }
|
|
517
|
+
);
|
|
518
|
+
return resp.data ?? resp;
|
|
519
|
+
},
|
|
520
|
+
/**
|
|
521
|
+
* Create a new sequence with optional steps + channels. Pass `idempotencyKey`
|
|
522
|
+
* to make a retry safe — the same key returns the first result instead of
|
|
523
|
+
* creating a duplicate sequence on a 5xx-then-success (A6).
|
|
524
|
+
*/
|
|
525
|
+
async create(payload, idempotencyKey) {
|
|
526
|
+
const resp = await request(baseUrl, "/api/v1/sequences", apiKey, {
|
|
401
527
|
method: "POST",
|
|
402
|
-
|
|
403
|
-
|
|
528
|
+
body: payload,
|
|
529
|
+
idempotencyKey
|
|
404
530
|
});
|
|
405
|
-
|
|
406
|
-
return data.data || data;
|
|
531
|
+
return resp.data ?? resp;
|
|
407
532
|
},
|
|
408
533
|
/** Update sequence metadata. Rejected (409) if sequence is in a transitional status. */
|
|
409
534
|
async update(sequenceId, fields) {
|
|
410
|
-
const resp = await
|
|
535
|
+
const resp = await request(baseUrl, `/api/v1/sequences/${sequenceId}`, apiKey, {
|
|
411
536
|
method: "PATCH",
|
|
412
|
-
|
|
413
|
-
body: JSON.stringify(fields)
|
|
537
|
+
body: fields
|
|
414
538
|
});
|
|
415
|
-
|
|
416
|
-
return data.data || data;
|
|
539
|
+
return resp.data ?? resp;
|
|
417
540
|
},
|
|
418
541
|
/** Update a single step within a sequence. */
|
|
419
542
|
async updateStep(sequenceId, stepId, fields) {
|
|
420
|
-
const resp = await
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
return
|
|
543
|
+
const resp = await request(
|
|
544
|
+
baseUrl,
|
|
545
|
+
`/api/v1/sequences/${sequenceId}/steps/${stepId}`,
|
|
546
|
+
apiKey,
|
|
547
|
+
{ method: "PATCH", body: fields }
|
|
548
|
+
);
|
|
549
|
+
return resp.data ?? resp;
|
|
427
550
|
},
|
|
428
551
|
/** Soft-delete (archive) a sequence. */
|
|
429
552
|
async delete(sequenceId) {
|
|
430
|
-
const resp = await
|
|
431
|
-
method: "DELETE"
|
|
432
|
-
headers: headers()
|
|
553
|
+
const resp = await request(baseUrl, `/api/v1/sequences/${sequenceId}`, apiKey, {
|
|
554
|
+
method: "DELETE"
|
|
433
555
|
});
|
|
434
|
-
|
|
435
|
-
return data.data || data;
|
|
556
|
+
return resp.data ?? resp;
|
|
436
557
|
},
|
|
437
|
-
/**
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
const
|
|
444
|
-
|
|
558
|
+
/**
|
|
559
|
+
* Run/start a DRAFTED sequence (V2 orchestration). Pass `idempotencyKey` to
|
|
560
|
+
* make a retry safe — the same key won't re-trigger the run on a
|
|
561
|
+
* 5xx-then-success (A6).
|
|
562
|
+
*/
|
|
563
|
+
async run(sequenceId, idempotencyKey) {
|
|
564
|
+
const resp = await request(
|
|
565
|
+
baseUrl,
|
|
566
|
+
`/api/v1/sequences/${sequenceId}/run`,
|
|
567
|
+
apiKey,
|
|
568
|
+
{ method: "POST", idempotencyKey }
|
|
569
|
+
);
|
|
570
|
+
return resp.data ?? resp;
|
|
445
571
|
},
|
|
446
|
-
/**
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
572
|
+
/**
|
|
573
|
+
* Pause a live sequence. Pass `idempotencyKey` to make a retry safe — the
|
|
574
|
+
* same key won't double-apply on a 5xx-then-success (A6).
|
|
575
|
+
*/
|
|
576
|
+
async pause(sequenceId, idempotencyKey) {
|
|
577
|
+
const resp = await request(
|
|
578
|
+
baseUrl,
|
|
579
|
+
`/api/v1/sequences/${sequenceId}/pause`,
|
|
580
|
+
apiKey,
|
|
581
|
+
{ method: "POST", idempotencyKey }
|
|
582
|
+
);
|
|
583
|
+
return resp.data ?? resp;
|
|
454
584
|
},
|
|
455
|
-
/**
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
585
|
+
/**
|
|
586
|
+
* Resume a paused sequence. Pass `idempotencyKey` to make a retry safe — the
|
|
587
|
+
* same key won't double-apply on a 5xx-then-success (A6).
|
|
588
|
+
*/
|
|
589
|
+
async resume(sequenceId, idempotencyKey) {
|
|
590
|
+
const resp = await request(
|
|
591
|
+
baseUrl,
|
|
592
|
+
`/api/v1/sequences/${sequenceId}/resume`,
|
|
593
|
+
apiKey,
|
|
594
|
+
{ method: "POST", idempotencyKey }
|
|
595
|
+
);
|
|
596
|
+
return resp.data ?? resp;
|
|
463
597
|
},
|
|
464
598
|
/** Read-only sequence preview with all steps + channels (no enrollment). */
|
|
465
599
|
async preview(sequenceId) {
|
|
466
|
-
const resp = await
|
|
467
|
-
|
|
468
|
-
});
|
|
469
|
-
const data = await resp.json();
|
|
470
|
-
return data.data || data;
|
|
600
|
+
const resp = await request(baseUrl, `/api/v1/sequences/${sequenceId}/preview`, apiKey);
|
|
601
|
+
return resp.data ?? resp;
|
|
471
602
|
},
|
|
472
603
|
/** Comprehensive analytics for a sequence. */
|
|
473
604
|
async analytics(sequenceId) {
|
|
474
|
-
const resp = await
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
605
|
+
const resp = await request(
|
|
606
|
+
baseUrl,
|
|
607
|
+
`/api/v1/sequences/${sequenceId}/analytics`,
|
|
608
|
+
apiKey
|
|
609
|
+
);
|
|
610
|
+
return resp.data ?? resp;
|
|
479
611
|
}
|
|
480
612
|
};
|
|
481
613
|
};
|
|
@@ -484,37 +616,30 @@ var createSequencesClient = (apiKey, apiUrl) => {
|
|
|
484
616
|
var DEFAULT_API8 = "https://be.graph8.com";
|
|
485
617
|
var createCampaignsClient = (apiKey, apiUrl) => {
|
|
486
618
|
const baseUrl = apiUrl || DEFAULT_API8;
|
|
487
|
-
const headers = () => ({ "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` });
|
|
488
619
|
return {
|
|
489
620
|
async list(page = 1, limit = 50) {
|
|
490
|
-
const resp = await
|
|
491
|
-
|
|
492
|
-
|
|
621
|
+
const resp = await request(baseUrl, "/api/v1/campaigns", apiKey, {
|
|
622
|
+
query: { page, limit }
|
|
623
|
+
});
|
|
624
|
+
return resp.data ?? resp;
|
|
493
625
|
},
|
|
494
626
|
async get(campaignId) {
|
|
495
|
-
const resp = await
|
|
496
|
-
|
|
497
|
-
return data.data || data;
|
|
627
|
+
const resp = await request(baseUrl, `/api/v1/campaigns/${campaignId}`, apiKey);
|
|
628
|
+
return resp.data ?? resp;
|
|
498
629
|
},
|
|
499
630
|
async create(config) {
|
|
500
|
-
const resp = await
|
|
631
|
+
const resp = await request(baseUrl, "/api/v1/campaigns", apiKey, {
|
|
501
632
|
method: "POST",
|
|
502
|
-
|
|
503
|
-
body: JSON.stringify(config)
|
|
633
|
+
body: config
|
|
504
634
|
});
|
|
505
|
-
|
|
506
|
-
return data.data || data;
|
|
635
|
+
return resp.data ?? resp;
|
|
507
636
|
},
|
|
508
637
|
async launch(campaignId) {
|
|
509
|
-
await
|
|
510
|
-
method: "POST",
|
|
511
|
-
headers: headers()
|
|
512
|
-
});
|
|
638
|
+
await request(baseUrl, `/api/v1/campaigns/${campaignId}/launch`, apiKey, { method: "POST" });
|
|
513
639
|
},
|
|
514
640
|
async stats(campaignId) {
|
|
515
|
-
const resp = await
|
|
516
|
-
|
|
517
|
-
return data.data || data;
|
|
641
|
+
const resp = await request(baseUrl, `/api/v1/campaigns/${campaignId}/stats`, apiKey);
|
|
642
|
+
return resp.data ?? resp;
|
|
518
643
|
}
|
|
519
644
|
};
|
|
520
645
|
};
|
|
@@ -523,25 +648,21 @@ var createCampaignsClient = (apiKey, apiUrl) => {
|
|
|
523
648
|
var DEFAULT_API9 = "https://be.graph8.com";
|
|
524
649
|
var createIntegrationsClient = (apiKey, apiUrl) => {
|
|
525
650
|
const baseUrl = apiUrl || DEFAULT_API9;
|
|
526
|
-
const headers = () => ({ "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` });
|
|
527
651
|
return {
|
|
528
652
|
async list() {
|
|
529
|
-
const resp = await
|
|
530
|
-
|
|
531
|
-
return data.data || data;
|
|
653
|
+
const resp = await request(baseUrl, "/api/v1/integrations", apiKey);
|
|
654
|
+
return resp.data ?? resp;
|
|
532
655
|
},
|
|
533
656
|
async connect(provider, config) {
|
|
534
|
-
await
|
|
657
|
+
await request(baseUrl, "/api/v1/integrations/connect", apiKey, {
|
|
535
658
|
method: "POST",
|
|
536
|
-
|
|
537
|
-
body: JSON.stringify({ provider, ...config })
|
|
659
|
+
body: { provider, ...config }
|
|
538
660
|
});
|
|
539
661
|
},
|
|
540
662
|
async sync(provider, config) {
|
|
541
|
-
await
|
|
663
|
+
await request(baseUrl, "/api/v1/integrations/sync", apiKey, {
|
|
542
664
|
method: "POST",
|
|
543
|
-
|
|
544
|
-
body: JSON.stringify({ provider, ...config })
|
|
665
|
+
body: { provider, ...config }
|
|
545
666
|
});
|
|
546
667
|
}
|
|
547
668
|
};
|
|
@@ -581,15 +702,12 @@ var createSignalsClient = (key, isApiKey, apiUrl) => {
|
|
|
581
702
|
var DEFAULT_API11 = "https://be.graph8.com";
|
|
582
703
|
var createAnalyticsClient = (apiKey, apiUrl) => {
|
|
583
704
|
const baseUrl = apiUrl || DEFAULT_API11;
|
|
584
|
-
const headers = () => ({ "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` });
|
|
585
705
|
return {
|
|
586
706
|
async overview(config) {
|
|
587
|
-
const
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
const data = await resp.json();
|
|
592
|
-
return data.data || data;
|
|
707
|
+
const resp = await request(baseUrl, "/api/v1/analytics/overview", apiKey, {
|
|
708
|
+
query: { period: config?.period }
|
|
709
|
+
});
|
|
710
|
+
return resp.data ?? resp;
|
|
593
711
|
}
|
|
594
712
|
};
|
|
595
713
|
};
|
|
@@ -598,48 +716,37 @@ var createAnalyticsClient = (apiKey, apiUrl) => {
|
|
|
598
716
|
var DEFAULT_API12 = "https://be.graph8.com";
|
|
599
717
|
var createVoiceClient = (apiKey, apiUrl) => {
|
|
600
718
|
const baseUrl = apiUrl || DEFAULT_API12;
|
|
601
|
-
const headers = () => ({ "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` });
|
|
602
719
|
const listeners = /* @__PURE__ */ new Map();
|
|
603
|
-
const toQuery = (params) => {
|
|
604
|
-
const qs = new URLSearchParams();
|
|
605
|
-
for (const [k, v] of Object.entries(params)) {
|
|
606
|
-
if (v != null) qs.set(k, String(v));
|
|
607
|
-
}
|
|
608
|
-
const s = qs.toString();
|
|
609
|
-
return s ? `?${s}` : "";
|
|
610
|
-
};
|
|
611
720
|
const dialer = {
|
|
612
721
|
/** List parallel-dialer sessions with filters + pagination. */
|
|
613
722
|
async listSessions(params = {}) {
|
|
614
|
-
const resp = await
|
|
615
|
-
|
|
616
|
-
|
|
723
|
+
const resp = await request(
|
|
724
|
+
baseUrl,
|
|
725
|
+
"/api/v1/voice/dialer/sessions",
|
|
726
|
+
apiKey,
|
|
727
|
+
{ query: params }
|
|
617
728
|
);
|
|
618
|
-
|
|
619
|
-
return data.data || data;
|
|
729
|
+
return resp.data ?? resp;
|
|
620
730
|
},
|
|
621
731
|
/** Create a parallel-dialer session in PAUSED state. SDR opens UI to start dialing. */
|
|
622
732
|
async createSession(payload) {
|
|
623
|
-
const resp = await
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
return
|
|
733
|
+
const resp = await request(
|
|
734
|
+
baseUrl,
|
|
735
|
+
"/api/v1/voice/dialer/sessions",
|
|
736
|
+
apiKey,
|
|
737
|
+
{ method: "POST", body: payload }
|
|
738
|
+
);
|
|
739
|
+
return resp.data ?? resp;
|
|
630
740
|
},
|
|
631
741
|
/** Pause / resume / stop a dialer session via status flip. */
|
|
632
742
|
async updateSessionStatus(sessionId, status) {
|
|
633
|
-
const resp = await
|
|
634
|
-
|
|
635
|
-
{
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
body: JSON.stringify({ status })
|
|
639
|
-
}
|
|
743
|
+
const resp = await request(
|
|
744
|
+
baseUrl,
|
|
745
|
+
`/api/v1/voice/dialer/sessions/${sessionId}/status`,
|
|
746
|
+
apiKey,
|
|
747
|
+
{ method: "PATCH", body: { status } }
|
|
640
748
|
);
|
|
641
|
-
|
|
642
|
-
return data.data || data;
|
|
749
|
+
return resp.data ?? resp;
|
|
643
750
|
},
|
|
644
751
|
/**
|
|
645
752
|
* Resume a PAUSED dialer session. Auto-fetches the next batch from the source list,
|
|
@@ -647,94 +754,97 @@ var createVoiceClient = (apiKey, apiUrl) => {
|
|
|
647
754
|
* @param maxContacts 1-4 (voice caps parallel dialing at 4). Default 4.
|
|
648
755
|
*/
|
|
649
756
|
async resumeSession(sessionId, maxContacts = 4) {
|
|
650
|
-
const resp = await
|
|
651
|
-
|
|
652
|
-
{
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
body: JSON.stringify({ max_contacts: maxContacts })
|
|
656
|
-
}
|
|
757
|
+
const resp = await request(
|
|
758
|
+
baseUrl,
|
|
759
|
+
`/api/v1/voice/dialer/sessions/${sessionId}/resume`,
|
|
760
|
+
apiKey,
|
|
761
|
+
{ method: "POST", body: { max_contacts: maxContacts } }
|
|
657
762
|
);
|
|
658
|
-
|
|
659
|
-
return data.data || data;
|
|
763
|
+
return resp.data ?? resp;
|
|
660
764
|
},
|
|
661
765
|
/** Aggregated dialer analytics (daily breakdown or total). */
|
|
662
766
|
async stats(params = {}) {
|
|
663
|
-
const resp = await
|
|
664
|
-
|
|
665
|
-
|
|
767
|
+
const resp = await request(
|
|
768
|
+
baseUrl,
|
|
769
|
+
"/api/v1/voice/dialer/stats",
|
|
770
|
+
apiKey,
|
|
771
|
+
{ query: params }
|
|
666
772
|
);
|
|
667
|
-
|
|
668
|
-
return data.data || data;
|
|
773
|
+
return resp.data ?? resp;
|
|
669
774
|
},
|
|
670
775
|
/** List dialer-eligible phone numbers with 7-day stats + daily limits. */
|
|
671
776
|
async numbers(userEmail) {
|
|
672
|
-
const
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
777
|
+
const resp = await request(
|
|
778
|
+
baseUrl,
|
|
779
|
+
"/api/v1/voice/dialer/numbers",
|
|
780
|
+
apiKey,
|
|
781
|
+
{ query: userEmail ? { user_email: userEmail } : {} }
|
|
676
782
|
);
|
|
677
|
-
|
|
678
|
-
return data.data || data;
|
|
783
|
+
return resp.data ?? resp;
|
|
679
784
|
},
|
|
680
785
|
/** List missed inbound callbacks with caller / contact info. */
|
|
681
786
|
async missedCallbacks(limit = 50) {
|
|
682
|
-
const resp = await
|
|
683
|
-
|
|
684
|
-
|
|
787
|
+
const resp = await request(
|
|
788
|
+
baseUrl,
|
|
789
|
+
"/api/v1/voice/dialer/missed-callbacks",
|
|
790
|
+
apiKey,
|
|
791
|
+
{ query: { limit } }
|
|
685
792
|
);
|
|
686
|
-
|
|
687
|
-
return data.data || data;
|
|
793
|
+
return resp.data ?? resp;
|
|
688
794
|
},
|
|
689
795
|
/** AI grading for a single dialer call (returns "pending" while in progress). */
|
|
690
796
|
async callGrading(roomName) {
|
|
691
|
-
const resp = await
|
|
692
|
-
|
|
693
|
-
{
|
|
797
|
+
const resp = await request(
|
|
798
|
+
baseUrl,
|
|
799
|
+
`/api/v1/voice/dialer/calls/${encodeURIComponent(roomName)}/grading`,
|
|
800
|
+
apiKey
|
|
694
801
|
);
|
|
695
|
-
|
|
696
|
-
return data.data || data;
|
|
802
|
+
return resp.data ?? resp;
|
|
697
803
|
},
|
|
698
804
|
/** List voice agents available for dialer sessions (capped at 100; no pagination). */
|
|
699
805
|
async agents(params = {}) {
|
|
700
|
-
const resp = await
|
|
701
|
-
|
|
702
|
-
|
|
806
|
+
const resp = await request(
|
|
807
|
+
baseUrl,
|
|
808
|
+
"/api/v1/voice/dialer/agents",
|
|
809
|
+
apiKey,
|
|
810
|
+
{ query: params }
|
|
703
811
|
);
|
|
704
|
-
|
|
705
|
-
return data.data || data;
|
|
812
|
+
return resp.data ?? resp;
|
|
706
813
|
},
|
|
707
814
|
/** Fetch the full transcript for a single dialer call. */
|
|
708
815
|
async callTranscript(roomName) {
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
{
|
|
816
|
+
return request(
|
|
817
|
+
baseUrl,
|
|
818
|
+
`/api/v1/voice/dialer/calls/${encodeURIComponent(roomName)}/transcript`,
|
|
819
|
+
apiKey
|
|
712
820
|
);
|
|
713
|
-
return resp.json();
|
|
714
821
|
},
|
|
715
822
|
/** List dialer calls — pass `contact_id` or `user_email` to scope. */
|
|
716
823
|
async listCalls(params = {}) {
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
824
|
+
return request(
|
|
825
|
+
baseUrl,
|
|
826
|
+
"/api/v1/voice/dialer/calls",
|
|
827
|
+
apiKey,
|
|
828
|
+
{ query: params }
|
|
720
829
|
);
|
|
721
|
-
return resp.json();
|
|
722
830
|
},
|
|
723
831
|
/** Convenience: list calls for a single contact. */
|
|
724
832
|
async listCallsForContact(contactId, extra = {}) {
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
833
|
+
return request(
|
|
834
|
+
baseUrl,
|
|
835
|
+
"/api/v1/voice/dialer/calls",
|
|
836
|
+
apiKey,
|
|
837
|
+
{ query: { contact_id: contactId, ...extra } }
|
|
728
838
|
);
|
|
729
|
-
return resp.json();
|
|
730
839
|
},
|
|
731
840
|
/** Convenience: list calls placed by a specific SDR. */
|
|
732
841
|
async listCallsForSdr(userEmail, extra = {}) {
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
842
|
+
return request(
|
|
843
|
+
baseUrl,
|
|
844
|
+
"/api/v1/voice/dialer/calls",
|
|
845
|
+
apiKey,
|
|
846
|
+
{ query: { user_email: userEmail, ...extra } }
|
|
736
847
|
);
|
|
737
|
-
return resp.json();
|
|
738
848
|
}
|
|
739
849
|
};
|
|
740
850
|
return {
|
|
@@ -743,22 +853,25 @@ var createVoiceClient = (apiKey, apiUrl) => {
|
|
|
743
853
|
* @deprecated Preview surface — for parallel-dialer flows use `voice.dialer.createSession()`.
|
|
744
854
|
*/
|
|
745
855
|
async start(config) {
|
|
746
|
-
const resp = await
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
return
|
|
856
|
+
const resp = await request(
|
|
857
|
+
baseUrl,
|
|
858
|
+
"/api/v1/voice/sessions",
|
|
859
|
+
apiKey,
|
|
860
|
+
{ method: "POST", body: config }
|
|
861
|
+
);
|
|
862
|
+
return resp.data ?? resp;
|
|
753
863
|
},
|
|
754
864
|
/**
|
|
755
865
|
* Get call analysis for a completed session.
|
|
756
866
|
* @deprecated Preview surface — for dialer-call grading use `voice.dialer.callGrading(roomName)`.
|
|
757
867
|
*/
|
|
758
868
|
async analysis(sessionId) {
|
|
759
|
-
const resp = await
|
|
760
|
-
|
|
761
|
-
|
|
869
|
+
const resp = await request(
|
|
870
|
+
baseUrl,
|
|
871
|
+
`/api/v1/voice/sessions/${sessionId}/analysis`,
|
|
872
|
+
apiKey
|
|
873
|
+
);
|
|
874
|
+
return resp.data ?? resp;
|
|
762
875
|
},
|
|
763
876
|
/** Listen for voice events. */
|
|
764
877
|
on(event, callback) {
|
|
@@ -774,75 +887,128 @@ var createVoiceClient = (apiKey, apiUrl) => {
|
|
|
774
887
|
var DEFAULT_API13 = "https://be.graph8.com";
|
|
775
888
|
var createPagesClient = (apiKey, apiUrl) => {
|
|
776
889
|
const baseUrl = apiUrl || DEFAULT_API13;
|
|
777
|
-
const headers = () => ({ "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` });
|
|
778
890
|
return {
|
|
779
891
|
/** Clone a landing page from any URL. */
|
|
780
892
|
async clone(url) {
|
|
781
|
-
const resp = await
|
|
893
|
+
const resp = await request(baseUrl, "/api/v1/landing-pages/clone-url", apiKey, {
|
|
782
894
|
method: "POST",
|
|
783
|
-
|
|
784
|
-
body: JSON.stringify({ url })
|
|
895
|
+
body: { url }
|
|
785
896
|
});
|
|
786
|
-
|
|
787
|
-
return data.data || data;
|
|
897
|
+
return resp.data ?? resp;
|
|
788
898
|
},
|
|
789
899
|
/** Create a landing page from a template. */
|
|
790
900
|
async create(config) {
|
|
791
|
-
const resp = await
|
|
901
|
+
const resp = await request(baseUrl, "/api/v1/landing-pages", apiKey, {
|
|
792
902
|
method: "POST",
|
|
793
|
-
|
|
794
|
-
body: JSON.stringify(config)
|
|
903
|
+
body: config
|
|
795
904
|
});
|
|
796
|
-
|
|
797
|
-
return data.data || data;
|
|
905
|
+
return resp.data ?? resp;
|
|
798
906
|
},
|
|
799
907
|
/** Publish a landing page to CDN. */
|
|
800
908
|
async publish(pageId) {
|
|
801
|
-
const
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
909
|
+
const data = await request(
|
|
910
|
+
baseUrl,
|
|
911
|
+
`/api/v1/landing-pages/${pageId}/publish`,
|
|
912
|
+
apiKey,
|
|
913
|
+
{ method: "POST" }
|
|
914
|
+
);
|
|
806
915
|
return { url: data.published_url || data.data?.published_url || "" };
|
|
807
916
|
}
|
|
808
917
|
};
|
|
809
918
|
};
|
|
810
919
|
|
|
811
920
|
// src/webhooks.ts
|
|
921
|
+
var import_node_crypto = require("crypto");
|
|
812
922
|
var DEFAULT_API14 = "https://be.graph8.com";
|
|
813
|
-
var
|
|
923
|
+
var KNOWN_WEBHOOK_EVENTS = [
|
|
924
|
+
"campaign.created",
|
|
925
|
+
"campaign.updated",
|
|
926
|
+
"campaign.deleted",
|
|
927
|
+
"campaign.launched",
|
|
928
|
+
"campaign.paused",
|
|
929
|
+
"campaign.completed",
|
|
930
|
+
"campaign.status_changed",
|
|
931
|
+
"campaign.content_ready",
|
|
932
|
+
"document.generated",
|
|
933
|
+
"document.failed",
|
|
934
|
+
"intelligence.completed",
|
|
935
|
+
"intelligence.failed",
|
|
936
|
+
"company.enriched",
|
|
937
|
+
"company_intelligence.completed",
|
|
938
|
+
"audience.ready",
|
|
939
|
+
"audience.failed",
|
|
940
|
+
"sequence.deployed",
|
|
941
|
+
"sequence.started",
|
|
942
|
+
"sequence.paused",
|
|
943
|
+
"sequence.completed",
|
|
944
|
+
"engagement.email_sent",
|
|
945
|
+
"engagement.email_replied",
|
|
946
|
+
"engagement.email_bounced",
|
|
947
|
+
"engagement.email_skipped",
|
|
948
|
+
"engagement.call_dispatched",
|
|
949
|
+
"engagement.sms_sent",
|
|
950
|
+
"engagement.sms_replied",
|
|
951
|
+
"engagement.whatsapp_sent",
|
|
952
|
+
"engagement.linkedin_connection_sent",
|
|
953
|
+
"engagement.linkedin_message_sent",
|
|
954
|
+
"engagement.linkedin_inmail_sent",
|
|
955
|
+
"engagement.linkedin_reply_received",
|
|
956
|
+
"engagement.linkedin_connection_accepted",
|
|
957
|
+
"meeting.booked",
|
|
958
|
+
"meeting.cancelled",
|
|
959
|
+
"meeting.rescheduled"
|
|
960
|
+
];
|
|
961
|
+
var WebhookSignatureError = class extends Error {
|
|
962
|
+
constructor(message) {
|
|
963
|
+
super(message);
|
|
964
|
+
this.name = "WebhookSignatureError";
|
|
965
|
+
}
|
|
966
|
+
};
|
|
967
|
+
function timingSafeEqualHex(a, b) {
|
|
968
|
+
if (a.length !== b.length) return false;
|
|
969
|
+
try {
|
|
970
|
+
const enc = new TextEncoder();
|
|
971
|
+
return (0, import_node_crypto.timingSafeEqual)(enc.encode(a), enc.encode(b));
|
|
972
|
+
} catch {
|
|
973
|
+
return false;
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
function constructEvent(payload, signature, timestamp, secret, opts = {}) {
|
|
977
|
+
if (!signature) throw new WebhookSignatureError("Missing X-Studio-Signature header");
|
|
978
|
+
if (timestamp === void 0 || timestamp === null || timestamp === "") {
|
|
979
|
+
throw new WebhookSignatureError("Missing X-Studio-Timestamp header");
|
|
980
|
+
}
|
|
981
|
+
if (!secret) throw new WebhookSignatureError("Missing signing secret");
|
|
982
|
+
const ts = typeof timestamp === "number" ? timestamp : parseInt(timestamp, 10);
|
|
983
|
+
if (!Number.isFinite(ts)) throw new WebhookSignatureError("Invalid X-Studio-Timestamp header");
|
|
984
|
+
const tolerance = opts.toleranceSeconds ?? 0;
|
|
985
|
+
if (tolerance > 0) {
|
|
986
|
+
const ageSeconds = Math.floor(Date.now() / 1e3) - ts;
|
|
987
|
+
if (Math.abs(ageSeconds) > tolerance) {
|
|
988
|
+
throw new WebhookSignatureError(`Timestamp outside tolerance (${ageSeconds}s > ${tolerance}s)`);
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
const expected = (0, import_node_crypto.createHmac)("sha256", secret).update(`${ts}.${payload}`).digest("hex");
|
|
992
|
+
const provided = signature.startsWith("sha256=") ? signature.slice(7) : signature;
|
|
993
|
+
if (!timingSafeEqualHex(expected, provided)) {
|
|
994
|
+
throw new WebhookSignatureError("Signature verification failed");
|
|
995
|
+
}
|
|
996
|
+
try {
|
|
997
|
+
return JSON.parse(payload);
|
|
998
|
+
} catch {
|
|
999
|
+
throw new WebhookSignatureError("Invalid JSON payload");
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
var createWebhooksClient = (_apiKey, apiUrl) => {
|
|
814
1003
|
const baseUrl = apiUrl || DEFAULT_API14;
|
|
815
|
-
const headers = () => ({ "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` });
|
|
816
|
-
const listeners = /* @__PURE__ */ new Map();
|
|
817
|
-
let polling = false;
|
|
818
|
-
let pollInterval = null;
|
|
819
1004
|
return {
|
|
820
|
-
/**
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
try {
|
|
828
|
-
const resp = await fetch(`${baseUrl}/api/v1/webhooks/events?since=30s`, { headers: headers() });
|
|
829
|
-
if (!resp.ok) return;
|
|
830
|
-
const data = await resp.json();
|
|
831
|
-
const events = data.data || data || [];
|
|
832
|
-
for (const evt of events) {
|
|
833
|
-
const cbs = listeners.get(evt.type);
|
|
834
|
-
if (cbs) cbs.forEach((cb) => cb(evt));
|
|
835
|
-
}
|
|
836
|
-
} catch {
|
|
837
|
-
}
|
|
838
|
-
}, 3e4);
|
|
839
|
-
}
|
|
840
|
-
},
|
|
841
|
-
/** Stop all webhook polling. */
|
|
842
|
-
stop() {
|
|
843
|
-
if (pollInterval) clearInterval(pollInterval);
|
|
844
|
-
polling = false;
|
|
845
|
-
listeners.clear();
|
|
1005
|
+
/** Base URL the webhook subscription API lives under. */
|
|
1006
|
+
baseUrl,
|
|
1007
|
+
/** Known event types (for autocomplete / validation). */
|
|
1008
|
+
knownEvents: KNOWN_WEBHOOK_EVENTS,
|
|
1009
|
+
/** Verify an incoming webhook's HMAC signature and return the parsed event. */
|
|
1010
|
+
constructEvent(payload, signature, timestamp, secret, opts) {
|
|
1011
|
+
return constructEvent(payload, signature, timestamp, secret, opts);
|
|
846
1012
|
}
|
|
847
1013
|
};
|
|
848
1014
|
};
|
|
@@ -851,75 +1017,59 @@ var createWebhooksClient = (apiKey, apiUrl) => {
|
|
|
851
1017
|
var DEFAULT_API15 = "https://be.graph8.com";
|
|
852
1018
|
var createContactsClient = (apiKey, apiUrl) => {
|
|
853
1019
|
const baseUrl = apiUrl || DEFAULT_API15;
|
|
854
|
-
const headers = () => ({ "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` });
|
|
855
|
-
const toQuery = (params) => {
|
|
856
|
-
const qs = new URLSearchParams();
|
|
857
|
-
for (const [k, v] of Object.entries(params)) {
|
|
858
|
-
if (v != null) qs.set(k, String(v));
|
|
859
|
-
}
|
|
860
|
-
const s = qs.toString();
|
|
861
|
-
return s ? `?${s}` : "";
|
|
862
|
-
};
|
|
863
1020
|
return {
|
|
864
1021
|
/** List contacts with optional filters. */
|
|
865
1022
|
async list(params = {}) {
|
|
866
|
-
|
|
867
|
-
|
|
1023
|
+
return request(baseUrl, "/api/v1/contacts", apiKey, {
|
|
1024
|
+
query: params
|
|
1025
|
+
});
|
|
868
1026
|
},
|
|
869
1027
|
/** Get a single contact by ID. */
|
|
870
1028
|
async get(contactId) {
|
|
871
|
-
const resp = await
|
|
872
|
-
|
|
873
|
-
return data.data || data;
|
|
1029
|
+
const resp = await request(baseUrl, `/api/v1/contacts/${contactId}`, apiKey);
|
|
1030
|
+
return resp.data ?? resp;
|
|
874
1031
|
},
|
|
875
|
-
/**
|
|
876
|
-
|
|
877
|
-
|
|
1032
|
+
/**
|
|
1033
|
+
* Create a new contact. Pass `idempotencyKey` to make a retry safe — the
|
|
1034
|
+
* same key returns the first result instead of creating a duplicate (A6).
|
|
1035
|
+
*/
|
|
1036
|
+
async create(contact, idempotencyKey) {
|
|
1037
|
+
const resp = await request(baseUrl, "/api/v1/contacts", apiKey, {
|
|
878
1038
|
method: "POST",
|
|
879
|
-
|
|
880
|
-
|
|
1039
|
+
body: contact,
|
|
1040
|
+
idempotencyKey
|
|
881
1041
|
});
|
|
882
|
-
|
|
883
|
-
return data.data || data;
|
|
1042
|
+
return resp.data ?? resp;
|
|
884
1043
|
},
|
|
885
1044
|
/** Update a contact (partial). */
|
|
886
1045
|
async update(contactId, fields) {
|
|
887
|
-
|
|
1046
|
+
return request(baseUrl, `/api/v1/contacts/${contactId}`, apiKey, {
|
|
888
1047
|
method: "PATCH",
|
|
889
|
-
|
|
890
|
-
body: JSON.stringify(fields)
|
|
1048
|
+
body: fields
|
|
891
1049
|
});
|
|
892
|
-
return resp.json();
|
|
893
1050
|
},
|
|
894
1051
|
/** Delete a contact (soft-delete). */
|
|
895
1052
|
async delete(contactId) {
|
|
896
|
-
|
|
897
|
-
method: "DELETE",
|
|
898
|
-
headers: headers()
|
|
899
|
-
});
|
|
900
|
-
return resp.json();
|
|
1053
|
+
return request(baseUrl, `/api/v1/contacts/${contactId}`, apiKey, { method: "DELETE" });
|
|
901
1054
|
},
|
|
902
1055
|
/** List custom contact columns. Pass listId to include list-specific columns. */
|
|
903
1056
|
async listColumns(listId) {
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
1057
|
+
return request(baseUrl, "/api/v1/contacts/columns", apiKey, {
|
|
1058
|
+
query: listId != null ? { list_id: listId } : void 0
|
|
1059
|
+
});
|
|
907
1060
|
},
|
|
908
1061
|
/** Create a custom contact column. Global if list_id is omitted, list-scoped otherwise. */
|
|
909
1062
|
async createColumn(params) {
|
|
910
|
-
const
|
|
911
|
-
title: params.title,
|
|
912
|
-
data_type: params.data_type || "text",
|
|
913
|
-
list_id: params.list_id ?? null,
|
|
914
|
-
created_by: params.created_by
|
|
915
|
-
};
|
|
916
|
-
const resp = await fetch(`${baseUrl}/api/v1/contacts/columns/create`, {
|
|
1063
|
+
const resp = await request(baseUrl, "/api/v1/contacts/columns/create", apiKey, {
|
|
917
1064
|
method: "POST",
|
|
918
|
-
|
|
919
|
-
|
|
1065
|
+
body: {
|
|
1066
|
+
title: params.title,
|
|
1067
|
+
data_type: params.data_type || "text",
|
|
1068
|
+
list_id: params.list_id ?? null,
|
|
1069
|
+
created_by: params.created_by
|
|
1070
|
+
}
|
|
920
1071
|
});
|
|
921
|
-
|
|
922
|
-
return data.data || data;
|
|
1072
|
+
return resp.data ?? resp;
|
|
923
1073
|
}
|
|
924
1074
|
};
|
|
925
1075
|
};
|
|
@@ -928,73 +1078,46 @@ var createContactsClient = (apiKey, apiUrl) => {
|
|
|
928
1078
|
var DEFAULT_API16 = "https://be.graph8.com";
|
|
929
1079
|
var createCompaniesClient = (apiKey, apiUrl) => {
|
|
930
1080
|
const baseUrl = apiUrl || DEFAULT_API16;
|
|
931
|
-
const headers = () => ({ "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` });
|
|
932
|
-
const toQuery = (params) => {
|
|
933
|
-
const qs = new URLSearchParams();
|
|
934
|
-
for (const [k, v] of Object.entries(params)) {
|
|
935
|
-
if (v != null) qs.set(k, String(v));
|
|
936
|
-
}
|
|
937
|
-
const s = qs.toString();
|
|
938
|
-
return s ? `?${s}` : "";
|
|
939
|
-
};
|
|
940
1081
|
return {
|
|
941
1082
|
/** List companies with optional filters. */
|
|
942
1083
|
async list(params = {}) {
|
|
943
|
-
|
|
944
|
-
return resp.json();
|
|
1084
|
+
return request(baseUrl, "/api/v1/companies", apiKey, { query: params });
|
|
945
1085
|
},
|
|
946
1086
|
/** Get a single company by ID. */
|
|
947
1087
|
async get(companyId) {
|
|
948
|
-
const resp = await
|
|
949
|
-
|
|
950
|
-
return data.data || data;
|
|
1088
|
+
const resp = await request(baseUrl, `/api/v1/companies/${companyId}`, apiKey);
|
|
1089
|
+
return resp.data ?? resp;
|
|
951
1090
|
},
|
|
952
1091
|
/** Get contacts belonging to a company. */
|
|
953
1092
|
async contacts(companyId, limit = 50, offset = 0) {
|
|
954
|
-
|
|
955
|
-
`${baseUrl}/api/v1/companies/${companyId}/contacts?limit=${limit}&offset=${offset}`,
|
|
956
|
-
{ headers: headers() }
|
|
957
|
-
);
|
|
958
|
-
return resp.json();
|
|
1093
|
+
return request(baseUrl, `/api/v1/companies/${companyId}/contacts`, apiKey, { query: { limit, offset } });
|
|
959
1094
|
},
|
|
960
1095
|
/** Update a company (partial). */
|
|
961
1096
|
async update(companyId, fields) {
|
|
962
|
-
|
|
963
|
-
method: "PATCH",
|
|
964
|
-
headers: headers(),
|
|
965
|
-
body: JSON.stringify(fields)
|
|
966
|
-
});
|
|
967
|
-
return resp.json();
|
|
1097
|
+
return request(baseUrl, `/api/v1/companies/${companyId}`, apiKey, { method: "PATCH", body: fields });
|
|
968
1098
|
},
|
|
969
1099
|
/** Delete a company (soft-delete). */
|
|
970
1100
|
async delete(companyId) {
|
|
971
|
-
|
|
972
|
-
method: "DELETE",
|
|
973
|
-
headers: headers()
|
|
974
|
-
});
|
|
975
|
-
return resp.json();
|
|
1101
|
+
return request(baseUrl, `/api/v1/companies/${companyId}`, apiKey, { method: "DELETE" });
|
|
976
1102
|
},
|
|
977
1103
|
/** List custom company columns. Pass listId to include list-specific columns. */
|
|
978
1104
|
async listColumns(listId) {
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
1105
|
+
return request(baseUrl, "/api/v1/companies/columns", apiKey, {
|
|
1106
|
+
query: listId != null ? { list_id: listId } : void 0
|
|
1107
|
+
});
|
|
982
1108
|
},
|
|
983
1109
|
/** Create a custom company column. Global if list_id is omitted, list-scoped otherwise. */
|
|
984
1110
|
async createColumn(params) {
|
|
985
|
-
const
|
|
986
|
-
title: params.title,
|
|
987
|
-
data_type: params.data_type || "text",
|
|
988
|
-
list_id: params.list_id ?? null,
|
|
989
|
-
created_by: params.created_by
|
|
990
|
-
};
|
|
991
|
-
const resp = await fetch(`${baseUrl}/api/v1/companies/columns/create`, {
|
|
1111
|
+
const resp = await request(baseUrl, "/api/v1/companies/columns/create", apiKey, {
|
|
992
1112
|
method: "POST",
|
|
993
|
-
|
|
994
|
-
|
|
1113
|
+
body: {
|
|
1114
|
+
title: params.title,
|
|
1115
|
+
data_type: params.data_type || "text",
|
|
1116
|
+
list_id: params.list_id ?? null,
|
|
1117
|
+
created_by: params.created_by
|
|
1118
|
+
}
|
|
995
1119
|
});
|
|
996
|
-
|
|
997
|
-
return data.data || data;
|
|
1120
|
+
return resp.data ?? resp;
|
|
998
1121
|
}
|
|
999
1122
|
};
|
|
1000
1123
|
};
|
|
@@ -1003,56 +1126,40 @@ var createCompaniesClient = (apiKey, apiUrl) => {
|
|
|
1003
1126
|
var DEFAULT_API17 = "https://be.graph8.com";
|
|
1004
1127
|
var createListsClient = (apiKey, apiUrl) => {
|
|
1005
1128
|
const baseUrl = apiUrl || DEFAULT_API17;
|
|
1006
|
-
const headers = () => ({ "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` });
|
|
1007
1129
|
return {
|
|
1008
1130
|
/** List all lists. */
|
|
1009
1131
|
async list(page = 1, limit = 50) {
|
|
1010
|
-
|
|
1011
|
-
return resp.json();
|
|
1132
|
+
return request(baseUrl, "/api/v1/lists", apiKey, { query: { page, limit } });
|
|
1012
1133
|
},
|
|
1013
1134
|
/** Create a new list. */
|
|
1014
1135
|
async create(title, type = "contacts") {
|
|
1015
|
-
const resp = await
|
|
1136
|
+
const resp = await request(baseUrl, "/api/v1/lists", apiKey, {
|
|
1016
1137
|
method: "POST",
|
|
1017
|
-
|
|
1018
|
-
body: JSON.stringify({ title, type })
|
|
1138
|
+
body: { title, type }
|
|
1019
1139
|
});
|
|
1020
|
-
|
|
1021
|
-
return data.data || data;
|
|
1140
|
+
return resp.data ?? resp;
|
|
1022
1141
|
},
|
|
1023
1142
|
/** Delete a list (soft-delete). */
|
|
1024
1143
|
async delete(listId) {
|
|
1025
|
-
|
|
1026
|
-
method: "DELETE",
|
|
1027
|
-
headers: headers()
|
|
1028
|
-
});
|
|
1029
|
-
return resp.json();
|
|
1144
|
+
return request(baseUrl, `/api/v1/lists/${listId}`, apiKey, { method: "DELETE" });
|
|
1030
1145
|
},
|
|
1031
1146
|
/** Get contacts in a list. */
|
|
1032
1147
|
async contacts(listId, page = 1, limit = 50) {
|
|
1033
|
-
|
|
1034
|
-
`${baseUrl}/api/v1/lists/${listId}/contacts?page=${page}&limit=${limit}`,
|
|
1035
|
-
{ headers: headers() }
|
|
1036
|
-
);
|
|
1037
|
-
return resp.json();
|
|
1148
|
+
return request(baseUrl, `/api/v1/lists/${listId}/contacts`, apiKey, { query: { page, limit } });
|
|
1038
1149
|
},
|
|
1039
1150
|
/** Add contacts to a list. */
|
|
1040
1151
|
async addContacts(listId, contactIds) {
|
|
1041
|
-
|
|
1152
|
+
return request(baseUrl, `/api/v1/lists/${listId}/contacts`, apiKey, {
|
|
1042
1153
|
method: "POST",
|
|
1043
|
-
|
|
1044
|
-
body: JSON.stringify({ contact_ids: contactIds })
|
|
1154
|
+
body: { contact_ids: contactIds }
|
|
1045
1155
|
});
|
|
1046
|
-
return resp.json();
|
|
1047
1156
|
},
|
|
1048
1157
|
/** Remove contacts from a list. */
|
|
1049
1158
|
async removeContacts(listId, contactIds) {
|
|
1050
|
-
|
|
1159
|
+
return request(baseUrl, `/api/v1/lists/${listId}/contacts`, apiKey, {
|
|
1051
1160
|
method: "DELETE",
|
|
1052
|
-
|
|
1053
|
-
body: JSON.stringify({ contact_ids: contactIds })
|
|
1161
|
+
body: { contact_ids: contactIds }
|
|
1054
1162
|
});
|
|
1055
|
-
return resp.json();
|
|
1056
1163
|
}
|
|
1057
1164
|
};
|
|
1058
1165
|
};
|
|
@@ -1061,40 +1168,30 @@ var createListsClient = (apiKey, apiUrl) => {
|
|
|
1061
1168
|
var DEFAULT_API18 = "https://be.graph8.com";
|
|
1062
1169
|
var createNotesClient = (apiKey, apiUrl) => {
|
|
1063
1170
|
const baseUrl = apiUrl || DEFAULT_API18;
|
|
1064
|
-
const headers = () => ({ "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` });
|
|
1065
1171
|
return {
|
|
1066
1172
|
/** List all notes on a contact. */
|
|
1067
1173
|
async list(contactId) {
|
|
1068
|
-
|
|
1069
|
-
return resp.json();
|
|
1174
|
+
return request(baseUrl, `/api/v1/contacts/${contactId}/notes`, apiKey);
|
|
1070
1175
|
},
|
|
1071
1176
|
/** Create a note on a contact. */
|
|
1072
1177
|
async create(contactId, content) {
|
|
1073
|
-
const resp = await
|
|
1178
|
+
const resp = await request(baseUrl, `/api/v1/contacts/${contactId}/notes`, apiKey, {
|
|
1074
1179
|
method: "POST",
|
|
1075
|
-
|
|
1076
|
-
body: JSON.stringify({ content })
|
|
1180
|
+
body: { content }
|
|
1077
1181
|
});
|
|
1078
|
-
|
|
1079
|
-
return data.data || data;
|
|
1182
|
+
return resp.data ?? resp;
|
|
1080
1183
|
},
|
|
1081
1184
|
/** Update a note's content. */
|
|
1082
1185
|
async update(noteId, content) {
|
|
1083
|
-
const resp = await
|
|
1186
|
+
const resp = await request(baseUrl, `/api/v1/notes/${noteId}`, apiKey, {
|
|
1084
1187
|
method: "PATCH",
|
|
1085
|
-
|
|
1086
|
-
body: JSON.stringify({ content })
|
|
1188
|
+
body: { content }
|
|
1087
1189
|
});
|
|
1088
|
-
|
|
1089
|
-
return data.data || data;
|
|
1190
|
+
return resp.data ?? resp;
|
|
1090
1191
|
},
|
|
1091
1192
|
/** Delete a note. */
|
|
1092
1193
|
async delete(noteId) {
|
|
1093
|
-
|
|
1094
|
-
method: "DELETE",
|
|
1095
|
-
headers: headers()
|
|
1096
|
-
});
|
|
1097
|
-
return resp.json();
|
|
1194
|
+
return request(baseUrl, `/api/v1/notes/${noteId}`, apiKey, { method: "DELETE" });
|
|
1098
1195
|
}
|
|
1099
1196
|
};
|
|
1100
1197
|
};
|
|
@@ -1103,54 +1200,36 @@ var createNotesClient = (apiKey, apiUrl) => {
|
|
|
1103
1200
|
var DEFAULT_API19 = "https://be.graph8.com";
|
|
1104
1201
|
var createTasksClient = (apiKey, apiUrl) => {
|
|
1105
1202
|
const baseUrl = apiUrl || DEFAULT_API19;
|
|
1106
|
-
const headers = () => ({ "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` });
|
|
1107
|
-
const toQuery = (params) => {
|
|
1108
|
-
const qs = new URLSearchParams();
|
|
1109
|
-
for (const [k, v] of Object.entries(params)) {
|
|
1110
|
-
if (v != null) qs.set(k, String(v));
|
|
1111
|
-
}
|
|
1112
|
-
const s = qs.toString();
|
|
1113
|
-
return s ? `?${s}` : "";
|
|
1114
|
-
};
|
|
1115
1203
|
return {
|
|
1116
1204
|
/** List tasks on a single contact. Optional status filter ("open" | "completed"). */
|
|
1117
1205
|
async listForContact(contactId, status) {
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1206
|
+
return request(baseUrl, `/api/v1/contacts/${contactId}/tasks`, apiKey, {
|
|
1207
|
+
query: status ? { status } : void 0
|
|
1208
|
+
});
|
|
1121
1209
|
},
|
|
1122
1210
|
/** List all tasks org-wide with optional filters. */
|
|
1123
1211
|
async list(params = {}) {
|
|
1124
|
-
|
|
1125
|
-
return resp.json();
|
|
1212
|
+
return request(baseUrl, "/api/v1/tasks", apiKey, { query: params });
|
|
1126
1213
|
},
|
|
1127
1214
|
/** Create a task on a contact. */
|
|
1128
1215
|
async create(contactId, task) {
|
|
1129
|
-
const resp = await
|
|
1216
|
+
const resp = await request(baseUrl, `/api/v1/contacts/${contactId}/tasks`, apiKey, {
|
|
1130
1217
|
method: "POST",
|
|
1131
|
-
|
|
1132
|
-
body: JSON.stringify(task)
|
|
1218
|
+
body: task
|
|
1133
1219
|
});
|
|
1134
|
-
|
|
1135
|
-
return data.data || data;
|
|
1220
|
+
return resp.data ?? resp;
|
|
1136
1221
|
},
|
|
1137
1222
|
/** Update a task (partial). */
|
|
1138
1223
|
async update(taskId, fields) {
|
|
1139
|
-
const resp = await
|
|
1224
|
+
const resp = await request(baseUrl, `/api/v1/tasks/${taskId}`, apiKey, {
|
|
1140
1225
|
method: "PATCH",
|
|
1141
|
-
|
|
1142
|
-
body: JSON.stringify(fields)
|
|
1226
|
+
body: fields
|
|
1143
1227
|
});
|
|
1144
|
-
|
|
1145
|
-
return data.data || data;
|
|
1228
|
+
return resp.data ?? resp;
|
|
1146
1229
|
},
|
|
1147
1230
|
/** Delete a task. */
|
|
1148
1231
|
async delete(taskId) {
|
|
1149
|
-
|
|
1150
|
-
method: "DELETE",
|
|
1151
|
-
headers: headers()
|
|
1152
|
-
});
|
|
1153
|
-
return resp.json();
|
|
1232
|
+
return request(baseUrl, `/api/v1/tasks/${taskId}`, apiKey, { method: "DELETE" });
|
|
1154
1233
|
}
|
|
1155
1234
|
};
|
|
1156
1235
|
};
|
|
@@ -1159,67 +1238,42 @@ var createTasksClient = (apiKey, apiUrl) => {
|
|
|
1159
1238
|
var DEFAULT_API20 = "https://be.graph8.com";
|
|
1160
1239
|
var createFieldsClient = (apiKey, apiUrl) => {
|
|
1161
1240
|
const baseUrl = apiUrl || DEFAULT_API20;
|
|
1162
|
-
const headers = () => ({ "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` });
|
|
1163
|
-
const toQuery = (params) => {
|
|
1164
|
-
const qs = new URLSearchParams();
|
|
1165
|
-
for (const [k, v] of Object.entries(params)) {
|
|
1166
|
-
if (v != null) qs.set(k, String(v));
|
|
1167
|
-
}
|
|
1168
|
-
const s = qs.toString();
|
|
1169
|
-
return s ? `?${s}` : "";
|
|
1170
|
-
};
|
|
1171
1241
|
return {
|
|
1172
1242
|
/** List contact fields (base + custom). Pass listId to include list-specific custom fields. */
|
|
1173
1243
|
async listContactFields(listId) {
|
|
1174
|
-
|
|
1175
|
-
const resp = await fetch(`${baseUrl}/api/v1/fields${qs}`, { headers: headers() });
|
|
1176
|
-
return resp.json();
|
|
1244
|
+
return request(baseUrl, "/api/v1/fields", apiKey, { query: listId != null ? { list_id: listId } : void 0 });
|
|
1177
1245
|
},
|
|
1178
1246
|
/** List company fields (base + custom). Pass listId to include list-specific custom fields. */
|
|
1179
1247
|
async listCompanyFields(listId) {
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1248
|
+
return request(baseUrl, "/api/v1/fields/companies", apiKey, {
|
|
1249
|
+
query: listId != null ? { list_id: listId } : void 0
|
|
1250
|
+
});
|
|
1183
1251
|
},
|
|
1184
1252
|
/** Create a custom field on contacts (default) or companies. */
|
|
1185
1253
|
async create(params) {
|
|
1186
|
-
const
|
|
1187
|
-
title: params.title,
|
|
1188
|
-
data_type: params.data_type || "text",
|
|
1189
|
-
list_id: params.list_id ?? null,
|
|
1190
|
-
entity: params.entity || "contacts"
|
|
1191
|
-
};
|
|
1192
|
-
const resp = await fetch(`${baseUrl}/api/v1/fields`, {
|
|
1254
|
+
const resp = await request(baseUrl, "/api/v1/fields", apiKey, {
|
|
1193
1255
|
method: "POST",
|
|
1194
|
-
|
|
1195
|
-
|
|
1256
|
+
body: {
|
|
1257
|
+
title: params.title,
|
|
1258
|
+
data_type: params.data_type || "text",
|
|
1259
|
+
list_id: params.list_id ?? null,
|
|
1260
|
+
entity: params.entity || "contacts"
|
|
1261
|
+
}
|
|
1196
1262
|
});
|
|
1197
|
-
|
|
1198
|
-
return data.data || data;
|
|
1263
|
+
return resp.data ?? resp;
|
|
1199
1264
|
},
|
|
1200
1265
|
/** Delete a custom field (soft-delete). Pass list_id to scope-guard against cross-list deletion. */
|
|
1201
1266
|
async delete(columnId, params = {}) {
|
|
1202
|
-
const
|
|
1203
|
-
if (params.list_id != null)
|
|
1204
|
-
|
|
1205
|
-
method: "DELETE",
|
|
1206
|
-
headers: headers()
|
|
1207
|
-
});
|
|
1208
|
-
return resp.json();
|
|
1267
|
+
const query = { entity: params.entity || "contacts" };
|
|
1268
|
+
if (params.list_id != null) query.list_id = params.list_id;
|
|
1269
|
+
return request(baseUrl, `/api/v1/fields/${columnId}`, apiKey, { method: "DELETE", query });
|
|
1209
1270
|
},
|
|
1210
1271
|
/** Set a custom field value on a single contact or company row. Pass value=null to clear. */
|
|
1211
1272
|
async setValue(columnId, params) {
|
|
1212
|
-
|
|
1213
|
-
record_id: params.record_id,
|
|
1214
|
-
value: params.value ?? null,
|
|
1215
|
-
entity: params.entity || "contacts"
|
|
1216
|
-
};
|
|
1217
|
-
const resp = await fetch(`${baseUrl}/api/v1/fields/${columnId}/values`, {
|
|
1273
|
+
return request(baseUrl, `/api/v1/fields/${columnId}/values`, apiKey, {
|
|
1218
1274
|
method: "PATCH",
|
|
1219
|
-
|
|
1220
|
-
body: JSON.stringify(body)
|
|
1275
|
+
body: { record_id: params.record_id, value: params.value ?? null, entity: params.entity || "contacts" }
|
|
1221
1276
|
});
|
|
1222
|
-
return resp.json();
|
|
1223
1277
|
}
|
|
1224
1278
|
};
|
|
1225
1279
|
};
|
|
@@ -1228,69 +1282,44 @@ var createFieldsClient = (apiKey, apiUrl) => {
|
|
|
1228
1282
|
var DEFAULT_API21 = "https://be.graph8.com";
|
|
1229
1283
|
var createDealsClient = (apiKey, apiUrl) => {
|
|
1230
1284
|
const baseUrl = apiUrl || DEFAULT_API21;
|
|
1231
|
-
const headers = () => ({ "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` });
|
|
1232
|
-
const toQuery = (params) => {
|
|
1233
|
-
const qs = new URLSearchParams();
|
|
1234
|
-
for (const [k, v] of Object.entries(params)) {
|
|
1235
|
-
if (v != null) qs.set(k, String(v));
|
|
1236
|
-
}
|
|
1237
|
-
const s = qs.toString();
|
|
1238
|
-
return s ? `?${s}` : "";
|
|
1239
|
-
};
|
|
1240
1285
|
return {
|
|
1241
1286
|
/** List all deal pipelines and their stages. */
|
|
1242
1287
|
async pipelines() {
|
|
1243
|
-
|
|
1244
|
-
return resp.json();
|
|
1288
|
+
return request(baseUrl, "/api/v1/deals/pipelines", apiKey);
|
|
1245
1289
|
},
|
|
1246
1290
|
/** List deals org-wide with optional filters and pagination. */
|
|
1247
1291
|
async list(params = {}) {
|
|
1248
|
-
|
|
1249
|
-
return resp.json();
|
|
1292
|
+
return request(baseUrl, "/api/v1/deals", apiKey, { query: params });
|
|
1250
1293
|
},
|
|
1251
1294
|
/** Create a new deal. */
|
|
1252
1295
|
async create(deal) {
|
|
1253
|
-
const resp = await
|
|
1254
|
-
|
|
1255
|
-
headers: headers(),
|
|
1256
|
-
body: JSON.stringify(deal)
|
|
1257
|
-
});
|
|
1258
|
-
const data = await resp.json();
|
|
1259
|
-
return data.data || data;
|
|
1296
|
+
const resp = await request(baseUrl, "/api/v1/deals", apiKey, { method: "POST", body: deal });
|
|
1297
|
+
return resp.data ?? resp;
|
|
1260
1298
|
},
|
|
1261
1299
|
/** Get a single deal by ID. */
|
|
1262
1300
|
async get(dealId) {
|
|
1263
|
-
const resp = await
|
|
1264
|
-
|
|
1265
|
-
return data.data || data;
|
|
1301
|
+
const resp = await request(baseUrl, `/api/v1/deals/${dealId}`, apiKey);
|
|
1302
|
+
return resp.data ?? resp;
|
|
1266
1303
|
},
|
|
1267
1304
|
/** Update a deal (partial). */
|
|
1268
1305
|
async update(dealId, fields) {
|
|
1269
|
-
const resp = await
|
|
1306
|
+
const resp = await request(baseUrl, `/api/v1/deals/${dealId}`, apiKey, {
|
|
1270
1307
|
method: "PATCH",
|
|
1271
|
-
|
|
1272
|
-
body: JSON.stringify(fields)
|
|
1308
|
+
body: fields
|
|
1273
1309
|
});
|
|
1274
|
-
|
|
1275
|
-
return data.data || data;
|
|
1310
|
+
return resp.data ?? resp;
|
|
1276
1311
|
},
|
|
1277
1312
|
/** Delete a deal. */
|
|
1278
1313
|
async delete(dealId) {
|
|
1279
|
-
|
|
1280
|
-
method: "DELETE",
|
|
1281
|
-
headers: headers()
|
|
1282
|
-
});
|
|
1283
|
-
return resp.json();
|
|
1314
|
+
return request(baseUrl, `/api/v1/deals/${dealId}`, apiKey, { method: "DELETE" });
|
|
1284
1315
|
},
|
|
1285
1316
|
/** Get all deals associated with a contact. */
|
|
1286
1317
|
async forContact(contactId) {
|
|
1287
|
-
|
|
1288
|
-
return resp.json();
|
|
1318
|
+
return request(baseUrl, `/api/v1/contacts/${contactId}/deals`, apiKey);
|
|
1289
1319
|
},
|
|
1290
1320
|
/** Get all deals associated with a company. */
|
|
1291
1321
|
async forCompany(companyId) {
|
|
1292
|
-
|
|
1293
|
-
return resp.json();
|
|
1322
|
+
return request(baseUrl, `/api/v1/companies/${companyId}/deals`, apiKey);
|
|
1294
1323
|
}
|
|
1295
1324
|
};
|
|
1296
1325
|
};
|
|
@@ -1299,77 +1328,53 @@ var createDealsClient = (apiKey, apiUrl) => {
|
|
|
1299
1328
|
var DEFAULT_API22 = "https://be.graph8.com";
|
|
1300
1329
|
var createInboxClient = (apiKey, apiUrl) => {
|
|
1301
1330
|
const baseUrl = apiUrl || DEFAULT_API22;
|
|
1302
|
-
const headers = () => ({ "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` });
|
|
1303
|
-
const toQuery = (params) => {
|
|
1304
|
-
const qs = new URLSearchParams();
|
|
1305
|
-
for (const [k, v] of Object.entries(params)) {
|
|
1306
|
-
if (v != null) qs.set(k, String(v));
|
|
1307
|
-
}
|
|
1308
|
-
const s = qs.toString();
|
|
1309
|
-
return s ? `?${s}` : "";
|
|
1310
|
-
};
|
|
1311
1331
|
return {
|
|
1312
1332
|
/** List inbox threads across email, SMS, and LinkedIn. */
|
|
1313
1333
|
async list(params = {}) {
|
|
1314
|
-
|
|
1315
|
-
return resp.json();
|
|
1334
|
+
return request(baseUrl, "/api/v1/inbox", apiKey, { query: params });
|
|
1316
1335
|
},
|
|
1317
1336
|
/** Get a single inbox thread. Defaults to email channel. */
|
|
1318
1337
|
async get(replyId, channel = "email") {
|
|
1319
|
-
const resp = await
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
const data = await resp.json();
|
|
1324
|
-
return data.data || data;
|
|
1338
|
+
const resp = await request(baseUrl, `/api/v1/inbox/${replyId}`, apiKey, {
|
|
1339
|
+
query: { channel }
|
|
1340
|
+
});
|
|
1341
|
+
return resp.data ?? resp;
|
|
1325
1342
|
},
|
|
1326
1343
|
/** Assign a user to an inbox thread. */
|
|
1327
1344
|
async assign(replyId, assigneeEmail, channel = "email") {
|
|
1328
|
-
const resp = await
|
|
1329
|
-
|
|
1330
|
-
{
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
}
|
|
1335
|
-
);
|
|
1336
|
-
const data = await resp.json();
|
|
1337
|
-
return data.data || data;
|
|
1345
|
+
const resp = await request(baseUrl, `/api/v1/inbox/${replyId}/assign`, apiKey, {
|
|
1346
|
+
method: "POST",
|
|
1347
|
+
query: { channel },
|
|
1348
|
+
body: { assignee_email: assigneeEmail }
|
|
1349
|
+
});
|
|
1350
|
+
return resp.data ?? resp;
|
|
1338
1351
|
},
|
|
1339
1352
|
/** Attach tag IDs to an inbox thread. */
|
|
1340
1353
|
async tag(replyId, tagIds, channel = "email") {
|
|
1341
|
-
const resp = await
|
|
1342
|
-
|
|
1343
|
-
{
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
}
|
|
1348
|
-
);
|
|
1349
|
-
const data = await resp.json();
|
|
1350
|
-
return data.data || data;
|
|
1354
|
+
const resp = await request(baseUrl, `/api/v1/inbox/${replyId}/tag`, apiKey, {
|
|
1355
|
+
method: "POST",
|
|
1356
|
+
query: { channel },
|
|
1357
|
+
body: { tag_ids: tagIds }
|
|
1358
|
+
});
|
|
1359
|
+
return resp.data ?? resp;
|
|
1351
1360
|
},
|
|
1352
1361
|
/**
|
|
1353
1362
|
* Generate an AI draft reply for a thread.
|
|
1354
1363
|
* Charges credits — server returns 402 if balance is insufficient.
|
|
1355
1364
|
*/
|
|
1356
1365
|
async draft(replyId, channel = "email") {
|
|
1357
|
-
const resp = await
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
const data = await resp.json();
|
|
1362
|
-
return data.data || data;
|
|
1366
|
+
const resp = await request(baseUrl, `/api/v1/inbox/${replyId}/draft`, apiKey, {
|
|
1367
|
+
query: { channel }
|
|
1368
|
+
});
|
|
1369
|
+
return resp.data ?? resp;
|
|
1363
1370
|
},
|
|
1364
1371
|
/** Send a reply through email, SMS, or LinkedIn. */
|
|
1365
1372
|
async send(replyId, payload) {
|
|
1366
|
-
const resp = await
|
|
1373
|
+
const resp = await request(baseUrl, `/api/v1/inbox/${replyId}/send`, apiKey, {
|
|
1367
1374
|
method: "POST",
|
|
1368
|
-
|
|
1369
|
-
body: JSON.stringify(payload)
|
|
1375
|
+
body: payload
|
|
1370
1376
|
});
|
|
1371
|
-
|
|
1372
|
-
return data.data || data;
|
|
1377
|
+
return resp.data ?? resp;
|
|
1373
1378
|
}
|
|
1374
1379
|
};
|
|
1375
1380
|
};
|
|
@@ -1378,104 +1383,72 @@ var createInboxClient = (apiKey, apiUrl) => {
|
|
|
1378
1383
|
var DEFAULT_API23 = "https://be.graph8.com";
|
|
1379
1384
|
var createQuotesClient = (apiKey, apiUrl) => {
|
|
1380
1385
|
const baseUrl = apiUrl || DEFAULT_API23;
|
|
1381
|
-
const headers = () => ({ "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` });
|
|
1382
|
-
const toQuery = (params) => {
|
|
1383
|
-
const qs = new URLSearchParams();
|
|
1384
|
-
for (const [k, v] of Object.entries(params)) {
|
|
1385
|
-
if (v != null) qs.set(k, String(v));
|
|
1386
|
-
}
|
|
1387
|
-
const s = qs.toString();
|
|
1388
|
-
return s ? `?${s}` : "";
|
|
1389
|
-
};
|
|
1390
1386
|
return {
|
|
1391
1387
|
/** List quotes org-wide with optional filters and pagination. */
|
|
1392
1388
|
async list(params = {}) {
|
|
1393
|
-
|
|
1394
|
-
return resp.json();
|
|
1389
|
+
return request(baseUrl, "/api/v1/quotes", apiKey, { query: params });
|
|
1395
1390
|
},
|
|
1396
1391
|
/** Get full details for a single quote. */
|
|
1397
1392
|
async get(quoteId) {
|
|
1398
|
-
const resp = await
|
|
1399
|
-
|
|
1400
|
-
return data.data || data;
|
|
1393
|
+
const resp = await request(baseUrl, `/api/v1/quotes/${quoteId}`, apiKey);
|
|
1394
|
+
return resp.data ?? resp;
|
|
1401
1395
|
},
|
|
1402
1396
|
/** Create a new quote from line items. */
|
|
1403
1397
|
async create(quote) {
|
|
1404
|
-
const resp = await
|
|
1398
|
+
const resp = await request(baseUrl, "/api/v1/quotes", apiKey, {
|
|
1405
1399
|
method: "POST",
|
|
1406
|
-
|
|
1407
|
-
body: JSON.stringify(quote)
|
|
1400
|
+
body: quote
|
|
1408
1401
|
});
|
|
1409
|
-
|
|
1410
|
-
return data.data || data;
|
|
1402
|
+
return resp.data ?? resp;
|
|
1411
1403
|
},
|
|
1412
1404
|
/** Update a draft quote (line items, expiry, notes). */
|
|
1413
1405
|
async update(quoteId, fields) {
|
|
1414
|
-
const resp = await
|
|
1406
|
+
const resp = await request(baseUrl, `/api/v1/quotes/${quoteId}`, apiKey, {
|
|
1415
1407
|
method: "PUT",
|
|
1416
|
-
|
|
1417
|
-
body: JSON.stringify(fields)
|
|
1408
|
+
body: fields
|
|
1418
1409
|
});
|
|
1419
|
-
|
|
1420
|
-
return data.data || data;
|
|
1410
|
+
return resp.data ?? resp;
|
|
1421
1411
|
},
|
|
1422
1412
|
/** Delete a draft quote (irreversible). */
|
|
1423
1413
|
async delete(quoteId) {
|
|
1424
|
-
|
|
1425
|
-
method: "DELETE",
|
|
1426
|
-
headers: headers()
|
|
1427
|
-
});
|
|
1428
|
-
return resp.json();
|
|
1414
|
+
return request(baseUrl, `/api/v1/quotes/${quoteId}`, apiKey, { method: "DELETE" });
|
|
1429
1415
|
},
|
|
1430
1416
|
/** Duplicate an existing quote (all line items copied into a new draft). */
|
|
1431
1417
|
async duplicate(quoteId) {
|
|
1432
|
-
const resp = await
|
|
1418
|
+
const resp = await request(baseUrl, `/api/v1/quotes/${quoteId}/duplicate`, apiKey, {
|
|
1433
1419
|
method: "POST",
|
|
1434
|
-
|
|
1435
|
-
body: JSON.stringify({})
|
|
1420
|
+
body: {}
|
|
1436
1421
|
});
|
|
1437
|
-
|
|
1438
|
-
return data.data || data;
|
|
1422
|
+
return resp.data ?? resp;
|
|
1439
1423
|
},
|
|
1440
1424
|
/** Convert a signed / sent quote back to editable draft state. */
|
|
1441
1425
|
async editAsDraft(quoteId) {
|
|
1442
|
-
|
|
1443
|
-
method: "POST",
|
|
1444
|
-
headers: headers(),
|
|
1445
|
-
body: JSON.stringify({})
|
|
1446
|
-
});
|
|
1447
|
-
return resp.json();
|
|
1426
|
+
return request(baseUrl, `/api/v1/quotes/${quoteId}/edit-as-draft`, apiKey, { method: "POST", body: {} });
|
|
1448
1427
|
},
|
|
1449
1428
|
/** Send a quote to its recipient via email (with signature + optional payment link). */
|
|
1450
1429
|
async send(quoteId, params) {
|
|
1451
|
-
const resp = await
|
|
1430
|
+
const resp = await request(baseUrl, `/api/v1/quotes/${quoteId}/send`, apiKey, {
|
|
1452
1431
|
method: "POST",
|
|
1453
|
-
|
|
1454
|
-
body: JSON.stringify(params)
|
|
1432
|
+
body: params
|
|
1455
1433
|
});
|
|
1456
|
-
|
|
1457
|
-
return data.data || data;
|
|
1434
|
+
return resp.data ?? resp;
|
|
1458
1435
|
},
|
|
1459
1436
|
/** List products available for line items. */
|
|
1460
1437
|
async products() {
|
|
1461
|
-
|
|
1462
|
-
return resp.json();
|
|
1438
|
+
return request(baseUrl, "/api/v1/quotable-products", apiKey);
|
|
1463
1439
|
},
|
|
1464
1440
|
/** Get org-level quote settings (currency, tax rate, payment providers, logo). */
|
|
1465
1441
|
async settings() {
|
|
1466
|
-
const resp = await
|
|
1467
|
-
|
|
1468
|
-
return data.data || data;
|
|
1442
|
+
const resp = await request(baseUrl, "/api/v1/quote-settings", apiKey);
|
|
1443
|
+
return resp.data ?? resp;
|
|
1469
1444
|
},
|
|
1470
1445
|
/** Get all quotes associated with a contact. */
|
|
1471
1446
|
async forContact(contactId) {
|
|
1472
|
-
|
|
1473
|
-
return resp.json();
|
|
1447
|
+
return request(baseUrl, `/api/v1/contacts/${contactId}/quotes`, apiKey);
|
|
1474
1448
|
},
|
|
1475
1449
|
/** Get all quotes associated with a company. */
|
|
1476
1450
|
async forCompany(companyId) {
|
|
1477
|
-
|
|
1478
|
-
return resp.json();
|
|
1451
|
+
return request(baseUrl, `/api/v1/companies/${companyId}/quotes`, apiKey);
|
|
1479
1452
|
}
|
|
1480
1453
|
};
|
|
1481
1454
|
};
|
|
@@ -1484,107 +1457,82 @@ var createQuotesClient = (apiKey, apiUrl) => {
|
|
|
1484
1457
|
var DEFAULT_API24 = "https://be.graph8.com";
|
|
1485
1458
|
var createPipelinesClient = (apiKey, apiUrl) => {
|
|
1486
1459
|
const baseUrl = apiUrl || DEFAULT_API24;
|
|
1487
|
-
const headers = () => ({ "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` });
|
|
1488
1460
|
return {
|
|
1489
1461
|
/** List all stage-checklist pipelines with stages, evidence, scripts. */
|
|
1490
1462
|
async list() {
|
|
1491
|
-
|
|
1492
|
-
return resp.json();
|
|
1463
|
+
return request(baseUrl, "/api/v1/pipelines", apiKey);
|
|
1493
1464
|
},
|
|
1494
1465
|
/** Get a single pipeline by ID. */
|
|
1495
1466
|
async get(pipelineId) {
|
|
1496
|
-
const resp = await
|
|
1497
|
-
|
|
1498
|
-
return data.data || data;
|
|
1467
|
+
const resp = await request(baseUrl, `/api/v1/pipelines/${pipelineId}`, apiKey);
|
|
1468
|
+
return resp.data ?? resp;
|
|
1499
1469
|
},
|
|
1500
1470
|
/** Get the canonical evidence-key library (used when defining stages). */
|
|
1501
1471
|
async evidenceLibrary() {
|
|
1502
|
-
|
|
1503
|
-
return resp.json();
|
|
1472
|
+
return request(baseUrl, "/api/v1/pipelines/evidence-library", apiKey);
|
|
1504
1473
|
},
|
|
1505
1474
|
/** Create a new pipeline. Defaults to a templated set of stages; pass blank=true for empty. */
|
|
1506
1475
|
async create(params) {
|
|
1507
|
-
const resp = await
|
|
1476
|
+
const resp = await request(baseUrl, "/api/v1/pipelines", apiKey, {
|
|
1508
1477
|
method: "POST",
|
|
1509
|
-
|
|
1510
|
-
body: JSON.stringify(params)
|
|
1478
|
+
body: params
|
|
1511
1479
|
});
|
|
1512
|
-
|
|
1513
|
-
return data.data || data;
|
|
1480
|
+
return resp.data ?? resp;
|
|
1514
1481
|
},
|
|
1515
1482
|
/** Update pipeline metadata (name, target). */
|
|
1516
1483
|
async update(pipelineId, fields) {
|
|
1517
|
-
const resp = await
|
|
1484
|
+
const resp = await request(baseUrl, `/api/v1/pipelines/${pipelineId}`, apiKey, {
|
|
1518
1485
|
method: "PUT",
|
|
1519
|
-
|
|
1520
|
-
body: JSON.stringify(fields)
|
|
1486
|
+
body: fields
|
|
1521
1487
|
});
|
|
1522
|
-
|
|
1523
|
-
return data.data || data;
|
|
1488
|
+
return resp.data ?? resp;
|
|
1524
1489
|
},
|
|
1525
1490
|
/** Delete a pipeline. Only allowed when no deals reference it. */
|
|
1526
1491
|
async delete(pipelineId) {
|
|
1527
|
-
|
|
1528
|
-
method: "DELETE",
|
|
1529
|
-
headers: headers()
|
|
1530
|
-
});
|
|
1531
|
-
return resp.json();
|
|
1492
|
+
return request(baseUrl, `/api/v1/pipelines/${pipelineId}`, apiKey, { method: "DELETE" });
|
|
1532
1493
|
},
|
|
1533
1494
|
/** Add a new stage to a pipeline. */
|
|
1534
1495
|
async createStage(pipelineId, stage) {
|
|
1535
|
-
const resp = await
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
return
|
|
1496
|
+
const resp = await request(
|
|
1497
|
+
baseUrl,
|
|
1498
|
+
`/api/v1/pipelines/${pipelineId}/stages`,
|
|
1499
|
+
apiKey,
|
|
1500
|
+
{ method: "POST", body: stage }
|
|
1501
|
+
);
|
|
1502
|
+
return resp.data ?? resp;
|
|
1542
1503
|
},
|
|
1543
1504
|
/** Update a stage (evidence, scripts, position). */
|
|
1544
1505
|
async updateStage(pipelineId, stageId, fields) {
|
|
1545
|
-
const resp = await
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
return
|
|
1506
|
+
const resp = await request(
|
|
1507
|
+
baseUrl,
|
|
1508
|
+
`/api/v1/pipelines/${pipelineId}/stages/${stageId}`,
|
|
1509
|
+
apiKey,
|
|
1510
|
+
{ method: "PUT", body: fields }
|
|
1511
|
+
);
|
|
1512
|
+
return resp.data ?? resp;
|
|
1552
1513
|
},
|
|
1553
1514
|
/** Reorder stages within a pipeline (pass full ordered list of stage IDs). */
|
|
1554
1515
|
async reorderStages(pipelineId, stageIds) {
|
|
1555
|
-
|
|
1516
|
+
return request(baseUrl, `/api/v1/pipelines/${pipelineId}/stages/reorder`, apiKey, {
|
|
1556
1517
|
method: "PUT",
|
|
1557
|
-
|
|
1558
|
-
body: JSON.stringify({ stage_ids: stageIds })
|
|
1518
|
+
body: { stage_ids: stageIds }
|
|
1559
1519
|
});
|
|
1560
|
-
return resp.json();
|
|
1561
1520
|
},
|
|
1562
1521
|
/** Delete a stage from a pipeline. */
|
|
1563
1522
|
async deleteStage(pipelineId, stageId) {
|
|
1564
|
-
|
|
1565
|
-
method: "DELETE",
|
|
1566
|
-
headers: headers()
|
|
1567
|
-
});
|
|
1568
|
-
return resp.json();
|
|
1523
|
+
return request(baseUrl, `/api/v1/pipelines/${pipelineId}/stages/${stageId}`, apiKey, { method: "DELETE" });
|
|
1569
1524
|
},
|
|
1570
1525
|
/** Get an AI-suggested pipeline based on org context (brand, ICP, messaging). */
|
|
1571
1526
|
async suggest() {
|
|
1572
|
-
|
|
1573
|
-
method: "POST",
|
|
1574
|
-
headers: headers(),
|
|
1575
|
-
body: JSON.stringify({})
|
|
1576
|
-
});
|
|
1577
|
-
return resp.json();
|
|
1527
|
+
return request(baseUrl, "/api/v1/pipelines/suggest", apiKey, { method: "POST", body: {} });
|
|
1578
1528
|
},
|
|
1579
1529
|
/** Create a real pipeline from an AI suggestion (optionally with overrides). */
|
|
1580
1530
|
async fromSuggestion(suggestionId, overrides) {
|
|
1581
|
-
const resp = await
|
|
1531
|
+
const resp = await request(baseUrl, "/api/v1/pipelines/from-suggestion", apiKey, {
|
|
1582
1532
|
method: "POST",
|
|
1583
|
-
|
|
1584
|
-
body: JSON.stringify({ suggestion_id: suggestionId, ...overrides || {} })
|
|
1533
|
+
body: { suggestion_id: suggestionId, ...overrides || {} }
|
|
1585
1534
|
});
|
|
1586
|
-
|
|
1587
|
-
return data.data || data;
|
|
1535
|
+
return resp.data ?? resp;
|
|
1588
1536
|
}
|
|
1589
1537
|
};
|
|
1590
1538
|
};
|
|
@@ -1593,36 +1541,23 @@ var createPipelinesClient = (apiKey, apiUrl) => {
|
|
|
1593
1541
|
var DEFAULT_API25 = "https://be.graph8.com";
|
|
1594
1542
|
var createWorkflowsClient = (apiKey, apiUrl) => {
|
|
1595
1543
|
const baseUrl = apiUrl || DEFAULT_API25;
|
|
1596
|
-
const headers = () => ({ "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` });
|
|
1597
|
-
const toQuery = (params) => {
|
|
1598
|
-
const qs = new URLSearchParams();
|
|
1599
|
-
for (const [k, v] of Object.entries(params)) {
|
|
1600
|
-
if (v != null) qs.set(k, String(v));
|
|
1601
|
-
}
|
|
1602
|
-
const s = qs.toString();
|
|
1603
|
-
return s ? `?${s}` : "";
|
|
1604
|
-
};
|
|
1605
1544
|
return {
|
|
1606
1545
|
/** List workflows org-wide. */
|
|
1607
1546
|
async list(params = {}) {
|
|
1608
|
-
|
|
1609
|
-
return resp.json();
|
|
1547
|
+
return request(baseUrl, "/api/v1/workflows", apiKey, { query: params });
|
|
1610
1548
|
},
|
|
1611
1549
|
/** Get full workflow definition (nodes, connections, trigger, execution state). */
|
|
1612
1550
|
async get(workflowId) {
|
|
1613
|
-
const resp = await
|
|
1614
|
-
|
|
1615
|
-
return data.data || data;
|
|
1551
|
+
const resp = await request(baseUrl, `/api/v1/workflows/${workflowId}`, apiKey);
|
|
1552
|
+
return resp.data ?? resp;
|
|
1616
1553
|
},
|
|
1617
1554
|
/** Create a new workflow. */
|
|
1618
1555
|
async create(params) {
|
|
1619
|
-
const resp = await
|
|
1556
|
+
const resp = await request(baseUrl, "/api/v1/workflows", apiKey, {
|
|
1620
1557
|
method: "POST",
|
|
1621
|
-
|
|
1622
|
-
body: JSON.stringify(params)
|
|
1558
|
+
body: params
|
|
1623
1559
|
});
|
|
1624
|
-
|
|
1625
|
-
return data.data || data;
|
|
1560
|
+
return resp.data ?? resp;
|
|
1626
1561
|
},
|
|
1627
1562
|
/**
|
|
1628
1563
|
* Update a workflow. Pass the full `config` (nodes + connections) to edit
|
|
@@ -1630,129 +1565,92 @@ var createWorkflowsClient = (apiKey, apiUrl) => {
|
|
|
1630
1565
|
* config and submitting the updated record.
|
|
1631
1566
|
*/
|
|
1632
1567
|
async update(workflowId, fields) {
|
|
1633
|
-
const resp = await
|
|
1568
|
+
const resp = await request(baseUrl, `/api/v1/workflows/${workflowId}`, apiKey, {
|
|
1634
1569
|
method: "PUT",
|
|
1635
|
-
|
|
1636
|
-
body: JSON.stringify(fields)
|
|
1570
|
+
body: fields
|
|
1637
1571
|
});
|
|
1638
|
-
|
|
1639
|
-
return data.data || data;
|
|
1572
|
+
return resp.data ?? resp;
|
|
1640
1573
|
},
|
|
1641
1574
|
/** Delete a workflow. */
|
|
1642
1575
|
async delete(workflowId) {
|
|
1643
|
-
|
|
1644
|
-
method: "DELETE",
|
|
1645
|
-
headers: headers()
|
|
1646
|
-
});
|
|
1647
|
-
return resp.json();
|
|
1576
|
+
return request(baseUrl, `/api/v1/workflows/${workflowId}`, apiKey, { method: "DELETE" });
|
|
1648
1577
|
},
|
|
1649
1578
|
/** Validate a workflow definition (orphans, dangling connections, required fields). */
|
|
1650
1579
|
async validate(workflow) {
|
|
1651
|
-
|
|
1652
|
-
method: "POST",
|
|
1653
|
-
headers: headers(),
|
|
1654
|
-
body: JSON.stringify(workflow)
|
|
1655
|
-
});
|
|
1656
|
-
return resp.json();
|
|
1580
|
+
return request(baseUrl, "/api/v1/workflows/validate", apiKey, { method: "POST", body: workflow });
|
|
1657
1581
|
},
|
|
1658
1582
|
/** Execute a workflow immediately with a trigger payload. */
|
|
1659
1583
|
async execute(workflowId, triggerPayload = {}) {
|
|
1660
|
-
const resp = await
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
return
|
|
1584
|
+
const resp = await request(
|
|
1585
|
+
baseUrl,
|
|
1586
|
+
`/api/v1/workflows/${workflowId}/execute`,
|
|
1587
|
+
apiKey,
|
|
1588
|
+
{ method: "POST", body: { trigger_payload: triggerPayload } }
|
|
1589
|
+
);
|
|
1590
|
+
return resp.data ?? resp;
|
|
1667
1591
|
},
|
|
1668
|
-
/** Get the status +
|
|
1592
|
+
/** Get the status + outputs of a single execution. */
|
|
1669
1593
|
async getExecution(executionId) {
|
|
1670
|
-
const resp = await
|
|
1671
|
-
|
|
1672
|
-
|
|
1594
|
+
const resp = await request(
|
|
1595
|
+
baseUrl,
|
|
1596
|
+
`/api/v1/workflows/executions/${executionId}`,
|
|
1597
|
+
apiKey
|
|
1598
|
+
);
|
|
1599
|
+
return resp.data ?? resp;
|
|
1673
1600
|
},
|
|
1674
|
-
/** Pause
|
|
1601
|
+
/** Pause a running execution. */
|
|
1675
1602
|
async pauseExecution(executionId) {
|
|
1676
|
-
|
|
1677
|
-
method: "POST",
|
|
1678
|
-
headers: headers(),
|
|
1679
|
-
body: JSON.stringify({})
|
|
1680
|
-
});
|
|
1681
|
-
return resp.json();
|
|
1603
|
+
return request(baseUrl, `/api/v1/workflows/executions/${executionId}/pause`, apiKey, { method: "POST" });
|
|
1682
1604
|
},
|
|
1683
1605
|
/** Resume a paused execution. */
|
|
1684
1606
|
async resumeExecution(executionId) {
|
|
1685
|
-
|
|
1686
|
-
method: "POST",
|
|
1687
|
-
headers: headers(),
|
|
1688
|
-
body: JSON.stringify({})
|
|
1689
|
-
});
|
|
1690
|
-
return resp.json();
|
|
1607
|
+
return request(baseUrl, `/api/v1/workflows/executions/${executionId}/resume`, apiKey, { method: "POST" });
|
|
1691
1608
|
},
|
|
1692
|
-
/** Stop an execution
|
|
1609
|
+
/** Stop an execution. */
|
|
1693
1610
|
async stopExecution(executionId) {
|
|
1694
|
-
|
|
1695
|
-
method: "POST",
|
|
1696
|
-
headers: headers(),
|
|
1697
|
-
body: JSON.stringify({})
|
|
1698
|
-
});
|
|
1699
|
-
return resp.json();
|
|
1611
|
+
return request(baseUrl, `/api/v1/workflows/executions/${executionId}/stop`, apiKey, { method: "POST" });
|
|
1700
1612
|
},
|
|
1701
|
-
/** Get the status
|
|
1613
|
+
/** Get the trigger status (e.g. schedule / webhook wiring) for a workflow. */
|
|
1702
1614
|
async getTriggerStatus(workflowId) {
|
|
1703
|
-
|
|
1704
|
-
return resp.json();
|
|
1615
|
+
return request(baseUrl, `/api/v1/workflows/${workflowId}/trigger-status`, apiKey);
|
|
1705
1616
|
},
|
|
1706
|
-
/** Reset
|
|
1617
|
+
/** Reset a workflow's trigger cursor / state. */
|
|
1707
1618
|
async resetTrigger(workflowId) {
|
|
1708
|
-
|
|
1709
|
-
method: "POST",
|
|
1710
|
-
headers: headers(),
|
|
1711
|
-
body: JSON.stringify({})
|
|
1712
|
-
});
|
|
1713
|
-
return resp.json();
|
|
1619
|
+
return request(baseUrl, `/api/v1/workflows/${workflowId}/trigger-reset`, apiKey, { method: "POST" });
|
|
1714
1620
|
},
|
|
1715
|
-
/**
|
|
1716
|
-
* List available node types with schemas. Pass a `type` param to fetch one type's full schema.
|
|
1717
|
-
*/
|
|
1621
|
+
/** Catalog of available workflow node types with config + output schemas. */
|
|
1718
1622
|
async nodeTypes(params = {}) {
|
|
1719
|
-
|
|
1720
|
-
|
|
1623
|
+
return request(baseUrl, "/api/v1/workflows/node-types/schema", apiKey, {
|
|
1624
|
+
query: params
|
|
1625
|
+
});
|
|
1721
1626
|
},
|
|
1722
|
-
/** Slack
|
|
1627
|
+
/** Slack users available to workflow nodes. */
|
|
1723
1628
|
async listSlackUsers() {
|
|
1724
|
-
|
|
1725
|
-
return resp.json();
|
|
1629
|
+
return request(baseUrl, "/api/v1/workflows/integrations/slack/users", apiKey);
|
|
1726
1630
|
},
|
|
1727
|
-
/** Slack channels. */
|
|
1631
|
+
/** Slack channels available to workflow nodes. */
|
|
1728
1632
|
async listSlackChannels() {
|
|
1729
|
-
|
|
1730
|
-
return resp.json();
|
|
1633
|
+
return request(baseUrl, "/api/v1/workflows/integrations/slack/channels", apiKey);
|
|
1731
1634
|
},
|
|
1732
|
-
/** Roam
|
|
1635
|
+
/** Roam users available to workflow nodes. */
|
|
1733
1636
|
async listRoamUsers() {
|
|
1734
|
-
|
|
1735
|
-
return resp.json();
|
|
1637
|
+
return request(baseUrl, "/api/v1/workflows/integrations/roam/users", apiKey);
|
|
1736
1638
|
},
|
|
1737
|
-
/** Roam
|
|
1639
|
+
/** Roam groups available to workflow nodes. */
|
|
1738
1640
|
async listRoamGroups() {
|
|
1739
|
-
|
|
1740
|
-
return resp.json();
|
|
1641
|
+
return request(baseUrl, "/api/v1/workflows/integrations/roam/groups", apiKey);
|
|
1741
1642
|
},
|
|
1742
|
-
/**
|
|
1643
|
+
/** MCP servers available to workflow nodes. */
|
|
1743
1644
|
async listMcpServers() {
|
|
1744
|
-
|
|
1745
|
-
return resp.json();
|
|
1645
|
+
return request(baseUrl, "/api/v1/workflows/mcp-servers", apiKey);
|
|
1746
1646
|
},
|
|
1747
|
-
/**
|
|
1647
|
+
/** Disposition options available to workflow nodes. */
|
|
1748
1648
|
async listDispositions() {
|
|
1749
|
-
|
|
1750
|
-
return resp.json();
|
|
1649
|
+
return request(baseUrl, "/api/v1/workflows/dispositions", apiKey);
|
|
1751
1650
|
},
|
|
1752
|
-
/** Form field
|
|
1651
|
+
/** Form field definitions for a given form (used by form-trigger nodes). */
|
|
1753
1652
|
async listFormFields(formId) {
|
|
1754
|
-
|
|
1755
|
-
return resp.json();
|
|
1653
|
+
return request(baseUrl, `/api/v1/workflows/forms/${formId}/fields`, apiKey);
|
|
1756
1654
|
}
|
|
1757
1655
|
};
|
|
1758
1656
|
};
|
|
@@ -1761,127 +1659,87 @@ var createWorkflowsClient = (apiKey, apiUrl) => {
|
|
|
1761
1659
|
var DEFAULT_API26 = "https://be.graph8.com";
|
|
1762
1660
|
var createSkillsClient = (apiKey, apiUrl) => {
|
|
1763
1661
|
const baseUrl = apiUrl || DEFAULT_API26;
|
|
1764
|
-
const headers = () => ({ "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` });
|
|
1765
|
-
const toQuery = (params) => {
|
|
1766
|
-
const qs = new URLSearchParams();
|
|
1767
|
-
for (const [k, v] of Object.entries(params)) {
|
|
1768
|
-
if (v != null) qs.set(k, String(v));
|
|
1769
|
-
}
|
|
1770
|
-
const s = qs.toString();
|
|
1771
|
-
return s ? `?${s}` : "";
|
|
1772
|
-
};
|
|
1773
1662
|
return {
|
|
1774
1663
|
/** List skills. */
|
|
1775
1664
|
async list(params = {}) {
|
|
1776
|
-
|
|
1777
|
-
return resp.json();
|
|
1665
|
+
return request(baseUrl, "/api/v1/skills", apiKey, { query: params });
|
|
1778
1666
|
},
|
|
1779
1667
|
/** Get a skill by ID. */
|
|
1780
1668
|
async get(skillId) {
|
|
1781
|
-
const resp = await
|
|
1782
|
-
|
|
1783
|
-
return data.data || data;
|
|
1669
|
+
const resp = await request(baseUrl, `/api/v1/skills/${skillId}`, apiKey);
|
|
1670
|
+
return resp.data ?? resp;
|
|
1784
1671
|
},
|
|
1785
1672
|
/** Get the variables required by a skill (extracted from prompt or body template). */
|
|
1786
1673
|
async getVariables(skillId) {
|
|
1787
|
-
|
|
1788
|
-
return resp.json();
|
|
1674
|
+
return request(baseUrl, `/api/v1/skills/${skillId}/variables`, apiKey);
|
|
1789
1675
|
},
|
|
1790
1676
|
/** List available LLM models. */
|
|
1791
1677
|
async listModels() {
|
|
1792
|
-
|
|
1793
|
-
return resp.json();
|
|
1678
|
+
return request(baseUrl, "/api/v1/skills/models", apiKey);
|
|
1794
1679
|
},
|
|
1795
1680
|
/** List skill templates. */
|
|
1796
1681
|
async listTemplates(params = {}) {
|
|
1797
|
-
|
|
1798
|
-
return resp.json();
|
|
1682
|
+
return request(baseUrl, "/api/v1/skills/templates", apiKey, { query: params });
|
|
1799
1683
|
},
|
|
1800
1684
|
/** Create an LLM skill (prompt + model + schemas). */
|
|
1801
1685
|
async createLLM(params) {
|
|
1802
|
-
const resp = await
|
|
1686
|
+
const resp = await request(baseUrl, "/api/v1/skills", apiKey, {
|
|
1803
1687
|
method: "POST",
|
|
1804
|
-
|
|
1805
|
-
body: JSON.stringify({ ...params, type: "llm" })
|
|
1688
|
+
body: { ...params, type: "llm" }
|
|
1806
1689
|
});
|
|
1807
|
-
|
|
1808
|
-
return data.data || data;
|
|
1690
|
+
return resp.data ?? resp;
|
|
1809
1691
|
},
|
|
1810
1692
|
/** Create an API skill (HTTP request wrapper). */
|
|
1811
1693
|
async createAPI(params) {
|
|
1812
|
-
const resp = await
|
|
1694
|
+
const resp = await request(baseUrl, "/api/v1/skills", apiKey, {
|
|
1813
1695
|
method: "POST",
|
|
1814
|
-
|
|
1815
|
-
body: JSON.stringify({ ...params, type: "api" })
|
|
1696
|
+
body: { ...params, type: "api" }
|
|
1816
1697
|
});
|
|
1817
|
-
|
|
1818
|
-
return data.data || data;
|
|
1698
|
+
return resp.data ?? resp;
|
|
1819
1699
|
},
|
|
1820
1700
|
/** Create a skill from a built-in template. */
|
|
1821
1701
|
async createFromTemplate(params) {
|
|
1822
|
-
const resp = await
|
|
1702
|
+
const resp = await request(baseUrl, "/api/v1/skills/from-template", apiKey, {
|
|
1823
1703
|
method: "POST",
|
|
1824
|
-
|
|
1825
|
-
body: JSON.stringify(params)
|
|
1704
|
+
body: params
|
|
1826
1705
|
});
|
|
1827
|
-
|
|
1828
|
-
return data.data || data;
|
|
1706
|
+
return resp.data ?? resp;
|
|
1829
1707
|
},
|
|
1830
1708
|
/** Lift a workflow node into a reusable skill. */
|
|
1831
1709
|
async createFromNode(params) {
|
|
1832
|
-
const resp = await
|
|
1710
|
+
const resp = await request(baseUrl, "/api/v1/skills/from-node", apiKey, {
|
|
1833
1711
|
method: "POST",
|
|
1834
|
-
|
|
1835
|
-
body: JSON.stringify(params)
|
|
1712
|
+
body: params
|
|
1836
1713
|
});
|
|
1837
|
-
|
|
1838
|
-
return data.data || data;
|
|
1714
|
+
return resp.data ?? resp;
|
|
1839
1715
|
},
|
|
1840
1716
|
/** Update an LLM skill. */
|
|
1841
1717
|
async updateLLM(skillId, fields) {
|
|
1842
|
-
const resp = await
|
|
1718
|
+
const resp = await request(baseUrl, `/api/v1/skills/${skillId}`, apiKey, {
|
|
1843
1719
|
method: "PUT",
|
|
1844
|
-
|
|
1845
|
-
body: JSON.stringify({ ...fields, type: "llm" })
|
|
1720
|
+
body: { ...fields, type: "llm" }
|
|
1846
1721
|
});
|
|
1847
|
-
|
|
1848
|
-
return data.data || data;
|
|
1722
|
+
return resp.data ?? resp;
|
|
1849
1723
|
},
|
|
1850
1724
|
/** Update an API skill. */
|
|
1851
1725
|
async updateAPI(skillId, fields) {
|
|
1852
|
-
const resp = await
|
|
1726
|
+
const resp = await request(baseUrl, `/api/v1/skills/${skillId}`, apiKey, {
|
|
1853
1727
|
method: "PUT",
|
|
1854
|
-
|
|
1855
|
-
body: JSON.stringify({ ...fields, type: "api" })
|
|
1728
|
+
body: { ...fields, type: "api" }
|
|
1856
1729
|
});
|
|
1857
|
-
|
|
1858
|
-
return data.data || data;
|
|
1730
|
+
return resp.data ?? resp;
|
|
1859
1731
|
},
|
|
1860
1732
|
/** Delete a skill (irreversible if in-use workflows exist). */
|
|
1861
1733
|
async delete(skillId) {
|
|
1862
|
-
|
|
1863
|
-
method: "DELETE",
|
|
1864
|
-
headers: headers()
|
|
1865
|
-
});
|
|
1866
|
-
return resp.json();
|
|
1734
|
+
return request(baseUrl, `/api/v1/skills/${skillId}`, apiKey, { method: "DELETE" });
|
|
1867
1735
|
},
|
|
1868
1736
|
/** Validate a skill definition (without saving). */
|
|
1869
1737
|
async validate(skill) {
|
|
1870
|
-
|
|
1871
|
-
method: "POST",
|
|
1872
|
-
headers: headers(),
|
|
1873
|
-
body: JSON.stringify(skill)
|
|
1874
|
-
});
|
|
1875
|
-
return resp.json();
|
|
1738
|
+
return request(baseUrl, "/api/v1/skills/validate", apiKey, { method: "POST", body: skill });
|
|
1876
1739
|
},
|
|
1877
1740
|
/** Execute a skill immediately with an input payload (test / preview). */
|
|
1878
1741
|
async execute(skillId, inputPayload) {
|
|
1879
|
-
|
|
1880
|
-
method: "POST",
|
|
1881
|
-
headers: headers(),
|
|
1882
|
-
body: JSON.stringify(inputPayload)
|
|
1883
|
-
});
|
|
1884
|
-
return resp.json();
|
|
1742
|
+
return request(baseUrl, `/api/v1/skills/${skillId}/execute`, apiKey, { method: "POST", body: inputPayload });
|
|
1885
1743
|
}
|
|
1886
1744
|
};
|
|
1887
1745
|
};
|
|
@@ -1890,23 +1748,9 @@ var createSkillsClient = (apiKey, apiUrl) => {
|
|
|
1890
1748
|
var DEFAULT_API27 = "https://be.graph8.com";
|
|
1891
1749
|
var createIntentClient = (apiKey, apiUrl) => {
|
|
1892
1750
|
const baseUrl = apiUrl || DEFAULT_API27;
|
|
1893
|
-
const
|
|
1894
|
-
const
|
|
1895
|
-
|
|
1896
|
-
return resp.json();
|
|
1897
|
-
};
|
|
1898
|
-
const post = async (path, body = {}) => {
|
|
1899
|
-
const resp = await fetch(`${baseUrl}/api/v1${path}`, {
|
|
1900
|
-
method: "POST",
|
|
1901
|
-
headers: headers(),
|
|
1902
|
-
body: JSON.stringify(body)
|
|
1903
|
-
});
|
|
1904
|
-
return resp.json();
|
|
1905
|
-
};
|
|
1906
|
-
const del = async (path) => {
|
|
1907
|
-
const resp = await fetch(`${baseUrl}/api/v1${path}`, { method: "DELETE", headers: headers() });
|
|
1908
|
-
return resp.json();
|
|
1909
|
-
};
|
|
1751
|
+
const get = (path) => request(baseUrl, `/api/v1${path}`, apiKey);
|
|
1752
|
+
const post = (path, body = {}) => request(baseUrl, `/api/v1${path}`, apiKey, { method: "POST", body });
|
|
1753
|
+
const del = (path) => request(baseUrl, `/api/v1${path}`, apiKey, { method: "DELETE" });
|
|
1910
1754
|
return {
|
|
1911
1755
|
/** Org-level intent stats (totals over the last 30 days). */
|
|
1912
1756
|
async stats() {
|
|
@@ -1963,12 +1807,10 @@ var createIntentClient = (apiKey, apiUrl) => {
|
|
|
1963
1807
|
* of the intent surface — we call it directly here instead of through the shared `post()` helper.
|
|
1964
1808
|
*/
|
|
1965
1809
|
async urlCompanies(url, params = {}) {
|
|
1966
|
-
|
|
1810
|
+
return request(baseUrl, "/intent-search/url-companies", apiKey, {
|
|
1967
1811
|
method: "POST",
|
|
1968
|
-
|
|
1969
|
-
body: JSON.stringify({ url, ...params })
|
|
1812
|
+
body: { url, ...params }
|
|
1970
1813
|
});
|
|
1971
|
-
return resp.json();
|
|
1972
1814
|
}
|
|
1973
1815
|
};
|
|
1974
1816
|
};
|
|
@@ -1977,19 +1819,7 @@ var createIntentClient = (apiKey, apiUrl) => {
|
|
|
1977
1819
|
var DEFAULT_API28 = "https://be.graph8.com";
|
|
1978
1820
|
var createStudioClient = (apiKey, apiUrl) => {
|
|
1979
1821
|
const baseUrl = apiUrl || DEFAULT_API28;
|
|
1980
|
-
const
|
|
1981
|
-
const toQuery = (params) => {
|
|
1982
|
-
const qs = new URLSearchParams();
|
|
1983
|
-
for (const [k, v] of Object.entries(params)) {
|
|
1984
|
-
if (v != null) qs.set(k, String(v));
|
|
1985
|
-
}
|
|
1986
|
-
const s = qs.toString();
|
|
1987
|
-
return s ? `?${s}` : "";
|
|
1988
|
-
};
|
|
1989
|
-
const get = async (path, params = {}) => {
|
|
1990
|
-
const resp = await fetch(`${baseUrl}/api/v1${path}${toQuery(params)}`, { headers: headers() });
|
|
1991
|
-
return resp.json();
|
|
1992
|
-
};
|
|
1822
|
+
const get = (path, params = {}) => request(baseUrl, `/api/v1${path}`, apiKey, { query: params });
|
|
1993
1823
|
return {
|
|
1994
1824
|
/** Org-level Studio documents (brand_brief, value_props, messaging_house, etc.).
|
|
1995
1825
|
* `include_content` defaults to true server-side, so each document includes
|
|
@@ -2020,33 +1850,187 @@ var createStudioClient = (apiKey, apiUrl) => {
|
|
|
2020
1850
|
var DEFAULT_API29 = "https://be.graph8.com";
|
|
2021
1851
|
var createMeetingsClient = (apiKey, apiUrl) => {
|
|
2022
1852
|
const baseUrl = apiUrl || DEFAULT_API29;
|
|
2023
|
-
const headers = () => ({ "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` });
|
|
2024
|
-
const toQuery = (params) => {
|
|
2025
|
-
const qs = new URLSearchParams();
|
|
2026
|
-
for (const [k, v] of Object.entries(params)) {
|
|
2027
|
-
if (v != null) qs.set(k, String(v));
|
|
2028
|
-
}
|
|
2029
|
-
const s = qs.toString();
|
|
2030
|
-
return s ? `?${s}` : "";
|
|
2031
|
-
};
|
|
2032
1853
|
return {
|
|
2033
1854
|
/** List meetings with optional filters. Returns summary rows without transcript / analysis. */
|
|
2034
1855
|
async list(params = {}) {
|
|
2035
|
-
|
|
2036
|
-
return resp.json();
|
|
1856
|
+
return request(baseUrl, "/api/v1/inbox/meetings", apiKey, { query: params });
|
|
2037
1857
|
},
|
|
2038
1858
|
/** Get full meeting detail including transcript + AI analysis (transcript available 1-5 min after meeting ends). */
|
|
2039
1859
|
async get(meetingId) {
|
|
2040
|
-
const resp = await
|
|
2041
|
-
|
|
2042
|
-
|
|
1860
|
+
const resp = await request(baseUrl, `/api/v1/inbox/meetings/${meetingId}`, apiKey);
|
|
1861
|
+
return resp.data ?? resp;
|
|
1862
|
+
}
|
|
1863
|
+
};
|
|
1864
|
+
};
|
|
1865
|
+
|
|
1866
|
+
// src/audiences.ts
|
|
1867
|
+
var DEFAULT_API30 = "https://be.graph8.com";
|
|
1868
|
+
var createAudiencesClient = (apiKey, apiUrl) => {
|
|
1869
|
+
const baseUrl = apiUrl || DEFAULT_API30;
|
|
1870
|
+
const base = "/api/v1/audience-syncs";
|
|
1871
|
+
return {
|
|
1872
|
+
/** List all audience syncs for the organization. */
|
|
1873
|
+
async list() {
|
|
1874
|
+
return request(baseUrl, base, apiKey);
|
|
1875
|
+
},
|
|
1876
|
+
/** Create a new audience sync to an ad platform. */
|
|
1877
|
+
async create(params) {
|
|
1878
|
+
const resp = await request(baseUrl, base, apiKey, {
|
|
1879
|
+
method: "POST",
|
|
1880
|
+
body: params
|
|
1881
|
+
});
|
|
1882
|
+
return resp.data ?? resp;
|
|
1883
|
+
},
|
|
1884
|
+
/** Get a single audience sync by ID. */
|
|
1885
|
+
async get(configId) {
|
|
1886
|
+
const resp = await request(baseUrl, `${base}/${configId}`, apiKey);
|
|
1887
|
+
return resp.data ?? resp;
|
|
1888
|
+
},
|
|
1889
|
+
/** Update an audience sync (partial). */
|
|
1890
|
+
async update(configId, fields) {
|
|
1891
|
+
const resp = await request(baseUrl, `${base}/${configId}`, apiKey, {
|
|
1892
|
+
method: "PATCH",
|
|
1893
|
+
body: fields
|
|
1894
|
+
});
|
|
1895
|
+
return resp.data ?? resp;
|
|
1896
|
+
},
|
|
1897
|
+
/** Delete an audience sync. */
|
|
1898
|
+
async delete(configId) {
|
|
1899
|
+
return request(baseUrl, `${base}/${configId}`, apiKey, { method: "DELETE" });
|
|
1900
|
+
},
|
|
1901
|
+
/** Trigger an immediate sync run for a config. */
|
|
1902
|
+
async trigger(configId) {
|
|
1903
|
+
return request(baseUrl, `${base}/${configId}/trigger`, apiKey, { method: "POST" });
|
|
1904
|
+
},
|
|
1905
|
+
/** List recent sync runs for a config (most recent first). */
|
|
1906
|
+
async runs(configId) {
|
|
1907
|
+
return request(baseUrl, `${base}/${configId}/runs`, apiKey);
|
|
1908
|
+
},
|
|
1909
|
+
/** List recent sync errors for a config. */
|
|
1910
|
+
async errors(configId) {
|
|
1911
|
+
return request(baseUrl, `${base}/${configId}/errors`, apiKey);
|
|
1912
|
+
}
|
|
1913
|
+
};
|
|
1914
|
+
};
|
|
1915
|
+
|
|
1916
|
+
// src/search.ts
|
|
1917
|
+
var DEFAULT_API31 = "https://be.graph8.com";
|
|
1918
|
+
var createSearchClient = (apiKey, apiUrl) => {
|
|
1919
|
+
const baseUrl = apiUrl || DEFAULT_API31;
|
|
1920
|
+
const body = (p) => ({ filters: [], page: 1, limit: 25, ...p });
|
|
1921
|
+
return {
|
|
1922
|
+
/** Search open-data contacts by filter. */
|
|
1923
|
+
async contacts(params = {}) {
|
|
1924
|
+
return request(baseUrl, "/api/v1/search/contacts", apiKey, { method: "POST", body: body(params) });
|
|
1925
|
+
},
|
|
1926
|
+
/** Search open-data companies by filter. */
|
|
1927
|
+
async companies(params = {}) {
|
|
1928
|
+
return request(baseUrl, "/api/v1/search/companies", apiKey, { method: "POST", body: body(params) });
|
|
1929
|
+
},
|
|
1930
|
+
/** Search contacts and save the matches into a new list. */
|
|
1931
|
+
async saveContacts(params) {
|
|
1932
|
+
const resp = await request(baseUrl, "/api/v1/search/contacts/save", apiKey, {
|
|
1933
|
+
method: "POST",
|
|
1934
|
+
body: { filters: [], page: 1, limit: 25, max_results: 1e3, ...params }
|
|
1935
|
+
});
|
|
1936
|
+
return resp.data ?? resp;
|
|
1937
|
+
},
|
|
1938
|
+
/** Search companies and save the matches into a new list. */
|
|
1939
|
+
async saveCompanies(params) {
|
|
1940
|
+
const resp = await request(baseUrl, "/api/v1/search/companies/save", apiKey, {
|
|
1941
|
+
method: "POST",
|
|
1942
|
+
body: { filters: [], page: 1, limit: 25, max_results: 1e3, ...params }
|
|
1943
|
+
});
|
|
1944
|
+
return resp.data ?? resp;
|
|
1945
|
+
}
|
|
1946
|
+
};
|
|
1947
|
+
};
|
|
1948
|
+
|
|
1949
|
+
// src/agency.ts
|
|
1950
|
+
var DEFAULT_API32 = "https://be.graph8.com";
|
|
1951
|
+
var createAgencyClient = (apiKey, apiUrl) => {
|
|
1952
|
+
const baseUrl = apiUrl || DEFAULT_API32;
|
|
1953
|
+
return {
|
|
1954
|
+
/** Describe the agency credential: agency org + authorized client count. */
|
|
1955
|
+
async me() {
|
|
1956
|
+
const resp = await request(baseUrl, "/api/v1/agency/me", apiKey);
|
|
1957
|
+
return resp.data ?? resp;
|
|
1958
|
+
},
|
|
1959
|
+
/** List the client orgs this agency key may target via `X-Target-Org-Id`. */
|
|
1960
|
+
async clients() {
|
|
1961
|
+
return request(baseUrl, "/api/v1/agency/clients", apiKey);
|
|
1962
|
+
}
|
|
1963
|
+
};
|
|
1964
|
+
};
|
|
1965
|
+
|
|
1966
|
+
// src/marketplace.ts
|
|
1967
|
+
var DEFAULT_API33 = "https://be.graph8.com";
|
|
1968
|
+
var createMarketplaceClient = (apiKey, apiUrl) => {
|
|
1969
|
+
const baseUrl = apiUrl || DEFAULT_API33;
|
|
1970
|
+
const base = "/api/v1/marketplace";
|
|
1971
|
+
return {
|
|
1972
|
+
/** Your own marketplace SDR profile. */
|
|
1973
|
+
async profile() {
|
|
1974
|
+
const resp = await request(baseUrl, `${base}/me/profile`, apiKey);
|
|
1975
|
+
return resp.data ?? resp;
|
|
1976
|
+
},
|
|
1977
|
+
/** Pending hire offers you can accept or reject. */
|
|
1978
|
+
async offers() {
|
|
1979
|
+
const resp = await request(
|
|
1980
|
+
baseUrl,
|
|
1981
|
+
`${base}/me/offers`,
|
|
1982
|
+
apiKey
|
|
1983
|
+
);
|
|
1984
|
+
return resp.data ?? resp;
|
|
1985
|
+
},
|
|
1986
|
+
/** Accept a pending hire offer (by hiring id). */
|
|
1987
|
+
async acceptOffer(hiringId) {
|
|
1988
|
+
const resp = await request(
|
|
1989
|
+
baseUrl,
|
|
1990
|
+
`${base}/me/offers/${hiringId}/accept`,
|
|
1991
|
+
apiKey,
|
|
1992
|
+
{ method: "POST" }
|
|
1993
|
+
);
|
|
1994
|
+
return resp.data ?? resp;
|
|
1995
|
+
},
|
|
1996
|
+
/** Reject a pending hire offer (by hiring id). */
|
|
1997
|
+
async rejectOffer(hiringId) {
|
|
1998
|
+
const resp = await request(
|
|
1999
|
+
baseUrl,
|
|
2000
|
+
`${base}/me/offers/${hiringId}/reject`,
|
|
2001
|
+
apiKey,
|
|
2002
|
+
{ method: "POST" }
|
|
2003
|
+
);
|
|
2004
|
+
return resp.data ?? resp;
|
|
2005
|
+
},
|
|
2006
|
+
/** Your active hiring contracts. */
|
|
2007
|
+
async hirings() {
|
|
2008
|
+
const resp = await request(
|
|
2009
|
+
baseUrl,
|
|
2010
|
+
`${base}/me/hirings`,
|
|
2011
|
+
apiKey
|
|
2012
|
+
);
|
|
2013
|
+
return resp.data ?? resp;
|
|
2014
|
+
}
|
|
2015
|
+
};
|
|
2016
|
+
};
|
|
2017
|
+
|
|
2018
|
+
// src/snippet.ts
|
|
2019
|
+
var DEFAULT_API34 = "https://be.graph8.com";
|
|
2020
|
+
var createSnippetClient = (apiKey, apiUrl) => {
|
|
2021
|
+
const baseUrl = apiUrl || DEFAULT_API34;
|
|
2022
|
+
return {
|
|
2023
|
+
/** Get your org's tracking snippet (write key + React/script-tag embeds + config). */
|
|
2024
|
+
async get() {
|
|
2025
|
+
const resp = await request(baseUrl, "/api/v1/snippet", apiKey);
|
|
2026
|
+
return resp.data ?? resp;
|
|
2043
2027
|
}
|
|
2044
2028
|
};
|
|
2045
2029
|
};
|
|
2046
2030
|
|
|
2047
2031
|
// src/core.ts
|
|
2048
2032
|
var DEFAULT_HOST = "https://t.graph8.com";
|
|
2049
|
-
var
|
|
2033
|
+
var DEFAULT_API35 = "https://be.graph8.com";
|
|
2050
2034
|
var G8 = class {
|
|
2051
2035
|
constructor() {
|
|
2052
2036
|
/** @internal */
|
|
@@ -2111,6 +2095,16 @@ var G8 = class {
|
|
|
2111
2095
|
this._studio = null;
|
|
2112
2096
|
/** @internal */
|
|
2113
2097
|
this._meetings = null;
|
|
2098
|
+
/** @internal */
|
|
2099
|
+
this._audiences = null;
|
|
2100
|
+
/** @internal */
|
|
2101
|
+
this._search = null;
|
|
2102
|
+
/** @internal */
|
|
2103
|
+
this._agency = null;
|
|
2104
|
+
/** @internal */
|
|
2105
|
+
this._marketplace = null;
|
|
2106
|
+
/** @internal */
|
|
2107
|
+
this._snippet = null;
|
|
2114
2108
|
}
|
|
2115
2109
|
/**
|
|
2116
2110
|
* Initialize the graph8 SDK. Must be called before any other method.
|
|
@@ -2125,7 +2119,7 @@ var G8 = class {
|
|
|
2125
2119
|
debug: config.debug
|
|
2126
2120
|
});
|
|
2127
2121
|
}
|
|
2128
|
-
const apiUrl = config.apiUrl ||
|
|
2122
|
+
const apiUrl = config.apiUrl || DEFAULT_API35;
|
|
2129
2123
|
const writeKey = config.writeKey || "";
|
|
2130
2124
|
const apiKey = config.apiKey || "";
|
|
2131
2125
|
if (writeKey) {
|
|
@@ -2160,6 +2154,11 @@ var G8 = class {
|
|
|
2160
2154
|
this._intent = createIntentClient(apiKey, apiUrl);
|
|
2161
2155
|
this._studio = createStudioClient(apiKey, apiUrl);
|
|
2162
2156
|
this._meetings = createMeetingsClient(apiKey, apiUrl);
|
|
2157
|
+
this._audiences = createAudiencesClient(apiKey, apiUrl);
|
|
2158
|
+
this._search = createSearchClient(apiKey, apiUrl);
|
|
2159
|
+
this._agency = createAgencyClient(apiKey, apiUrl);
|
|
2160
|
+
this._marketplace = createMarketplaceClient(apiKey, apiUrl);
|
|
2161
|
+
this._snippet = createSnippetClient(apiKey, apiUrl);
|
|
2163
2162
|
this._signals = createSignalsClient(apiKey, true, apiUrl);
|
|
2164
2163
|
}
|
|
2165
2164
|
}
|
|
@@ -2326,6 +2325,31 @@ var G8 = class {
|
|
|
2326
2325
|
this._assertKey("meetings");
|
|
2327
2326
|
return this._meetings;
|
|
2328
2327
|
}
|
|
2328
|
+
/** Audiences — sync audience lists to ad platforms (Meta, LinkedIn, Google, X) (requires API key). */
|
|
2329
|
+
get audiences() {
|
|
2330
|
+
this._assertKey("audiences");
|
|
2331
|
+
return this._audiences;
|
|
2332
|
+
}
|
|
2333
|
+
/** Search — prospect open-data contacts + companies by filter, optionally save to a list (requires API key). */
|
|
2334
|
+
get search() {
|
|
2335
|
+
this._assertKey("search");
|
|
2336
|
+
return this._search;
|
|
2337
|
+
}
|
|
2338
|
+
/** Agency — for agency keys: discover the agency credential + the client orgs it may target (requires API key). */
|
|
2339
|
+
get agency() {
|
|
2340
|
+
this._assertKey("agency");
|
|
2341
|
+
return this._agency;
|
|
2342
|
+
}
|
|
2343
|
+
/** Marketplace — for SDR/AE talent: profile, hire offers (accept/reject), active hirings (requires API key). */
|
|
2344
|
+
get marketplace() {
|
|
2345
|
+
this._assertKey("marketplace");
|
|
2346
|
+
return this._marketplace;
|
|
2347
|
+
}
|
|
2348
|
+
/** Snippet — fetch your org's tracking snippet (write key + React/script-tag embeds + config) for embedding (requires API key). */
|
|
2349
|
+
get snippet() {
|
|
2350
|
+
this._assertKey("snippet");
|
|
2351
|
+
return this._snippet;
|
|
2352
|
+
}
|
|
2329
2353
|
/** Whether the SDK has been initialized. */
|
|
2330
2354
|
get initialized() {
|
|
2331
2355
|
return this.config !== null;
|
|
@@ -2343,6 +2367,15 @@ var G8 = class {
|
|
|
2343
2367
|
var g8 = new G8();
|
|
2344
2368
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2345
2369
|
0 && (module.exports = {
|
|
2346
|
-
|
|
2370
|
+
G8Error,
|
|
2371
|
+
KNOWN_WEBHOOK_EVENTS,
|
|
2372
|
+
WebhookSignatureError,
|
|
2373
|
+
backoffDelayMs,
|
|
2374
|
+
constructEvent,
|
|
2375
|
+
g8,
|
|
2376
|
+
isRetryableStatus,
|
|
2377
|
+
paginate,
|
|
2378
|
+
parseRetryAfter,
|
|
2379
|
+
request
|
|
2347
2380
|
});
|
|
2348
2381
|
//# sourceMappingURL=index.js.map
|