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