@graph8/sdk 0.7.2 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -20,11 +20,18 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ DEFAULT_APP_API: () => DEFAULT_APP_API,
23
24
  G8Error: () => G8Error,
24
25
  KNOWN_WEBHOOK_EVENTS: () => KNOWN_WEBHOOK_EVENTS,
25
26
  WebhookSignatureError: () => WebhookSignatureError,
26
27
  backoffDelayMs: () => backoffDelayMs,
27
28
  constructEvent: () => constructEvent,
29
+ createAppRequester: () => createAppRequester,
30
+ createGraph8AppClient: () => createGraph8AppClient,
31
+ createGraph8ServiceClient: () => createGraph8ServiceClient,
32
+ createTokenManager: () => createTokenManager,
33
+ exchangeBrowserToken: () => exchangeBrowserToken,
34
+ exchangeServiceToken: () => exchangeServiceToken,
28
35
  g8: () => g8,
29
36
  isRetryableStatus: () => isRetryableStatus,
30
37
  paginate: () => paginate,
@@ -67,6 +74,21 @@ var createFormsClient = (writeKey, apiUrl) => {
67
74
 
68
75
  // src/utils.ts
69
76
  var isServer = typeof window === "undefined";
77
+ var resolveAppBaseUrl = (apiBaseUrl) => {
78
+ try {
79
+ const url = new URL(apiBaseUrl);
80
+ if (url.hostname === "localhost" || url.hostname === "127.0.0.1") {
81
+ url.port = "3000";
82
+ return url.origin;
83
+ }
84
+ if (url.hostname.endsWith("graph8.com")) {
85
+ url.hostname = url.hostname.replace(/^be\./, "app.");
86
+ return url.origin;
87
+ }
88
+ } catch {
89
+ }
90
+ return apiBaseUrl;
91
+ };
70
92
 
71
93
  // src/visitors.ts
72
94
  var DEFAULT_API2 = "https://be.graph8.com";
@@ -179,6 +201,7 @@ var createCopilotClient = (writeKey, apiUrl) => {
179
201
  var DEFAULT_API4 = "https://be.graph8.com";
180
202
  var createChatClient = (writeKey, apiUrl) => {
181
203
  const baseUrl = apiUrl || DEFAULT_API4;
204
+ const appUrl = resolveAppBaseUrl(baseUrl);
182
205
  const listeners = /* @__PURE__ */ new Map();
183
206
  let widgetEl = null;
184
207
  let ws = null;
@@ -193,7 +216,7 @@ var createChatClient = (writeKey, apiUrl) => {
193
216
  const position = config?.position || "bottom-right";
194
217
  const posStyle = position === "bottom-left" ? "left:16px;" : "right:16px;";
195
218
  const iframe = document.createElement("iframe");
196
- iframe.src = `${baseUrl}/webchat/embed?write_key=${writeKey}&theme=${config?.theme || "auto"}`;
219
+ iframe.src = `${appUrl}/webchat/embed?write_key=${writeKey}&theme=${config?.theme || "auto"}`;
197
220
  iframe.style.cssText = `position:fixed;bottom:16px;${posStyle}width:380px;height:560px;border:none;border-radius:12px;box-shadow:0 8px 32px rgba(0,0,0,0.15);z-index:99997;`;
198
221
  iframe.id = "g8-chat-widget";
199
222
  document.body.appendChild(iframe);
@@ -318,6 +341,19 @@ var G8Error = class _G8Error extends Error {
318
341
  function isRetryableStatus(status) {
319
342
  return status === 429 || status >= 500 && status <= 599;
320
343
  }
344
+ function isNonIdempotentMethod(method) {
345
+ const m = method.toUpperCase();
346
+ return m === "POST" || m === "PATCH";
347
+ }
348
+ function newIdempotencyKey() {
349
+ const c = globalThis.crypto;
350
+ if (c?.randomUUID) return c.randomUUID();
351
+ if (c?.getRandomValues) {
352
+ const bytes = c.getRandomValues(new Uint8Array(16));
353
+ return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
354
+ }
355
+ return `g8-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 12)}`;
356
+ }
321
357
  function parseRetryAfter(header, nowMs = Date.now()) {
322
358
  if (!header) return null;
323
359
  const secs = Number(header);
@@ -384,7 +420,8 @@ async function request(baseUrl, path, apiKey, opts = {}) {
384
420
  Authorization: `Bearer ${apiKey}`,
385
421
  ...headers
386
422
  };
387
- if (idempotencyKey) finalHeaders["Idempotency-Key"] = idempotencyKey;
423
+ const effectiveIdempotencyKey = idempotencyKey ?? (maxRetries > 0 && isNonIdempotentMethod(method) ? newIdempotencyKey() : void 0);
424
+ if (effectiveIdempotencyKey) finalHeaders["Idempotency-Key"] = effectiveIdempotencyKey;
388
425
  let attempt = 0;
389
426
  for (; ; ) {
390
427
  let resp;
@@ -462,7 +499,7 @@ var createEnrichClient = (apiKey, apiUrl) => {
462
499
  });
463
500
  return resp.data ?? resp;
464
501
  },
465
- /** Search 300M+ contacts with filters. Credits charged per result. */
502
+ /** Search 700M+ contacts with filters. Credits charged per result. */
466
503
  async search(filters, page = 1, limit = 25) {
467
504
  const resp = await request(baseUrl, "/api/v1/search/contacts", apiKey, {
468
505
  method: "POST",
@@ -635,45 +672,23 @@ var createCampaignsClient = (apiKey, apiUrl) => {
635
672
  return resp.data ?? resp;
636
673
  },
637
674
  async launch(campaignId) {
638
- await request(baseUrl, `/api/v1/campaigns/${campaignId}/launch`, apiKey, { method: "POST" });
639
- },
640
- async stats(campaignId) {
641
- const resp = await request(baseUrl, `/api/v1/campaigns/${campaignId}/stats`, apiKey);
675
+ const resp = await request(
676
+ baseUrl,
677
+ `/api/v1/campaigns/${campaignId}/launch`,
678
+ apiKey,
679
+ { method: "POST" }
680
+ );
642
681
  return resp.data ?? resp;
643
682
  }
644
683
  };
645
684
  };
646
685
 
647
- // src/integrations.ts
648
- var DEFAULT_API9 = "https://be.graph8.com";
649
- var createIntegrationsClient = (apiKey, apiUrl) => {
650
- const baseUrl = apiUrl || DEFAULT_API9;
651
- return {
652
- async list() {
653
- const resp = await request(baseUrl, "/api/v1/integrations", apiKey);
654
- return resp.data ?? resp;
655
- },
656
- async connect(provider, config) {
657
- await request(baseUrl, "/api/v1/integrations/connect", apiKey, {
658
- method: "POST",
659
- body: { provider, ...config }
660
- });
661
- },
662
- async sync(provider, config) {
663
- await request(baseUrl, "/api/v1/integrations/sync", apiKey, {
664
- method: "POST",
665
- body: { provider, ...config }
666
- });
667
- }
668
- };
669
- };
670
-
671
686
  // src/signals.ts
672
- var DEFAULT_API10 = "https://be.graph8.com";
687
+ var DEFAULT_API9 = "https://be.graph8.com";
673
688
  var createSignalsClient = (key, isApiKey, apiUrl) => {
674
- const baseUrl = apiUrl || DEFAULT_API10;
689
+ const baseUrl = apiUrl || DEFAULT_API9;
675
690
  const headers = () => isApiKey ? { "Content-Type": "application/json", "Authorization": `Bearer ${key}` } : { "Content-Type": "application/json", "X-Write-Key": key };
676
- const endpoint = isApiKey ? "/api/v1/signals/company" : "/api/v1/public/signals/company";
691
+ const endpoint = "/api/v1/public/signals/company";
677
692
  return {
678
693
  /** Get intent signals for a specific company domain. */
679
694
  async company(domain) {
@@ -698,24 +713,10 @@ var createSignalsClient = (key, isApiKey, apiUrl) => {
698
713
  };
699
714
  };
700
715
 
701
- // src/analytics.ts
702
- var DEFAULT_API11 = "https://be.graph8.com";
703
- var createAnalyticsClient = (apiKey, apiUrl) => {
704
- const baseUrl = apiUrl || DEFAULT_API11;
705
- return {
706
- async overview(config) {
707
- const resp = await request(baseUrl, "/api/v1/analytics/overview", apiKey, {
708
- query: { period: config?.period }
709
- });
710
- return resp.data ?? resp;
711
- }
712
- };
713
- };
714
-
715
716
  // src/voice.ts
716
- var DEFAULT_API12 = "https://be.graph8.com";
717
+ var DEFAULT_API10 = "https://be.graph8.com";
717
718
  var createVoiceClient = (apiKey, apiUrl) => {
718
- const baseUrl = apiUrl || DEFAULT_API12;
719
+ const baseUrl = apiUrl || DEFAULT_API10;
719
720
  const listeners = /* @__PURE__ */ new Map();
720
721
  const dialer = {
721
722
  /** List parallel-dialer sessions with filters + pagination. */
@@ -848,31 +849,6 @@ var createVoiceClient = (apiKey, apiUrl) => {
848
849
  }
849
850
  };
850
851
  return {
851
- /**
852
- * Start an AI voice session.
853
- * @deprecated Preview surface — for parallel-dialer flows use `voice.dialer.createSession()`.
854
- */
855
- async start(config) {
856
- const resp = await request(
857
- baseUrl,
858
- "/api/v1/voice/sessions",
859
- apiKey,
860
- { method: "POST", body: config }
861
- );
862
- return resp.data ?? resp;
863
- },
864
- /**
865
- * Get call analysis for a completed session.
866
- * @deprecated Preview surface — for dialer-call grading use `voice.dialer.callGrading(roomName)`.
867
- */
868
- async analysis(sessionId) {
869
- const resp = await request(
870
- baseUrl,
871
- `/api/v1/voice/sessions/${sessionId}/analysis`,
872
- apiKey
873
- );
874
- return resp.data ?? resp;
875
- },
876
852
  /** Listen for voice events. */
877
853
  on(event, callback) {
878
854
  if (!listeners.has(event)) listeners.set(event, []);
@@ -883,43 +859,9 @@ var createVoiceClient = (apiKey, apiUrl) => {
883
859
  };
884
860
  };
885
861
 
886
- // src/pages.ts
887
- var DEFAULT_API13 = "https://be.graph8.com";
888
- var createPagesClient = (apiKey, apiUrl) => {
889
- const baseUrl = apiUrl || DEFAULT_API13;
890
- return {
891
- /** Clone a landing page from any URL. */
892
- async clone(url) {
893
- const resp = await request(baseUrl, "/api/v1/landing-pages/clone-url", apiKey, {
894
- method: "POST",
895
- body: { url }
896
- });
897
- return resp.data ?? resp;
898
- },
899
- /** Create a landing page from a template. */
900
- async create(config) {
901
- const resp = await request(baseUrl, "/api/v1/landing-pages", apiKey, {
902
- method: "POST",
903
- body: config
904
- });
905
- return resp.data ?? resp;
906
- },
907
- /** Publish a landing page to CDN. */
908
- async publish(pageId) {
909
- const data = await request(
910
- baseUrl,
911
- `/api/v1/landing-pages/${pageId}/publish`,
912
- apiKey,
913
- { method: "POST" }
914
- );
915
- return { url: data.published_url || data.data?.published_url || "" };
916
- }
917
- };
918
- };
919
-
920
862
  // src/webhooks.ts
921
863
  var import_node_crypto = require("crypto");
922
- var DEFAULT_API14 = "https://be.graph8.com";
864
+ var DEFAULT_API11 = "https://be.graph8.com";
923
865
  var KNOWN_WEBHOOK_EVENTS = [
924
866
  "campaign.created",
925
867
  "campaign.updated",
@@ -937,7 +879,7 @@ var KNOWN_WEBHOOK_EVENTS = [
937
879
  "company_intelligence.completed",
938
880
  "audience.ready",
939
881
  "audience.failed",
940
- "sequence.deployed",
882
+ "sequence.draft_created",
941
883
  "sequence.started",
942
884
  "sequence.paused",
943
885
  "sequence.completed",
@@ -1000,7 +942,7 @@ function constructEvent(payload, signature, timestamp, secret, opts = {}) {
1000
942
  }
1001
943
  }
1002
944
  var createWebhooksClient = (_apiKey, apiUrl) => {
1003
- const baseUrl = apiUrl || DEFAULT_API14;
945
+ const baseUrl = apiUrl || DEFAULT_API11;
1004
946
  return {
1005
947
  /** Base URL the webhook subscription API lives under. */
1006
948
  baseUrl,
@@ -1014,9 +956,9 @@ var createWebhooksClient = (_apiKey, apiUrl) => {
1014
956
  };
1015
957
 
1016
958
  // src/contacts.ts
1017
- var DEFAULT_API15 = "https://be.graph8.com";
959
+ var DEFAULT_API12 = "https://be.graph8.com";
1018
960
  var createContactsClient = (apiKey, apiUrl) => {
1019
- const baseUrl = apiUrl || DEFAULT_API15;
961
+ const baseUrl = apiUrl || DEFAULT_API12;
1020
962
  return {
1021
963
  /** List contacts with optional filters. */
1022
964
  async list(params = {}) {
@@ -1075,9 +1017,9 @@ var createContactsClient = (apiKey, apiUrl) => {
1075
1017
  };
1076
1018
 
1077
1019
  // src/companies.ts
1078
- var DEFAULT_API16 = "https://be.graph8.com";
1020
+ var DEFAULT_API13 = "https://be.graph8.com";
1079
1021
  var createCompaniesClient = (apiKey, apiUrl) => {
1080
- const baseUrl = apiUrl || DEFAULT_API16;
1022
+ const baseUrl = apiUrl || DEFAULT_API13;
1081
1023
  return {
1082
1024
  /** List companies with optional filters. */
1083
1025
  async list(params = {}) {
@@ -1123,9 +1065,9 @@ var createCompaniesClient = (apiKey, apiUrl) => {
1123
1065
  };
1124
1066
 
1125
1067
  // src/lists.ts
1126
- var DEFAULT_API17 = "https://be.graph8.com";
1068
+ var DEFAULT_API14 = "https://be.graph8.com";
1127
1069
  var createListsClient = (apiKey, apiUrl) => {
1128
- const baseUrl = apiUrl || DEFAULT_API17;
1070
+ const baseUrl = apiUrl || DEFAULT_API14;
1129
1071
  return {
1130
1072
  /** List all lists. */
1131
1073
  async list(page = 1, limit = 50) {
@@ -1165,9 +1107,9 @@ var createListsClient = (apiKey, apiUrl) => {
1165
1107
  };
1166
1108
 
1167
1109
  // src/notes.ts
1168
- var DEFAULT_API18 = "https://be.graph8.com";
1110
+ var DEFAULT_API15 = "https://be.graph8.com";
1169
1111
  var createNotesClient = (apiKey, apiUrl) => {
1170
- const baseUrl = apiUrl || DEFAULT_API18;
1112
+ const baseUrl = apiUrl || DEFAULT_API15;
1171
1113
  return {
1172
1114
  /** List all notes on a contact. */
1173
1115
  async list(contactId) {
@@ -1197,9 +1139,9 @@ var createNotesClient = (apiKey, apiUrl) => {
1197
1139
  };
1198
1140
 
1199
1141
  // src/tasks.ts
1200
- var DEFAULT_API19 = "https://be.graph8.com";
1142
+ var DEFAULT_API16 = "https://be.graph8.com";
1201
1143
  var createTasksClient = (apiKey, apiUrl) => {
1202
- const baseUrl = apiUrl || DEFAULT_API19;
1144
+ const baseUrl = apiUrl || DEFAULT_API16;
1203
1145
  return {
1204
1146
  /** List tasks on a single contact. Optional status filter ("open" | "completed"). */
1205
1147
  async listForContact(contactId, status) {
@@ -1235,9 +1177,9 @@ var createTasksClient = (apiKey, apiUrl) => {
1235
1177
  };
1236
1178
 
1237
1179
  // src/fields.ts
1238
- var DEFAULT_API20 = "https://be.graph8.com";
1180
+ var DEFAULT_API17 = "https://be.graph8.com";
1239
1181
  var createFieldsClient = (apiKey, apiUrl) => {
1240
- const baseUrl = apiUrl || DEFAULT_API20;
1182
+ const baseUrl = apiUrl || DEFAULT_API17;
1241
1183
  return {
1242
1184
  /** List contact fields (base + custom). Pass listId to include list-specific custom fields. */
1243
1185
  async listContactFields(listId) {
@@ -1279,9 +1221,9 @@ var createFieldsClient = (apiKey, apiUrl) => {
1279
1221
  };
1280
1222
 
1281
1223
  // src/deals.ts
1282
- var DEFAULT_API21 = "https://be.graph8.com";
1224
+ var DEFAULT_API18 = "https://be.graph8.com";
1283
1225
  var createDealsClient = (apiKey, apiUrl) => {
1284
- const baseUrl = apiUrl || DEFAULT_API21;
1226
+ const baseUrl = apiUrl || DEFAULT_API18;
1285
1227
  return {
1286
1228
  /** List all deal pipelines and their stages. */
1287
1229
  async pipelines() {
@@ -1325,9 +1267,9 @@ var createDealsClient = (apiKey, apiUrl) => {
1325
1267
  };
1326
1268
 
1327
1269
  // src/inbox.ts
1328
- var DEFAULT_API22 = "https://be.graph8.com";
1270
+ var DEFAULT_API19 = "https://be.graph8.com";
1329
1271
  var createInboxClient = (apiKey, apiUrl) => {
1330
- const baseUrl = apiUrl || DEFAULT_API22;
1272
+ const baseUrl = apiUrl || DEFAULT_API19;
1331
1273
  return {
1332
1274
  /** List inbox threads across email, SMS, and LinkedIn. */
1333
1275
  async list(params = {}) {
@@ -1380,9 +1322,9 @@ var createInboxClient = (apiKey, apiUrl) => {
1380
1322
  };
1381
1323
 
1382
1324
  // src/quotes.ts
1383
- var DEFAULT_API23 = "https://be.graph8.com";
1325
+ var DEFAULT_API20 = "https://be.graph8.com";
1384
1326
  var createQuotesClient = (apiKey, apiUrl) => {
1385
- const baseUrl = apiUrl || DEFAULT_API23;
1327
+ const baseUrl = apiUrl || DEFAULT_API20;
1386
1328
  return {
1387
1329
  /** List quotes org-wide with optional filters and pagination. */
1388
1330
  async list(params = {}) {
@@ -1454,9 +1396,9 @@ var createQuotesClient = (apiKey, apiUrl) => {
1454
1396
  };
1455
1397
 
1456
1398
  // src/pipelines.ts
1457
- var DEFAULT_API24 = "https://be.graph8.com";
1399
+ var DEFAULT_API21 = "https://be.graph8.com";
1458
1400
  var createPipelinesClient = (apiKey, apiUrl) => {
1459
- const baseUrl = apiUrl || DEFAULT_API24;
1401
+ const baseUrl = apiUrl || DEFAULT_API21;
1460
1402
  return {
1461
1403
  /** List all stage-checklist pipelines with stages, evidence, scripts. */
1462
1404
  async list() {
@@ -1538,9 +1480,9 @@ var createPipelinesClient = (apiKey, apiUrl) => {
1538
1480
  };
1539
1481
 
1540
1482
  // src/workflows.ts
1541
- var DEFAULT_API25 = "https://be.graph8.com";
1483
+ var DEFAULT_API22 = "https://be.graph8.com";
1542
1484
  var createWorkflowsClient = (apiKey, apiUrl) => {
1543
- const baseUrl = apiUrl || DEFAULT_API25;
1485
+ const baseUrl = apiUrl || DEFAULT_API22;
1544
1486
  return {
1545
1487
  /** List workflows org-wide. */
1546
1488
  async list(params = {}) {
@@ -1656,9 +1598,9 @@ var createWorkflowsClient = (apiKey, apiUrl) => {
1656
1598
  };
1657
1599
 
1658
1600
  // src/skills.ts
1659
- var DEFAULT_API26 = "https://be.graph8.com";
1601
+ var DEFAULT_API23 = "https://be.graph8.com";
1660
1602
  var createSkillsClient = (apiKey, apiUrl) => {
1661
- const baseUrl = apiUrl || DEFAULT_API26;
1603
+ const baseUrl = apiUrl || DEFAULT_API23;
1662
1604
  return {
1663
1605
  /** List skills. */
1664
1606
  async list(params = {}) {
@@ -1745,9 +1687,9 @@ var createSkillsClient = (apiKey, apiUrl) => {
1745
1687
  };
1746
1688
 
1747
1689
  // src/intent.ts
1748
- var DEFAULT_API27 = "https://be.graph8.com";
1690
+ var DEFAULT_API24 = "https://be.graph8.com";
1749
1691
  var createIntentClient = (apiKey, apiUrl) => {
1750
- const baseUrl = apiUrl || DEFAULT_API27;
1692
+ const baseUrl = apiUrl || DEFAULT_API24;
1751
1693
  const get = (path) => request(baseUrl, `/api/v1${path}`, apiKey);
1752
1694
  const post = (path, body = {}) => request(baseUrl, `/api/v1${path}`, apiKey, { method: "POST", body });
1753
1695
  const del = (path) => request(baseUrl, `/api/v1${path}`, apiKey, { method: "DELETE" });
@@ -1816,10 +1758,12 @@ var createIntentClient = (apiKey, apiUrl) => {
1816
1758
  };
1817
1759
 
1818
1760
  // src/studio.ts
1819
- var DEFAULT_API28 = "https://be.graph8.com";
1761
+ var DEFAULT_API25 = "https://be.graph8.com";
1820
1762
  var createStudioClient = (apiKey, apiUrl) => {
1821
- const baseUrl = apiUrl || DEFAULT_API28;
1763
+ const baseUrl = apiUrl || DEFAULT_API25;
1822
1764
  const get = (path, params = {}) => request(baseUrl, `/api/v1${path}`, apiKey, { query: params });
1765
+ const post = (path, body = {}) => request(baseUrl, `/api/v1${path}`, apiKey, { method: "POST", body });
1766
+ const patch = (path, body = {}) => request(baseUrl, `/api/v1${path}`, apiKey, { method: "PATCH", body });
1823
1767
  return {
1824
1768
  /** Org-level Studio documents (brand_brief, value_props, messaging_house, etc.).
1825
1769
  * `include_content` defaults to true server-side, so each document includes
@@ -1842,14 +1786,38 @@ var createStudioClient = (apiKey, apiUrl) => {
1842
1786
  /** AI research reports (buyer psychology, competitive teardown, GTM channel, etc.). */
1843
1787
  async researchReports(params = {}) {
1844
1788
  return get("/research-reports", params);
1789
+ },
1790
+ /** Create an ICP manually (no AI scoring). Requires name + website_url. */
1791
+ async createIcp(body) {
1792
+ return post("/icps", body);
1793
+ },
1794
+ /** Update an ICP (partial - send only fields to change). */
1795
+ async updateIcp(icpId, body) {
1796
+ return patch(`/icps/${icpId}`, body);
1797
+ },
1798
+ /** Archive an ICP (soft delete - sets status to "archived"). */
1799
+ async archiveIcp(icpId) {
1800
+ return post(`/icps/${icpId}/archive`);
1801
+ },
1802
+ /** Create a buyer persona manually (no AI generation). Requires title + website_url. */
1803
+ async createPersona(body) {
1804
+ return post("/personas", body);
1805
+ },
1806
+ /** Update a persona (partial). Passing status "archived" is equivalent to archivePersona. */
1807
+ async updatePersona(personaId, body) {
1808
+ return patch(`/personas/${personaId}`, body);
1809
+ },
1810
+ /** Archive a persona (soft delete - sets status to "archived"). */
1811
+ async archivePersona(personaId) {
1812
+ return post(`/personas/${personaId}/archive`);
1845
1813
  }
1846
1814
  };
1847
1815
  };
1848
1816
 
1849
1817
  // src/meetings.ts
1850
- var DEFAULT_API29 = "https://be.graph8.com";
1818
+ var DEFAULT_API26 = "https://be.graph8.com";
1851
1819
  var createMeetingsClient = (apiKey, apiUrl) => {
1852
- const baseUrl = apiUrl || DEFAULT_API29;
1820
+ const baseUrl = apiUrl || DEFAULT_API26;
1853
1821
  return {
1854
1822
  /** List meetings with optional filters. Returns summary rows without transcript / analysis. */
1855
1823
  async list(params = {}) {
@@ -1864,9 +1832,9 @@ var createMeetingsClient = (apiKey, apiUrl) => {
1864
1832
  };
1865
1833
 
1866
1834
  // src/audiences.ts
1867
- var DEFAULT_API30 = "https://be.graph8.com";
1835
+ var DEFAULT_API27 = "https://be.graph8.com";
1868
1836
  var createAudiencesClient = (apiKey, apiUrl) => {
1869
- const baseUrl = apiUrl || DEFAULT_API30;
1837
+ const baseUrl = apiUrl || DEFAULT_API27;
1870
1838
  const base = "/api/v1/audience-syncs";
1871
1839
  return {
1872
1840
  /** List all audience syncs for the organization. */
@@ -1914,9 +1882,9 @@ var createAudiencesClient = (apiKey, apiUrl) => {
1914
1882
  };
1915
1883
 
1916
1884
  // src/search.ts
1917
- var DEFAULT_API31 = "https://be.graph8.com";
1885
+ var DEFAULT_API28 = "https://be.graph8.com";
1918
1886
  var createSearchClient = (apiKey, apiUrl) => {
1919
- const baseUrl = apiUrl || DEFAULT_API31;
1887
+ const baseUrl = apiUrl || DEFAULT_API28;
1920
1888
  const body = (p) => ({ filters: [], page: 1, limit: 25, ...p });
1921
1889
  return {
1922
1890
  /** Search open-data contacts by filter. */
@@ -1947,9 +1915,9 @@ var createSearchClient = (apiKey, apiUrl) => {
1947
1915
  };
1948
1916
 
1949
1917
  // src/agency.ts
1950
- var DEFAULT_API32 = "https://be.graph8.com";
1918
+ var DEFAULT_API29 = "https://be.graph8.com";
1951
1919
  var createAgencyClient = (apiKey, apiUrl) => {
1952
- const baseUrl = apiUrl || DEFAULT_API32;
1920
+ const baseUrl = apiUrl || DEFAULT_API29;
1953
1921
  return {
1954
1922
  /** Describe the agency credential: agency org + authorized client count. */
1955
1923
  async me() {
@@ -1964,9 +1932,9 @@ var createAgencyClient = (apiKey, apiUrl) => {
1964
1932
  };
1965
1933
 
1966
1934
  // src/marketplace.ts
1967
- var DEFAULT_API33 = "https://be.graph8.com";
1935
+ var DEFAULT_API30 = "https://be.graph8.com";
1968
1936
  var createMarketplaceClient = (apiKey, apiUrl) => {
1969
- const baseUrl = apiUrl || DEFAULT_API33;
1937
+ const baseUrl = apiUrl || DEFAULT_API30;
1970
1938
  const base = "/api/v1/marketplace";
1971
1939
  return {
1972
1940
  /** Your own marketplace SDR profile. */
@@ -2016,9 +1984,9 @@ var createMarketplaceClient = (apiKey, apiUrl) => {
2016
1984
  };
2017
1985
 
2018
1986
  // src/snippet.ts
2019
- var DEFAULT_API34 = "https://be.graph8.com";
1987
+ var DEFAULT_API31 = "https://be.graph8.com";
2020
1988
  var createSnippetClient = (apiKey, apiUrl) => {
2021
- const baseUrl = apiUrl || DEFAULT_API34;
1989
+ const baseUrl = apiUrl || DEFAULT_API31;
2022
1990
  return {
2023
1991
  /** Get your org's tracking snippet (write key + React/script-tag embeds + config). */
2024
1992
  async get() {
@@ -2030,7 +1998,7 @@ var createSnippetClient = (apiKey, apiUrl) => {
2030
1998
 
2031
1999
  // src/core.ts
2032
2000
  var DEFAULT_HOST = "https://t.graph8.com";
2033
- var DEFAULT_API35 = "https://be.graph8.com";
2001
+ var DEFAULT_API32 = "https://be.graph8.com";
2034
2002
  var G8 = class {
2035
2003
  constructor() {
2036
2004
  /** @internal */
@@ -2054,16 +2022,10 @@ var G8 = class {
2054
2022
  /** @internal */
2055
2023
  this._campaigns = null;
2056
2024
  /** @internal */
2057
- this._integrations = null;
2058
- /** @internal */
2059
2025
  this._signals = null;
2060
2026
  /** @internal */
2061
- this._analytics = null;
2062
- /** @internal */
2063
2027
  this._voice = null;
2064
2028
  /** @internal */
2065
- this._pages = null;
2066
- /** @internal */
2067
2029
  this._webhooks = null;
2068
2030
  /** @internal */
2069
2031
  this._contacts = null;
@@ -2119,7 +2081,7 @@ var G8 = class {
2119
2081
  debug: config.debug
2120
2082
  });
2121
2083
  }
2122
- const apiUrl = config.apiUrl || DEFAULT_API35;
2084
+ const apiUrl = config.apiUrl || DEFAULT_API32;
2123
2085
  const writeKey = config.writeKey || "";
2124
2086
  const apiKey = config.apiKey || "";
2125
2087
  if (writeKey) {
@@ -2134,10 +2096,7 @@ var G8 = class {
2134
2096
  this._enrich = createEnrichClient(apiKey, apiUrl);
2135
2097
  this._sequences = createSequencesClient(apiKey, apiUrl);
2136
2098
  this._campaigns = createCampaignsClient(apiKey, apiUrl);
2137
- this._integrations = createIntegrationsClient(apiKey, apiUrl);
2138
- this._analytics = createAnalyticsClient(apiKey, apiUrl);
2139
2099
  this._voice = createVoiceClient(apiKey, apiUrl);
2140
- this._pages = createPagesClient(apiKey, apiUrl);
2141
2100
  this._webhooks = createWebhooksClient(apiKey, apiUrl);
2142
2101
  this._contacts = createContactsClient(apiKey, apiUrl);
2143
2102
  this._companies = createCompaniesClient(apiKey, apiUrl);
@@ -2220,31 +2179,16 @@ var G8 = class {
2220
2179
  this._assertKey("campaigns");
2221
2180
  return this._campaigns;
2222
2181
  }
2223
- /** CRM integrations (requires API key). */
2224
- get integrations() {
2225
- this._assertKey("integrations");
2226
- return this._integrations;
2227
- }
2228
2182
  /** Intent signals. */
2229
2183
  get signals() {
2230
2184
  this._assertInit();
2231
2185
  return this._signals;
2232
2186
  }
2233
- /** Analytics (requires API key). */
2234
- get analytics() {
2235
- this._assertKey("analytics");
2236
- return this._analytics;
2237
- }
2238
2187
  /** Voice AI (requires API key). */
2239
2188
  get voice() {
2240
2189
  this._assertKey("voice");
2241
2190
  return this._voice;
2242
2191
  }
2243
- /** Landing pages (requires API key). */
2244
- get pages() {
2245
- this._assertKey("pages");
2246
- return this._pages;
2247
- }
2248
2192
  /** Webhook event listeners (requires API key). */
2249
2193
  get webhooks() {
2250
2194
  this._assertKey("webhooks");
@@ -2365,13 +2309,182 @@ var G8 = class {
2365
2309
  }
2366
2310
  };
2367
2311
  var g8 = new G8();
2312
+
2313
+ // src/appTokens.ts
2314
+ var DEFAULT_APP_API = "https://be.graph8.com";
2315
+ function createTokenManager(args) {
2316
+ const now = args.now ?? (() => Date.now());
2317
+ const skewMs = args.refreshSkewMs ?? 6e4;
2318
+ let token = null;
2319
+ let expiresAtMs = 0;
2320
+ let inflight = null;
2321
+ const doRefresh = async () => {
2322
+ const resp = await args.refresh();
2323
+ token = resp.access_token;
2324
+ expiresAtMs = now() + Math.max(0, resp.expires_in) * 1e3;
2325
+ return token;
2326
+ };
2327
+ return {
2328
+ async getToken(force = false) {
2329
+ const stillFresh = !force && token !== null && now() < expiresAtMs - skewMs;
2330
+ if (stillFresh) return token;
2331
+ if (!inflight) {
2332
+ inflight = doRefresh().finally(() => {
2333
+ inflight = null;
2334
+ });
2335
+ }
2336
+ return inflight;
2337
+ },
2338
+ expiresAt() {
2339
+ return expiresAtMs;
2340
+ }
2341
+ };
2342
+ }
2343
+ function createAppRequester(args) {
2344
+ const { baseUrl, tokens, extraHeaders, fetchImpl, sleepImpl } = args;
2345
+ const appRequest = async (path, opts = {}) => {
2346
+ const headers = { ...extraHeaders ?? {}, ...opts.headers ?? {} };
2347
+ const reqOpts = { ...opts, headers, fetchImpl, sleepImpl };
2348
+ const token = await tokens.getToken();
2349
+ try {
2350
+ return await request(baseUrl, path, token, reqOpts);
2351
+ } catch (err) {
2352
+ if (err instanceof G8Error && err.status === 401) {
2353
+ const fresh = await tokens.getToken(true);
2354
+ return await request(baseUrl, path, fresh, reqOpts);
2355
+ }
2356
+ throw err;
2357
+ }
2358
+ };
2359
+ return appRequest;
2360
+ }
2361
+ async function exchangeBrowserToken(args) {
2362
+ const propelToken = await Promise.resolve(args.getPropelAuthToken());
2363
+ if (!propelToken) {
2364
+ throw new G8Error({
2365
+ message: "getPropelAuthToken() returned no token \u2014 cannot exchange a browser app session",
2366
+ status: 401,
2367
+ type: "app_token_invalid",
2368
+ code: "app_token_invalid"
2369
+ });
2370
+ }
2371
+ const resp = await request(
2372
+ args.baseUrl,
2373
+ "/api/v1/app-sessions/exchange",
2374
+ propelToken,
2375
+ {
2376
+ method: "POST",
2377
+ body: { app_id: args.appId, scopes: args.scopes ?? [] },
2378
+ fetchImpl: args.fetchImpl,
2379
+ sleepImpl: args.sleepImpl
2380
+ }
2381
+ );
2382
+ return resp.data ?? resp;
2383
+ }
2384
+ async function exchangeServiceToken(args) {
2385
+ const resp = await request(
2386
+ args.baseUrl,
2387
+ "/api/v1/service-token",
2388
+ "",
2389
+ {
2390
+ method: "POST",
2391
+ body: {
2392
+ client_id: args.clientId,
2393
+ client_secret: args.clientSecret,
2394
+ scopes: args.scopes ?? [],
2395
+ ttl_seconds: args.ttlSeconds ?? null
2396
+ },
2397
+ fetchImpl: args.fetchImpl,
2398
+ sleepImpl: args.sleepImpl
2399
+ }
2400
+ );
2401
+ return resp.data ?? resp;
2402
+ }
2403
+
2404
+ // src/appClient.ts
2405
+ function createGraph8AppClient(config) {
2406
+ if (typeof config?.getPropelAuthToken !== "function") {
2407
+ throw new Error(
2408
+ "createGraph8AppClient requires getPropelAuthToken() \u2014 a function returning the caller's PropelAuth token"
2409
+ );
2410
+ }
2411
+ const asRecord = config;
2412
+ if ("apiKey" in asRecord || "writeKey" in asRecord) {
2413
+ throw new Error(
2414
+ "createGraph8AppClient does not accept an org API key or write key in the browser \u2014 pass getPropelAuthToken() instead"
2415
+ );
2416
+ }
2417
+ const baseUrl = config.apiUrl || DEFAULT_APP_API;
2418
+ const tokens = createTokenManager({
2419
+ now: config.now,
2420
+ refreshSkewMs: config.refreshSkewMs,
2421
+ refresh: () => exchangeBrowserToken({
2422
+ baseUrl,
2423
+ appId: config.appId,
2424
+ scopes: config.scopes,
2425
+ getPropelAuthToken: config.getPropelAuthToken,
2426
+ fetchImpl: config.fetchImpl,
2427
+ sleepImpl: config.sleepImpl
2428
+ })
2429
+ });
2430
+ const req = createAppRequester({ baseUrl, tokens, fetchImpl: config.fetchImpl, sleepImpl: config.sleepImpl });
2431
+ return {
2432
+ appId: config.appId,
2433
+ tenantOrgId: config.tenantOrgId,
2434
+ request: req,
2435
+ getAppToken: (force = false) => tokens.getToken(force)
2436
+ };
2437
+ }
2438
+ function createGraph8ServiceClient(config) {
2439
+ if (!config?.clientId || !config?.clientSecret) {
2440
+ throw new Error("createGraph8ServiceClient requires clientId and clientSecret");
2441
+ }
2442
+ if (!config?.tenantOrgId) {
2443
+ throw new Error(
2444
+ "createGraph8ServiceClient requires tenantOrgId \u2014 the single consented client org this backend acts for"
2445
+ );
2446
+ }
2447
+ const baseUrl = config.apiUrl || DEFAULT_APP_API;
2448
+ const tokens = createTokenManager({
2449
+ now: config.now,
2450
+ refreshSkewMs: config.refreshSkewMs,
2451
+ refresh: () => exchangeServiceToken({
2452
+ baseUrl,
2453
+ clientId: config.clientId,
2454
+ clientSecret: config.clientSecret,
2455
+ scopes: config.scopes,
2456
+ ttlSeconds: config.ttlSeconds,
2457
+ fetchImpl: config.fetchImpl,
2458
+ sleepImpl: config.sleepImpl
2459
+ })
2460
+ });
2461
+ const req = createAppRequester({
2462
+ baseUrl,
2463
+ tokens,
2464
+ extraHeaders: { "X-Target-Org-Id": config.tenantOrgId },
2465
+ fetchImpl: config.fetchImpl,
2466
+ sleepImpl: config.sleepImpl
2467
+ });
2468
+ return {
2469
+ tenantOrgId: config.tenantOrgId,
2470
+ request: req,
2471
+ getServiceToken: (force = false) => tokens.getToken(force)
2472
+ };
2473
+ }
2368
2474
  // Annotate the CommonJS export names for ESM import in node:
2369
2475
  0 && (module.exports = {
2476
+ DEFAULT_APP_API,
2370
2477
  G8Error,
2371
2478
  KNOWN_WEBHOOK_EVENTS,
2372
2479
  WebhookSignatureError,
2373
2480
  backoffDelayMs,
2374
2481
  constructEvent,
2482
+ createAppRequester,
2483
+ createGraph8AppClient,
2484
+ createGraph8ServiceClient,
2485
+ createTokenManager,
2486
+ exchangeBrowserToken,
2487
+ exchangeServiceToken,
2375
2488
  g8,
2376
2489
  isRetryableStatus,
2377
2490
  paginate,