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