@graph8/sdk 0.277.0 → 0.294.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.
Files changed (52) hide show
  1. package/README.md +2 -2
  2. package/dist/index.d.mts +604 -14
  3. package/dist/index.d.ts +604 -14
  4. package/dist/index.js +6 -4
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +6 -4
  7. package/dist/index.mjs.map +1 -1
  8. package/dist/react.d.mts +597 -14
  9. package/dist/react.d.ts +597 -14
  10. package/dist/react.js +5 -3
  11. package/dist/react.js.map +1 -1
  12. package/dist/react.mjs +5 -3
  13. package/dist/react.mjs.map +1 -1
  14. package/dist/types/enrich.d.ts +2 -2
  15. package/dist/types/react.d.ts +1 -3
  16. package/dist/types/version.d.ts +2 -2
  17. package/docs/agents.md +6 -6
  18. package/docs/api/README.md +3 -3
  19. package/docs/api/analytics.d.ts +26 -1
  20. package/docs/api/analytics.md +2 -0
  21. package/docs/api/assertUpsert.d.ts +2 -0
  22. package/docs/api/assertUpsert.md +1 -0
  23. package/docs/api/audienceSyncs.d.ts +8 -0
  24. package/docs/api/audienceSyncs.md +16 -0
  25. package/docs/api/by-path.md +2 -0
  26. package/docs/api/companies.d.ts +7 -1
  27. package/docs/api/companies.md +4 -1
  28. package/docs/api/contacts.d.ts +8 -2
  29. package/docs/api/contacts.md +5 -2
  30. package/docs/api/enrichment.d.ts +76 -2
  31. package/docs/api/enrichment.md +76 -1
  32. package/docs/api/fields.d.ts +24 -3
  33. package/docs/api/fields.md +15 -4
  34. package/docs/api/install.d.ts +26 -0
  35. package/docs/api/install.md +18 -0
  36. package/docs/api/intent.d.ts +26 -1
  37. package/docs/api/intent.md +23 -0
  38. package/docs/api/lists.d.ts +9 -0
  39. package/docs/api/lists.md +17 -2
  40. package/docs/api/marketingIntelligence.d.ts +40 -0
  41. package/docs/api/marketingIntelligence.md +20 -0
  42. package/docs/api/snippet.d.ts +66 -2
  43. package/docs/api/snippet.md +73 -4
  44. package/docs/api/suppressions.d.ts +4 -0
  45. package/docs/api/suppressions.md +2 -0
  46. package/docs/api/visitors.d.ts +26 -0
  47. package/docs/api/visitors.md +12 -0
  48. package/docs/api/webAnalytics.d.ts +288 -0
  49. package/docs/api/webAnalytics.md +144 -0
  50. package/docs/api/workflows.md +6 -0
  51. package/docs/sdk-clients.md +2 -2
  52. package/package.json +1 -1
@@ -2,7 +2,7 @@
2
2
 
3
3
  # `g8.api.enrichment`: Enrichment
4
4
 
5
- 114 operations (51 read, 21 write, 10 destructive, 32 billable).
5
+ 115 operations (52 read, 21 write, 10 destructive, 32 billable).
6
6
 
7
7
  3 of these also have a hand-written method (`g8.enrich`), marked **★** below. Prefer the hand-written method when one exists: it unwraps the `data` envelope and takes friendlier arguments. See [../sdk-clients.md](../sdk-clients.md).
8
8
 
