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