@@ -101,6 +101,7 @@ Exact TypeScript types for every operation on this page, and every schema they u
101
101
  | [`lookupPerson`](#op-lookupperson) ★ | `POST /api/v1/enrichment/lookup/person` | billable | `enrichment:run` | Lookup Person |
102
102
  | [`lookupPersonAlias`](#op-lookuppersonalias) | `POST /api/v1/enrichment/person` | billable | `enrichment:run` | Lookup Person (alias of /enrichment/lookup/person) |
103
103
  | [`pauseEnrichmentJob`](#op-pauseenrichmentjob) | `POST /api/v1/enrichment/jobs/{job_id}/pause` | write | `enrichment:write` | Pause Enrichment Job |
104
+ | [`preflightEnrichment`](#op-preflightenrichment) | `POST /api/v1/enrichment/preflight` | read | `enrichment:read` | Preflight Enrichment |
104
105
  | [`previewFindPeople`](#op-previewfindpeople) | `POST /api/v1/enrichment/find-people/{config_id}/preview` | billable | `enrichment:run` | Preview Find People |
105
106
  | [`previewFormula`](#op-previewformula) | `POST /api/v1/enrichment/ai-formula/preview` | read | `enrichment:read` | Preview Formula |
106
107
  | [`previewRecordSync`](#op-previewrecordsync) | `POST /api/v1/enrichment/record-sync/{entity_type}/preview` | read | `enrichment:read` | Preview Record Sync |
@@ -3255,6 +3256,80 @@ const result = await g8.api.enrichment.pauseEnrichmentJob({ path: { job_id: "id"
3255
3256
 
3256
3257
  ---
3257
3258
 
3259
+ <a id="op-preflightenrichment"></a>
3260
+
3261
+ ### `g8.api.enrichment.preflightEnrichment(input)`
3262
+
3263
+ **Preflight Enrichment**
3264
+
3265
+ - HTTP: `POST /api/v1/enrichment/preflight`
3266
+ - operationId: `preflight_enrichment_enrichment_preflight_post` (also callable as `g8.api.call("preflight_enrichment_enrichment_preflight_post", input)`)
3267
+ - Tier: `read`: reads data; safe to call and to retry
3268
+ - API-key scope: `enrichment:read`
3269
+
3270
+ Check an enrichment request before running it. Free: nothing is written,
3271
+ queued or charged.
3272
+
3273
+ Errors for input a run could never use: an unknown `mode` (400
3274
+ `invalid_mode`), zero or negative contact IDs (400 `invalid_record_ids`), a
3275
+ list that is not in this organization (404 `list_not_found`), an unknown
3276
+ `target_field` (400 `unsupported_field`), an unknown provider (400
3277
+ `unsupported_provider` / `unsupported_provider_for_field`) and a missing AI
3278
+ config (404 `ai_config_not_found`).
3279
+
3280
+ Otherwise returns what the run would do: the unique contact IDs (repeats
3281
+ are counted once), contacts that are not on the list, the providers that
3282
+ would run, and plain warnings such as "Lusha is not connected: add your
3283
+ key" or "No providers chosen: using your saved pipeline".
3284
+
3285
+ **Input**
3286
+
3287
+ | Field | Type | Required | Description |
3288
+ |---|---|---|---|
3289
+ | `body` | `EnrichmentPreflightRequest` | yes | Request body; fields below. |
3290
+
3291
+ Body fields (`EnrichmentPreflightRequest`):
3292
+
3293
+ | Field | Type | Required | Description |
3294
+ |---|---|---|---|
3295
+ | `body.contact_ids` | `Array<integer>` | yes | Contact IDs to enrich (duplicates are counted once) |
3296
+ | `body.list_id` | `integer` | yes | List ID the contacts belong to |
3297
+ | `body.ai_group_id` | `string \| null` | no | group_id of a saved AI enrichment config (required for 'ai-research') |
3298
+ | `body.email_verification` | `boolean` | no | Add ZeroBounce email verification default `false` |
3299
+ | `body.mode` | `string` | no | 'auto' (AI when ai_group_id is set, else waterfall), 'waterfall' or 'ai-research' default `"auto"` |
3300
+ | `body.providers` | `Array<string> \| null` | no | Ordered provider names for a waterfall run. Omit to use the list's saved pipeline; an empty list also uses the saved pipeline (a warning says so). |
3301
+ | `body.target_field` | `string \| null` | no | Column to enrich: a canonical CONTACT_*/COMPANY_* column or a synonym like 'phone' or 'email' |
3302
+
3303
+ **Returns** `ApiResponse_EnrichmentPreflightResponse_`: the envelope `{ data: EnrichmentPreflightResponse, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
3304
+
3305
+ Other envelope fields: `pagination` (PaginationMeta).
3306
+
3307
+ `EnrichmentPreflightResponse` fields:
3308
+
3309
+ | Field | Type | Required | Description |
3310
+ |---|---|---|---|
3311
+ | `contact_count` | `integer` | yes | Number of unique contacts (the count credits are estimated on) |
3312
+ | `contact_ids` | `Array<integer>` | yes | Contact IDs that will be enriched: duplicates removed, order kept |
3313
+ | `list_id` | `integer` | yes | |
3314
+ | `mode` | `string` | yes | Resolved mode: 'waterfall' or 'ai-research' |
3315
+ | `duplicates_removed` | `integer` | no | How many repeated contact IDs were dropped default `0` |
3316
+ | `list_name` | `string \| null` | no | |
3317
+ | `missing_credentials` | `Array<string>` | no | Providers whose step would be skipped because the org has no key for them |
3318
+ | `not_in_list` | `Array<integer>` | no | Contact IDs that are not on the list; the run skips them and does not charge for them |
3319
+ | `providers` | `Array<string>` | no | Providers that would run, in order (empty = the saved pipeline) |
3320
+ | `providers_detail` | `Array<ProviderStepDetail>` | no | |
3321
+ | `target_field` | `string \| null` | no | Canonical column for target_field, when given |
3322
+ | `uses_saved_pipeline` | `boolean` | no | True when the list's saved pipeline (or the graph8 default) would run default `false` |
3323
+ | `warnings` | `Array<string>` | no | Plain-language advisories for the user |
3324
+
3325
+ **Example**
3326
+
3327
+ ```ts
3328
+ const result = await g8.api.enrichment.preflightEnrichment({ body: { contact_ids: [123], list_id: 123 } });
3329
+ ```
3330
+
3331
+ ---
3332
+
3258
3333
  <a id="op-previewfindpeople"></a>
3259
3334
 
3260
3335
  ### `g8.api.enrichment.previewFindPeople(input)`
@@ -212,7 +212,7 @@ export interface ApiResponse_list_FieldResponse__ {
212
212
  * level (a batch targets one entity and, when enrichment is used, one list).
213
213
  */
214
214
  export interface BatchFieldItem {
215
- /** Column data type. Currently only 'text' is supported. */
215
+ /** Column data type: 'text', 'int' (whole number), 'numeric' (decimal) or 'boolean' (yes/no). Unknown values 400. */
216
216
  data_type?: string;
217
217
  /** Optional per-column waterfall enrichment block (identical shape to POST /fields). When supplied, a companion enrichment_configs row is created for that column so it's immediately runnable. */
218
218
  enrichment?: CreateFieldEnrichmentInput | null;
@@ -222,9 +222,13 @@ export interface BatchFieldItem {
222
222
 
223
223
  /** Per-column outcome inside a batch response. */
224
224
  export interface BatchFieldResult {
225
+ /** True when this column already existed (same name, same scope), so the existing column was returned instead of a new one. */
226
+ already_existed?: boolean;
225
227
  enrichment?: CreateFieldEnrichmentResponse | null;
226
228
  /** Set when the column was created but its companion enrichment config failed. */
227
229
  error?: string | null;
230
+ /** When `already_existed` is true: the existing column's data type. */
231
+ existing_data_type?: string | null;
228
232
  id?: number | null;
229
233
  /** True when this column was created org-GLOBAL (no list_id was supplied) and will therefore appear on EVERY list in the org. Pass `list_id` to scope columns to one list. */
230
234
  is_global?: boolean;
@@ -233,6 +237,8 @@ export interface BatchFieldResult {
233
237
  name?: string | null;
234
238
  ok?: boolean;
235
239
  title: string;
240
+ /** Non-blocking notices for this column (e.g. same name exists org-wide). */
241
+ warnings?: Array<string>;
236
242
  }
237
243
 
238
244
  /**
@@ -279,7 +285,7 @@ export interface CreateFieldEnrichmentResponse {
279
285
 
280
286
  /** Request body for creating a custom field (column). */
281
287
  export interface CreateFieldRequest {
282
- /** Column data type. Currently only 'text' is supported; additional types (numeric, date, boolean, select) may be added in future versions. */
288
+ /** Column data type: 'text', 'int' (whole number), 'numeric' (decimal) or 'boolean' (yes/no). Unknown values 400. If the name already exists with another type, the create is rejected with 409. */
283
289
  data_type?: string;
284
290
  /** Optional enrichment-pipeline block. When supplied, a companion `enrichment_configs` row is created in the same request so the new column is immediately runnable via /enrichment/waterfall/enrich. */
285
291
  enrichment?: CreateFieldEnrichmentInput | null;
@@ -292,14 +298,20 @@ export interface CreateFieldRequest {
292
298
  }
293
299
 
294
300
  export interface CreateFieldResponse {
301
+ /** True when a column with this name already existed in this scope, so no new column was created and `id` is the existing column. A different `data_type` for an existing name is rejected with 409. */
302
+ already_existed?: boolean;
295
303
  data_type: string;
296
304
  /** Populated when the request included an `enrichment` block. Use `enrichment.column_id` for subsequent /enrichment/waterfall/enrich calls. */
297
305
  enrichment?: CreateFieldEnrichmentResponse | null;
306
+ /** When `already_existed` is true: the existing column's data type. */
307
+ existing_data_type?: string | null;
298
308
  id: number;
299
309
  is_global: boolean;
300
310
  list_id?: number | null;
301
311
  name: string;
302
312
  title: string;
313
+ /** Non-blocking notices, e.g. a column with the same name already exists org-wide, so the list now shows two columns with that name. */
314
+ warnings?: Array<string>;
303
315
  }
304
316
 
305
317
  /**
@@ -321,6 +333,9 @@ export interface CreateFieldsBatchResponse {
321
333
  entity: string;
322
334
  list_id?: number | null;
323
335
  results: Array<BatchFieldResult>;
336
+ /** How many requested columns already existed and were returned as-is. */
337
+ total_already_existed?: number;
338
+ /** Columns returned by this call, INCLUDING ones that already existed (unchanged meaning). `total_already_existed` says how many of them were existing columns. */
324
339
  total_created: number;
325
340
  total_requested: number;
326
341
  }
@@ -355,6 +370,8 @@ export interface FieldResponse {
355
370
  data_type?: string;
356
371
  id?: number | null;
357
372
  is_global?: boolean;
373
+ /** Human-readable field name for display, e.g. 'First name' for CONTACT_FIRST_NAME. Custom columns use their title. Keep using `name` as the identifier. */
374
+ label?: string | null;
358
375
  name?: string | null;
359
376
  title: string;
360
377
  }
@@ -370,11 +387,15 @@ export interface FieldValueItem {
370
387
  /** Response body for reading a single custom column value from one row. */
371
388
  export interface GetFieldValueResponse {
372
389
  column_id: number;
390
+ /** The column's data type, the same value `GET /fields` reports in `data_type`: 'text', 'int', 'numeric' or 'boolean'. */
391
+ data_type?: string | null;
373
392
  entity: string;
374
393
  /** The underlying column slug (column_name_db). */
375
394
  name: string;
376
395
  record_id: number;
377
- /** The stored value, or null if the column is unset for this row. */
396
+ /** The stored value in its native JSON type: a number for 'int' and 'numeric' columns, true/false for 'boolean' columns, a string for text columns. Null when the column is unset for this row. */
397
+ typed_value?: boolean | number | string | null;
398
+ /** The stored value as text, or null if the column is unset for this row. Number and yes/no columns are returned in text form ('42', '12.5', 'true'/'false'); read `typed_value` for the native JSON value. */
378
399
  value?: string | null;
379
400
  }
380
401
 
@@ -66,7 +66,7 @@ Body fields (`CreateFieldRequest`):
66
66
  | Field | Type | Required | Description |
67
67
  |---|---|---|---|
68
68
  | `body.title` | `string` | yes | Column title, e.g. 'Job Level' |
69
- | `body.data_type` | `string` | no | Column data type. Currently only 'text' is supported; additional types (numeric, date, boolean, select) may be added in future versions. default `"text"` |
69
+ | `body.data_type` | `string` | no | Column data type: 'text', 'int' (whole number), 'numeric' (decimal) or 'boolean' (yes/no). Unknown values 400. If the name already exists with another type, the create is rejected with 409. default `"text"` |
70
70
  | `body.enrichment` | `CreateFieldEnrichmentInput \| null` | no | Optional enrichment-pipeline block. When supplied, a companion `enrichment_configs` row is created in the same request so the new column is immediately runnable via /enrichment/waterfall/enrich. |
71
71
  | `body.entity` | `string` | no | Target entity: 'contacts' or 'companies' default `"contacts"` |
72
72
  | `body.list_id` | `integer \| null` | no | If set, field is list-specific; otherwise global across the org |
@@ -84,8 +84,11 @@ Other envelope fields: `pagination` (PaginationMeta).
84
84
  | `is_global` | `boolean` | yes | |
85
85
  | `name` | `string` | yes | |
86
86
  | `title` | `string` | yes | |
87
+ | `already_existed` | `boolean` | no | True when a column with this name already existed in this scope, so no new column was created and `id` is the existing column. A different `data_type` for an existing name is rejected with 409. default `false` |
87
88
  | `enrichment` | `CreateFieldEnrichmentResponse \| null` | no | Populated when the request included an `enrichment` block. Use `enrichment.column_id` for subsequent /enrichment/waterfall/enrich calls. |
89
+ | `existing_data_type` | `string \| null` | no | When `already_existed` is true: the existing column's data type. |
88
90
  | `list_id` | `integer \| null` | no | |
91
+ | `warnings` | `Array<string>` | no | Non-blocking notices, e.g. a column with the same name already exists org-wide, so the list now shows two columns with that name. |
89
92
 
90
93
  **Example**
91
94
 
@@ -146,9 +149,10 @@ Other envelope fields: `pagination` (PaginationMeta).
146
149
  |---|---|---|---|
147
150
  | `entity` | `string` | yes | |
148
151
  | `results` | `Array<BatchFieldResult>` | yes | |
149
- | `total_created` | `integer` | yes | |
152
+ | `total_created` | `integer` | yes | Columns returned by this call, INCLUDING ones that already existed (unchanged meaning). `total_already_existed` says how many of them were existing columns. |
150
153
  | `total_requested` | `integer` | yes | |
151
154
  | `list_id` | `integer \| null` | no | |
155
+ | `total_already_existed` | `integer` | no | How many requested columns already existed and were returned as-is. default `0` |
152
156
 
153
157
  **Example**
154
158
 
@@ -251,7 +255,9 @@ Other envelope fields: `pagination` (PaginationMeta).
251
255
  | `entity` | `string` | yes | |
252
256
  | `name` | `string` | yes | The underlying column slug (column_name_db). |
253
257
  | `record_id` | `integer` | yes | |
254
- | `value` | `string \| null` | no | The stored value, or null if the column is unset for this row. |
258
+ | `data_type` | `string \| null` | no | The column's data type, the same value `GET /fields` reports in `data_type`: 'text', 'int', 'numeric' or 'boolean'. |
259
+ | `typed_value` | `boolean \| integer \| number \| string \| null \| null` | no | The stored value in its native JSON type: a number for 'int' and 'numeric' columns, true/false for 'boolean' columns, a string for text columns. Null when the column is unset for this row. |
260
+ | `value` | `string \| null` | no | The stored value as text, or null if the column is unset for this row. Number and yes/no columns are returned in text form ('42', '12.5', 'true'/'false'); read `typed_value` for the native JSON value. |
255
261
 
256
262
  **Example**
257
263
 
@@ -293,6 +299,7 @@ Other envelope fields: `pagination` (PaginationMeta).
293
299
  | `data_type` | `string` | no | default `"text"` |
294
300
  | `id` | `integer \| null` | no | |
295
301
  | `is_global` | `boolean` | no | default `true` |
302
+ | `label` | `string \| null` | no | Human-readable field name for display, e.g. 'First name' for CONTACT_FIRST_NAME. Custom columns use their title. Keep using `name` as the identifier. |
296
303
  | `name` | `string \| null` | no | |
297
304
 
298
305
  **Example**
@@ -335,6 +342,7 @@ Other envelope fields: `pagination` (PaginationMeta).
335
342
  | `data_type` | `string` | no | default `"text"` |
336
343
  | `id` | `integer \| null` | no | |
337
344
  | `is_global` | `boolean` | no | default `true` |
345
+ | `label` | `string \| null` | no | Human-readable field name for display, e.g. 'First name' for CONTACT_FIRST_NAME. Custom columns use their title. Keep using `name` as the identifier. |
338
346
  | `name` | `string \| null` | no | |
339
347
 
340
348
  **Example**
@@ -489,7 +497,7 @@ One column in a batch-create request. `title`, `data_type` and the optional `enr
489
497
  | Field | Type | Required | Description |
490
498
  |---|---|---|---|
491
499
  | `title` | `string` | yes | Column title, e.g. 'Job Level' |
492
- | `data_type` | `string` | no | Column data type. Currently only 'text' is supported. default `"text"` |
500
+ | `data_type` | `string` | no | Column data type: 'text', 'int' (whole number), 'numeric' (decimal) or 'boolean' (yes/no). Unknown values 400. default `"text"` |
493
501
  | `enrichment` | `CreateFieldEnrichmentInput \| null` | no | Optional per-column waterfall enrichment block (identical shape to POST /fields). When supplied, a companion enrichment_configs row is created for that column so it's immediately runnable. |
494
502
 
495
503
  <a id="type-batchfieldresult"></a>
@@ -501,13 +509,16 @@ Per-column outcome inside a batch response.
501
509
  | Field | Type | Required | Description |
502
510
  |---|---|---|---|
503
511
  | `title` | `string` | yes | |
512
+ | `already_existed` | `boolean` | no | True when this column already existed (same name, same scope), so the existing column was returned instead of a new one. default `false` |
504
513
  | `enrichment` | `CreateFieldEnrichmentResponse \| null` | no | |
505
514
  | `error` | `string \| null` | no | Set when the column was created but its companion enrichment config failed. |
515
+ | `existing_data_type` | `string \| null` | no | When `already_existed` is true: the existing column's data type. |
506
516
  | `id` | `integer \| null` | no | |
507
517
  | `is_global` | `boolean` | no | True when this column was created org-GLOBAL (no list_id was supplied) and will therefore appear on EVERY list in the org. Pass `list_id` to scope columns to one list. default `false` |
508
518
  | `list_id` | `integer \| null` | no | The list this column is scoped to, or null when it is org-global. |
509
519
  | `name` | `string \| null` | no | |
510
520
  | `ok` | `boolean` | no | default `true` |
521
+ | `warnings` | `Array<string>` | no | Non-blocking notices for this column (e.g. same name exists org-wide). |
511
522
 
512
523
  <a id="type-createfieldenrichmentinput"></a>
513
524
 
@@ -106,6 +106,12 @@ export interface InstallOperations {
106
106
  /** Repository ID */
107
107
  repo_id: string;
108
108
  };
109
+ query?: {
110
+ /** Page number (1-indexed). Omit page and limit to get every stream. */
111
+ page?: number | null;
112
+ /** Streams per page (max 200). Omit page and limit to get every stream. */
113
+ limit?: number | null;
114
+ };
109
115
  headers?: {
110
116
  "X-Target-Org-Id"?: string | null;
111
117
  };
@@ -196,6 +202,10 @@ export interface PatchSetResponse {
196
202
  }
197
203
 
198
204
  export interface SnippetResponse {
205
+ /** True when the organization has several streams and none could be identified as its main website. The write key is the first stream's (unchanged legacy default); pick the right one from available_streams and call again with stream_id. */
206
+ action_required?: boolean;
207
+ /** The organization's streams to choose from. Filled only when action_required is true. */
208
+ available_streams?: Array<StreamInfoResponse>;
199
209
  /** Full configuration object for gtm/config.json */
200
210
  config?: Record<string, unknown>;
201
211
  domains?: Array<string>;
@@ -203,17 +213,33 @@ export interface SnippetResponse {
203
213
  react_snippet: string;
204
214
  /** Vanilla JS script tag for non-React apps */
205
215
  script_tag: string;
216
+ /** ID of the tracking stream the write key belongs to, when known. */
217
+ stream_id?: string | null;
218
+ /** User-friendly name of that stream, when known. */
219
+ stream_name?: string | null;
220
+ /** How the stream was chosen: 'explicit' (stream_id given), 'repo_write_key' (the repository's stored key), 'only_stream', 'domain_match' (matches the organization's website), or 'first_stream_fallback' (ambiguous; see action_required). */
221
+ stream_selection?: string | null;
206
222
  tracking_host?: string;
223
+ /** Human-readable explanation when action_required is true, or a stream setup advisory. */
224
+ warning?: string | null;
207
225
  write_key: string;
208
226
  }
209
227
 
210
228
  export interface StreamInfoResponse {
211
229
  /** Domains associated with this stream */
212
230
  domains?: Array<string>;
231
+ /** Whether the stream lists allowed domains. False means its public write key is accepted from any website (see warning). */
232
+ domains_restricted?: boolean;
213
233
  /** Stream ID used to select this stream */
214
234
  id: string;
235
+ /** True for the stream GET /snippet uses when no stream_id is given: the only stream, or the one whose domain matches the organization's website. False on every stream when that choice is ambiguous; pass stream_id explicitly then. */
236
+ is_default?: boolean;
215
237
  /** User-friendly stream name (e.g. 'graph8.com', 'heyreach-graph8') */
216
238
  name: string;
239
+ /** Connected repository whose stored write key belongs to this stream. Null when no connected repository uses it: streams are organization-level, not owned by a repo. */
240
+ repo_id?: string | null;
241
+ /** Read-only advisory about this stream's setup, e.g. no allowed domains. Nothing is enforced. */
242
+ warning?: string | null;
217
243
  /** Public write key for this stream */
218
244
  write_key?: string | null;
219
245
  }
@@ -201,9 +201,15 @@ Other envelope fields: `pagination` (PaginationMeta).
201
201
  | `react_snippet` | `string` | yes | Ready-to-use React component import for @graph8/nextjs |
202
202
  | `script_tag` | `string` | yes | Vanilla JS script tag for non-React apps |
203
203
  | `write_key` | `string` | yes | |
204
+ | `action_required` | `boolean` | no | True when the organization has several streams and none could be identified as its main website. The write key is the first stream's (unchanged legacy default); pick the right one from available_streams and call again with stream_id. default `false` |
205
+ | `available_streams` | `Array<StreamInfoResponse>` | no | The organization's streams to choose from. Filled only when action_required is true. |
204
206
  | `config` | `Record<string, unknown>` | no | Full configuration object for gtm/config.json |
205
207
  | `domains` | `Array<string>` | no | |
208
+ | `stream_id` | `string \| null` | no | ID of the tracking stream the write key belongs to, when known. |
209
+ | `stream_name` | `string \| null` | no | User-friendly name of that stream, when known. |
210
+ | `stream_selection` | `string \| null` | no | How the stream was chosen: 'explicit' (stream_id given), 'repo_write_key' (the repository's stored key), 'only_stream', 'domain_match' (matches the organization's website), or 'first_stream_fallback' (ambiguous; see action_required). |
206
211
  | `tracking_host` | `string` | no | default `"https://t.graph8.com"` |
212
+ | `warning` | `string \| null` | no | Human-readable explanation when action_required is true, or a stream setup advisory. |
207
213
 
208
214
  **Example**
209
215
 
@@ -230,11 +236,19 @@ Returns each stream's ID, user-friendly name (domain or label),
230
236
  associated domains, and write key. The caller should select one
231
237
  and pass its `id` to the snippet endpoint.
232
238
 
239
+ Streams belong to the organization, not to the repository: every stream
240
+ of the org is listed, and `repo_id` on each one names the connected
241
+ repository already using it (null when none does). The repository must
242
+ exist in the caller's organization (404 otherwise). The org-level
243
+ equivalent that needs no repository is `GET /streams`.
244
+
233
245
  **Input**
234
246
 
235
247
  | Field | Type | Required | Description |
236
248
  |---|---|---|---|
237
249
  | `path.repo_id` | `string` | yes | Repository ID |
250
+ | `query.page` | `integer \| null` | no | Page number (1-indexed). Omit page and limit to get every stream. |
251
+ | `query.limit` | `integer \| null` | no | Streams per page (max 200). Omit page and limit to get every stream. |
238
252
 
239
253
  **Returns** `ApiResponse_list_StreamInfoResponse__`: the envelope `{ data: Array<StreamInfoResponse>, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
240
254
 
@@ -247,6 +261,10 @@ Other envelope fields: `pagination` (PaginationMeta).
247
261
  | `id` | `string` | yes | Stream ID used to select this stream |
248
262
  | `name` | `string` | yes | User-friendly stream name (e.g. 'graph8.com', 'heyreach-graph8') |
249
263
  | `domains` | `Array<string>` | no | Domains associated with this stream |
264
+ | `domains_restricted` | `boolean` | no | Whether the stream lists allowed domains. False means its public write key is accepted from any website (see warning). default `false` |
265
+ | `is_default` | `boolean` | no | True for the stream GET /snippet uses when no stream_id is given: the only stream, or the one whose domain matches the organization's website. False on every stream when that choice is ambiguous; pass stream_id explicitly then. default `false` |
266
+ | `repo_id` | `string \| null` | no | Connected repository whose stored write key belongs to this stream. Null when no connected repository uses it: streams are organization-level, not owned by a repo. |
267
+ | `warning` | `string \| null` | no | Read-only advisory about this stream's setup, e.g. no allowed domains. Nothing is enforced. |
250
268
  | `write_key` | `string \| null` | no | Public write key for this stream |
251
269
 
252
270
  **Example**
@@ -273,7 +273,7 @@ export interface IntentOperations {
273
273
  };
274
274
  }
275
275
 
276
- // 27 schemas referenced above (the same as G8Contract.<Name>).
276
+ // 28 schemas referenced above (the same as G8Contract.<Name>).
277
277
 
278
278
  export interface ApiResponse_KeywordCreateFromDomainResponse_ {
279
279
  data: KeywordCreateFromDomainResponse;
@@ -300,6 +300,13 @@ export interface ApiResponse_PagesSearchResponse_ {
300
300
  pagination?: PaginationMeta | null;
301
301
  }
302
302
 
303
+ export interface CreateFromDomainSampleContact {
304
+ company_domain?: string | null;
305
+ company_name?: string | null;
306
+ job_title?: string | null;
307
+ name?: string | null;
308
+ }
309
+
303
310
  export interface IntentPageItem {
304
311
  audience?: string | null;
305
312
  commercial_score?: number | null;
@@ -309,6 +316,8 @@ export interface IntentPageItem {
309
316
  summary?: string | null;
310
317
  title?: string | null;
311
318
  url?: string | null;
319
+ /** Distinct visitors (hashed emails) in the lookback window. Set only by pages/search with include_visitors=true when the count succeeded; null otherwise. */
320
+ visitors?: number | null;
312
321
  }
313
322
 
314
323
  export interface KeywordAddedItem {
@@ -324,6 +333,8 @@ export interface KeywordCreateFromDomainRequest {
324
333
  contact_limit?: number;
325
334
  /** Competitor domain to track, e.g. 'cognism.com'. */
326
335
  domain: string;
336
+ /** Preview only: find the on-domain pages and resolve contacts exactly as a real run would, but save nothing. The counts then say what WOULD be seeded, keyword_id stays null, and sample_pages / sample_contacts show a preview. Default false keeps the one-call create. */
337
+ dry_run?: boolean;
327
338
  /** Max pages to seed from the domain. */
328
339
  page_limit?: number;
329
340
  }
@@ -331,11 +342,17 @@ export interface KeywordCreateFromDomainRequest {
331
342
  export interface KeywordCreateFromDomainResponse {
332
343
  companies_seeded?: number;
333
344
  contacts_seeded?: number;
345
+ /** True when nothing was saved (preview). */
346
+ dry_run?: boolean;
334
347
  keyword: string;
335
348
  keyword_id?: string | null;
336
349
  message?: string;
337
350
  off_domain_rejected?: number;
338
351
  pages_seeded?: number;
352
+ /** Dry run only: up to 10 of the contacts that would be pre-resolved (no emails). */
353
+ sample_contacts?: Array<CreateFromDomainSampleContact>;
354
+ /** Dry run only: up to 10 of the pages that would be seeded. */
355
+ sample_pages?: Array<IntentPageItem>;
339
356
  }
340
357
 
341
358
  export interface KeywordCreateFromSearchItem {
@@ -441,11 +458,19 @@ export interface PagesSearchRequest {
441
458
  }
442
459
 
443
460
  export interface PagesSearchResponse {
461
+ /** Hits hidden because they had no visitors in the lookback window (include_visitors=true). total_hits counts them; pages does not. */
462
+ filtered_no_visitors?: number;
444
463
  mode?: string;
445
464
  pages?: Array<IntentPageItem>;
446
465
  query: string;
466
+ /** How this search scoped the results, when it differs from a sibling tool (e.g. a bare-domain query matches the apex + www only). */
467
+ scope_note?: string | null;
447
468
  took_ms?: number;
448
469
  total_hits?: number;
470
+ /** Why visitor enrichment was skipped (include_visitors=true only). */
471
+ visitors_error?: string | null;
472
+ /** Non-fatal problems: visitor counts timed out or failed (pages are then returned unfiltered, visitors=null), every hit was hidden by the has-visitors filter, or the search backend failed. */
473
+ warnings?: Array<string>;
449
474
  }
450
475
 
451
476
  export interface PagesVisitorCountsRequest {
@@ -168,6 +168,9 @@ const result = await g8.api.intent.keywordContacts({
168
168
 
169
169
  Replace a keyword's `search_filters` JSON.
170
170
 
171
+ 404 when the keyword does not exist for this org or was deleted (IN-07:
172
+ the bare ALTER matched no row and still answered "success").
173
+
171
174
  **Input**
172
175
 
173
176
  | Field | Type | Required | Description |
@@ -339,6 +342,7 @@ Body fields (`KeywordCreateFromDomainRequest`):
339
342
  |---|---|---|---|
340
343
  | `body.domain` | `string` | yes | Competitor domain to track, e.g. 'cognism.com'. min length 3, max length 253 |
341
344
  | `body.contact_limit` | `integer` | no | Max contacts to pre-resolve. default `200`, min 1, max 500 |
345
+ | `body.dry_run` | `boolean` | no | Preview only: find the on-domain pages and resolve contacts exactly as a real run would, but save nothing. The counts then say what WOULD be seeded, keyword_id stays null, and sample_pages / sample_contacts show a preview. Default false keeps the one-call create. default `false` |
342
346
  | `body.page_limit` | `integer` | no | Max pages to seed from the domain. default `200`, min 1, max 500 |
343
347
 
344
348
  **Returns** `ApiResponse_KeywordCreateFromDomainResponse_`: the envelope `{ data: KeywordCreateFromDomainResponse, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
@@ -352,10 +356,13 @@ Other envelope fields: `pagination` (PaginationMeta).
352
356
  | `keyword` | `string` | yes | |
353
357
  | `companies_seeded` | `integer` | no | default `0` |
354
358
  | `contacts_seeded` | `integer` | no | default `0` |
359
+ | `dry_run` | `boolean` | no | True when nothing was saved (preview). default `false` |
355
360
  | `keyword_id` | `string \| null` | no | |
356
361
  | `message` | `string` | no | default `""` |
357
362
  | `off_domain_rejected` | `integer` | no | default `0` |
358
363
  | `pages_seeded` | `integer` | no | default `0` |
364
+ | `sample_contacts` | `Array<CreateFromDomainSampleContact>` | no | Dry run only: up to 10 of the contacts that would be pre-resolved (no emails). |
365
+ | `sample_pages` | `Array<IntentPageItem>` | no | Dry run only: up to 10 of the pages that would be seeded. |
359
366
 
360
367
  **Example**
361
368
 
@@ -652,10 +659,14 @@ Other envelope fields: `pagination` (PaginationMeta).
652
659
  | Field | Type | Required | Description |
653
660
  |---|---|---|---|
654
661
  | `query` | `string` | yes | |
662
+ | `filtered_no_visitors` | `integer` | no | Hits hidden because they had no visitors in the lookback window (include_visitors=true). total_hits counts them; pages does not. default `0` |
655
663
  | `mode` | `string` | no | default `"text"` |
656
664
  | `pages` | `Array<IntentPageItem>` | no | default `[]` |
665
+ | `scope_note` | `string \| null` | no | How this search scoped the results, when it differs from a sibling tool (e.g. a bare-domain query matches the apex + www only). |
657
666
  | `took_ms` | `integer` | no | default `0` |
658
667
  | `total_hits` | `integer` | no | default `0` |
668
+ | `visitors_error` | `string \| null` | no | Why visitor enrichment was skipped (include_visitors=true only). |
669
+ | `warnings` | `Array<string>` | no | Non-fatal problems: visitor counts timed out or failed (pages are then returned unfiltered, visitors=null), every hit was hidden by the has-visitors filter, or the search backend failed. |
659
670
 
660
671
  **Example**
661
672
 
@@ -808,6 +819,17 @@ const result = await g8.api.intent.urlCompanies({ body: { url: "https://example.
808
819
 
809
820
  Named types that appear in the tables above. Full TypeScript definitions: `G8Contract.<Name>` (`import type { G8Contract } from "@graph8/sdk"`).
810
821
 
822
+ <a id="type-createfromdomainsamplecontact"></a>
823
+
824
+ ### `CreateFromDomainSampleContact`
825
+
826
+ | Field | Type | Required | Description |
827
+ |---|---|---|---|
828
+ | `company_domain` | `string \| null` | no | |
829
+ | `company_name` | `string \| null` | no | |
830
+ | `job_title` | `string \| null` | no | |
831
+ | `name` | `string \| null` | no | |
832
+
811
833
  <a id="type-intentpageitem"></a>
812
834
 
813
835
  ### `IntentPageItem`
@@ -822,6 +844,7 @@ Named types that appear in the tables above. Full TypeScript definitions: `G8Con
822
844
  | `summary` | `string \| null` | no | |
823
845
  | `title` | `string \| null` | no | |
824
846
  | `url` | `string \| null` | no | |
847
+ | `visitors` | `integer \| null` | no | Distinct visitors (hashed emails) in the lookback window. Set only by pages/search with include_visitors=true when the count succeeded; null otherwise. |
825
848
 
826
849
  <a id="type-keywordaddeditem"></a>
827
850
 
@@ -896,11 +896,15 @@ export interface ListCreateRequest {
896
896
 
897
897
  export interface ListCreateResponse {
898
898
  description?: string | null;
899
+ /** Ids of existing lists with the same name (case-insensitive), when any. */
900
+ duplicate_list_ids?: Array<number> | null;
899
901
  id: number;
900
902
  status?: string | null;
901
903
  title: string;
902
904
  total?: number;
903
905
  type?: string | null;
906
+ /** Set when another list already has this name. The list was still created. */
907
+ warning?: string | null;
904
908
  }
905
909
 
906
910
  /**
@@ -999,6 +1003,10 @@ export interface ListPerformanceResponse {
999
1003
 
1000
1004
  /** Audience/list representation for the public API. */
1001
1005
  export interface ListResponse {
1006
+ /** Number of companies in a company list (null for other list types) */
1007
+ company_count?: number | null;
1008
+ /** Number of contacts in a contact list (null for other list types) */
1009
+ contact_count?: number | null;
1002
1010
  created_at?: string | null;
1003
1011
  created_by?: string | null;
1004
1012
  /** Agent/human-readable note describing the list's purpose (#16641) */
@@ -1013,6 +1021,7 @@ export interface ListResponse {
1013
1021
  total?: number;
1014
1022
  /** List type (contacts, companies, suppressions, deals, leads) */
1015
1023
  type?: string | null;
1024
+ /** Last change to the list. Equals created_at for a list never edited since creation. */
1016
1025
  updated_at?: string | null;
1017
1026
  }
1018
1027
 
package/docs/api/lists.md CHANGED
@@ -75,6 +75,10 @@ Exact TypeScript types for every operation on this page, and every schema they u
75
75
 
76
76
  Add contacts to a list by their IDs.
77
77
 
78
+ ``added`` is the number of membership rows really created. Ids that are not
79
+ live contacts in this org come back in ``not_found``; ids already on the
80
+ list in ``already_member`` (LI-01). A missing or deleted list is a 404.
81
+
78
82
  **Input**
79
83
 
80
84
  | Field | Type | Required | Description |
@@ -350,9 +354,11 @@ Other envelope fields: `pagination` (PaginationMeta).
350
354
  | `id` | `integer` | yes | |
351
355
  | `title` | `string` | yes | |
352
356
  | `description` | `string \| null` | no | |
357
+ | `duplicate_list_ids` | `Array<integer> \| null` | no | Ids of existing lists with the same name (case-insensitive), when any. |
353
358
  | `status` | `string \| null` | no | |
354
359
  | `total` | `integer` | no | default `0` |
355
360
  | `type` | `string \| null` | no | |
361
+ | `warning` | `string \| null` | no | Set when another list already has this name. The list was still created. |
356
362
 
357
363
  **Example**
358
364
 
@@ -1076,6 +1082,8 @@ Other envelope fields: `pagination` (PaginationMeta).
1076
1082
  |---|---|---|---|
1077
1083
  | `id` | `integer` | yes | |
1078
1084
  | `title` | `string` | yes | |
1085
+ | `company_count` | `integer \| null` | no | Number of companies in a company list (null for other list types) |
1086
+ | `contact_count` | `integer \| null` | no | Number of contacts in a contact list (null for other list types) |
1079
1087
  | `created_at` | `string (date-time) \| null` | no | |
1080
1088
  | `created_by` | `string \| null` | no | |
1081
1089
  | `description` | `string \| null` | no | Agent/human-readable note describing the list's purpose (#16641) |
@@ -1085,7 +1093,7 @@ Other envelope fields: `pagination` (PaginationMeta).
1085
1093
  | `tags` | `Array<string>` | no | |
1086
1094
  | `total` | `integer` | no | default `0` |
1087
1095
  | `type` | `string \| null` | no | List type (contacts, companies, suppressions, deals, leads) |
1088
- | `updated_at` | `string (date-time) \| null` | no | |
1096
+ | `updated_at` | `string (date-time) \| null` | no | Last change to the list. Equals created_at for a list never edited since creation. |
1089
1097
 
1090
1098
  **Example**
1091
1099
 
@@ -1381,6 +1389,11 @@ const result = await g8.api.lists.refreshMasterListNow({ path: { audience_id: 12
1381
1389
 
1382
1390
  Remove contacts from a list.
1383
1391
 
1392
+ ``removed`` is the number of membership rows really deleted; requested ids
1393
+ that were not on the list come back in ``not_member`` (LI-01). A missing or
1394
+ deleted list is a 404 (a deleted list's membership is frozen, so nothing
1395
+ could be removed from it anyway).
1396
+
1384
1397
  **Input**
1385
1398
 
1386
1399
  | Field | Type | Required | Description |
@@ -1483,6 +1496,8 @@ Other envelope fields: `pagination` (PaginationMeta).
1483
1496
  |---|---|---|---|
1484
1497
  | `id` | `integer` | yes | |
1485
1498
  | `title` | `string` | yes | |
1499
+ | `company_count` | `integer \| null` | no | Number of companies in a company list (null for other list types) |
1500
+ | `contact_count` | `integer \| null` | no | Number of contacts in a contact list (null for other list types) |
1486
1501
  | `created_at` | `string (date-time) \| null` | no | |
1487
1502
  | `created_by` | `string \| null` | no | |
1488
1503
  | `description` | `string \| null` | no | Agent/human-readable note describing the list's purpose (#16641) |
@@ -1492,7 +1507,7 @@ Other envelope fields: `pagination` (PaginationMeta).
1492
1507
  | `tags` | `Array<string>` | no | |
1493
1508
  | `total` | `integer` | no | default `0` |
1494
1509
  | `type` | `string \| null` | no | List type (contacts, companies, suppressions, deals, leads) |
1495
- | `updated_at` | `string (date-time) \| null` | no | |
1510
+ | `updated_at` | `string (date-time) \| null` | no | Last change to the list. Equals created_at for a list never edited since creation. |
1496
1511
 
1497
1512
  **Example**
1498
1513