@graph8/sdk 0.357.0 → 0.358.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.
@@ -5,6 +5,6 @@
5
5
  * both together (the version-parity gate already pins package.json, the
6
6
  * lockfile and the CHANGELOG to each other).
7
7
  */
8
- export declare const SDK_VERSION = "0.357.0";
8
+ export declare const SDK_VERSION = "0.358.0";
9
9
  /** Value of the `X-G8-Client` header every SDK request carries (I-13). */
10
- export declare const SDK_CLIENT_ID = "js-sdk/0.357.0";
10
+ export declare const SDK_CLIENT_ID = "js-sdk/0.358.0";
@@ -355,6 +355,8 @@ export interface EnrichmentOperations {
355
355
  query?: {
356
356
  /** Remove the configuration permanently instead of deactivating it. The values it already wrote are kept either way. */
357
357
  hard_delete?: boolean;
358
+ /** Set to `org` to change or delete a qualification group shared by every list (the ICP and Persona qualification groups). Admin keys only. Without it such a call answers 409 with code `shared_qualification_group`. */
359
+ scope?: string | null;
358
360
  };
359
361
  headers?: {
360
362
  "X-Target-Org-Id"?: string | null;
@@ -376,6 +378,8 @@ export interface EnrichmentOperations {
376
378
  query?: {
377
379
  /** Remove the configuration permanently instead of deactivating it. The values it already wrote are kept either way. */
378
380
  hard_delete?: boolean;
381
+ /** Set to `org` to change or delete a qualification group shared by every list (the ICP and Persona qualification groups). Admin keys only. Without it such a call answers 409 with code `shared_qualification_group`. */
382
+ scope?: string | null;
379
383
  };
380
384
  headers?: {
381
385
  "X-Target-Org-Id"?: string | null;
@@ -414,6 +418,8 @@ export interface EnrichmentOperations {
414
418
  query?: {
415
419
  /** Remove the configuration permanently instead of deactivating it. The values it already wrote are kept either way. */
416
420
  hard_delete?: boolean;
421
+ /** Set to `org` to change or delete a qualification group shared by every list (the ICP and Persona qualification groups). Admin keys only. Without it such a call answers 409 with code `shared_qualification_group`. */
422
+ scope?: string | null;
417
423
  };
418
424
  headers?: {
419
425
  "X-Target-Org-Id"?: string | null;
@@ -1566,6 +1572,10 @@ export interface EnrichmentOperations {
1566
1572
  /** AI group id. */
1567
1573
  group_id: string;
1568
1574
  };
1575
+ query?: {
1576
+ /** Set to `org` to change or delete a qualification group shared by every list (the ICP and Persona qualification groups). Admin keys only. Without it such a call answers 409 with code `shared_qualification_group`. */
1577
+ scope?: string | null;
1578
+ };
1569
1579
  headers?: {
1570
1580
  "X-Target-Org-Id"?: string | null;
1571
1581
  };
@@ -1829,6 +1839,10 @@ export interface EnrichmentOperations {
1829
1839
  /** The AI group id. */
1830
1840
  group_id: string;
1831
1841
  };
1842
+ query?: {
1843
+ /** Set to `org` to change or delete a qualification group shared by every list (the ICP and Persona qualification groups). Admin keys only. Without it such a call answers 409 with code `shared_qualification_group`. */
1844
+ scope?: string | null;
1845
+ };
1832
1846
  headers?: {
1833
1847
  "X-Target-Org-Id"?: string | null;
1834
1848
  };
@@ -1883,6 +1897,10 @@ export interface EnrichmentOperations {
1883
1897
  /** Enrichment configuration id (UUID). */
1884
1898
  config_id: string;
1885
1899
  };
1900
+ query?: {
1901
+ /** Set to `org` to change or delete a qualification group shared by every list (the ICP and Persona qualification groups). Admin keys only. Without it such a call answers 409 with code `shared_qualification_group`. */
1902
+ scope?: string | null;
1903
+ };
1886
1904
  headers?: {
1887
1905
  "X-Target-Org-Id"?: string | null;
1888
1906
  };
@@ -802,7 +802,9 @@ const result = await g8.api.enrichment.createRoutingRule({ body: { name: "Exampl
802
802
  Drop ONE column from an AI group. The group and its other columns stay.
803
803
 
804
804
  Free. `columns` is plural here where the app writes `column`, so the path
805
- reads the same way as every other collection in this contract.
805
+ reads the same way as every other collection in this contract. A column of
806
+ a qualification group shared by every list answers 409 unless `scope=org`
807
+ (admin keys only).
806
808
 
807
809
  **Input**
808
810
 
@@ -811,6 +813,7 @@ reads the same way as every other collection in this contract.
811
813
  | `path.group_id` | `string` | yes | AI group id. |
812
814
  | `path.column_id` | `string` | yes | The single column to drop. |
813
815
  | `query.hard_delete` | `boolean` | no | Remove the configuration permanently instead of deactivating it. The values it already wrote are kept either way. default `false` |
816
+ | `query.scope` | `string \| null` | no | Set to `org` to change or delete a qualification group shared by every list (the ICP and Persona qualification groups). Admin keys only. Without it such a call answers 409 with code `shared_qualification_group`. |
814
817
 
815
818
  **Returns** `ApiResponse_EnrichmentPayload_`: the envelope `{ data: EnrichmentPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
816
819
 
@@ -838,12 +841,16 @@ const result = await g8.api.enrichment.deleteAiConfigByColumn({ path: { group_id
838
841
 
839
842
  Remove an AI group and every column it owns. Free.
840
843
 
844
+ A qualification group shared by every list answers 409 unless `scope=org`
845
+ (admin keys only).
846
+
841
847
  **Input**
842
848
 
843
849
  | Field | Type | Required | Description |
844
850
  |---|---|---|---|
845
851
  | `path.group_id` | `string` | yes | AI group id. |
846
852
  | `query.hard_delete` | `boolean` | no | Remove the configuration permanently instead of deactivating it. The values it already wrote are kept either way. default `false` |
853
+ | `query.scope` | `string \| null` | no | Set to `org` to change or delete a qualification group shared by every list (the ICP and Persona qualification groups). Admin keys only. Without it such a call answers 409 with code `shared_qualification_group`. |
847
854
 
848
855
  **Returns** `ApiResponse_EnrichmentPayload_`: the envelope `{ data: EnrichmentPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
849
856
 
@@ -903,12 +910,16 @@ const result = await g8.api.enrichment.deleteAutoEnrichmentConfig({ path: { conf
903
910
 
904
911
  Remove an enrichment configuration. Free.
905
912
 
913
+ A qualification configuration shared by every list answers 409 unless
914
+ `scope=org` (admin keys only).
915
+
906
916
  **Input**
907
917
 
908
918
  | Field | Type | Required | Description |
909
919
  |---|---|---|---|
910
920
  | `path.config_id` | `string` | yes | Enrichment configuration id (UUID). |
911
921
  | `query.hard_delete` | `boolean` | no | Remove the configuration permanently instead of deactivating it. The values it already wrote are kept either way. default `false` |
922
+ | `query.scope` | `string \| null` | no | Set to `org` to change or delete a qualification group shared by every list (the ICP and Persona qualification groups). Admin keys only. Without it such a call answers 409 with code `shared_qualification_group`. |
912
923
 
913
924
  **Returns** `ApiResponse_EnrichmentPayload_`: the envelope `{ data: EnrichmentPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
914
925
 
@@ -3505,7 +3516,8 @@ const result = await g8.api.enrichment.previewRoutingRule({ body: { source_list_
3505
3516
  Rename the column an AI group writes into. Free.
3506
3517
 
3507
3518
  Display name only - the underlying column id does not move, so formulas and
3508
- mappings that reference it keep working.
3519
+ mappings that reference it keep working. A qualification group shared by
3520
+ every list answers 409 unless `scope=org` (admin keys only).
3509
3521
 
3510
3522
  **Input**
3511
3523
 
@@ -3513,6 +3525,7 @@ mappings that reference it keep working.
3513
3525
  |---|---|---|---|
3514
3526
  | `path.group_id` | `string` | yes | AI group id. |
3515
3527
  | `body` | `RenameAIColumnRequest` | yes | Request body; fields below. |
3528
+ | `query.scope` | `string \| null` | no | Set to `org` to change or delete a qualification group shared by every list (the ICP and Persona qualification groups). Admin keys only. Without it such a call answers 409 with code `shared_qualification_group`. |
3516
3529
 
3517
3530
  Body fields (`RenameAIColumnRequest`):
3518
3531
 
@@ -4006,6 +4019,10 @@ EVERY list in the organisation, not just `config.list_id`. That is the
4006
4019
  wider blast radius of the two and it is what you get by omission, so set it
4007
4020
  deliberately.
4008
4021
 
4022
+ A `config.group_id` naming a qualification group shared by every list (the
4023
+ ICP and Persona qualification groups) answers 409 with code
4024
+ `shared_qualification_group`: those groups cannot gain columns here.
4025
+
4009
4026
  **Input**
4010
4027
 
4011
4028
  | Field | Type | Required | Description |
@@ -4308,7 +4325,8 @@ const result = await g8.api.enrichment.unassignConfigFromList({
4308
4325
  Edit an AI group in place. Free: editing runs nothing.
4309
4326
 
4310
4327
  Output columns that already exist keep their data; the run condition is
4311
- validated before anything is saved.
4328
+ validated before anything is saved. A qualification group shared by every
4329
+ list answers 409 unless `scope=org` (admin keys only).
4312
4330
 
4313
4331
  **Input**
4314
4332
 
@@ -4316,6 +4334,7 @@ validated before anything is saved.
4316
4334
  |---|---|---|---|
4317
4335
  | `path.group_id` | `string` | yes | The AI group id. |
4318
4336
  | `body` | `UpdateAIConfigRequest` | yes | Request body; fields below. |
4337
+ | `query.scope` | `string \| null` | no | Set to `org` to change or delete a qualification group shared by every list (the ICP and Persona qualification groups). Admin keys only. Without it such a call answers 409 with code `shared_qualification_group`. |
4319
4338
 
4320
4339
  Body fields (`UpdateAIConfigRequest`):
4321
4340
 
@@ -4452,7 +4471,8 @@ Change fields on an enrichment configuration. Free.
4452
4471
  Whatever keys are sent are written - the app takes a free-form body here
4453
4472
  and this forwards it unchanged rather than narrowing what the browser can
4454
4473
  already do. `updated_by` is stamped from the calling key and cannot be
4455
- supplied.
4474
+ supplied. A qualification configuration shared by every list answers 409
4475
+ unless `scope=org` (admin keys only).
4456
4476
 
4457
4477
  **Input**
4458
4478
 
@@ -4460,6 +4480,7 @@ supplied.
4460
4480
  |---|---|---|---|
4461
4481
  | `path.config_id` | `string` | yes | Enrichment configuration id (UUID). |
4462
4482
  | `body` | `EnrichmentConfigUpdateRequest` | yes | Request body; fields below. |
4483
+ | `query.scope` | `string \| null` | no | Set to `org` to change or delete a qualification group shared by every list (the ICP and Persona qualification groups). Admin keys only. Without it such a call answers 409 with code `shared_qualification_group`. |
4463
4484
 
4464
4485
  Body fields (`EnrichmentConfigUpdateRequest`):
4465
4486
 
@@ -153,7 +153,9 @@ export interface LifecycleRecordItem {
153
153
  }
154
154
 
155
155
  export interface LifecycleStageMoveRequest {
156
- /** Company moves only: run every check the move runs (company exists, stage known, Customers/Churned guards) and return the would-be transition without writing anything. Ignored for contact moves. */
156
+ /** Confirm a move to Customers of a company with no subscription (or a contact with no company or whose company has none). Without it such a move is refused with 409 and detail.code 'customers_without_subscription'. */
157
+ confirm_without_subscription?: boolean;
158
+ /** Run every check the move runs (record exists, stage known, Customers/Churned guards, the no-subscription confirmation) and return the would-be transition without writing anything. */
157
159
  dry_run?: boolean;
158
160
  /** Destination lifecycle slug, e.g. 'suspects', 'leads', 'trials', 'customers', 'churned'. Case and surrounding whitespace are ignored, and a stage's display name is accepted too. */
159
161
  target_slug: string;
@@ -191,6 +191,10 @@ with a 400 unless the company is or was a customer. `target_slug` ignores
191
191
  case and surrounding whitespace. `dry_run: true` runs every check and
192
192
  returns the would-be transition without writing anything.
193
193
 
194
+ A move to `customers` of a company with no subscription at all is a 409
195
+ (`detail.code` 'customers_without_subscription', `detail.message` names the
196
+ company) unless `confirm_without_subscription: true` is sent (R3-30).
197
+
194
198
  **Input**
195
199
 
196
200
  | Field | Type | Required | Description |
@@ -203,7 +207,8 @@ Body fields (`LifecycleStageMoveRequest`):
203
207
  | Field | Type | Required | Description |
204
208
  |---|---|---|---|
205
209
  | `body.target_slug` | `string` | yes | Destination lifecycle slug, e.g. 'suspects', 'leads', 'trials', 'customers', 'churned'. Case and surrounding whitespace are ignored, and a stage's display name is accepted too. |
206
- | `body.dry_run` | `boolean` | no | Company moves only: run every check the move runs (company exists, stage known, Customers/Churned guards) and return the would-be transition without writing anything. Ignored for contact moves. default `false` |
210
+ | `body.confirm_without_subscription` | `boolean` | no | Confirm a move to Customers of a company with no subscription (or a contact with no company or whose company has none). Without it such a move is refused with 409 and detail.code 'customers_without_subscription'. default `false` |
211
+ | `body.dry_run` | `boolean` | no | Run every check the move runs (record exists, stage known, Customers/Churned guards, the no-subscription confirmation) and return the would-be transition without writing anything. default `false` |
207
212
 
208
213
  **Returns** `ApiResponse_LifecycleStageMoveResponse_`: the envelope `{ data: LifecycleStageMoveResponse, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
209
214
 
@@ -247,6 +252,10 @@ yet, which is common for Suspects-stage contacts), and records the same
247
252
  audit trail the in-app Move-Stage dialog's contact mode does. Returns no
248
253
  contact PII (see the module docstring) — only the status transition.
249
254
 
255
+ A move to `customers` of a contact with no company, or whose company has no
256
+ subscription, is a 409 (`detail.code` 'customers_without_subscription')
257
+ unless `confirm_without_subscription: true` is sent (R3-31).
258
+
250
259
  **Input**
251
260
 
252
261
  | Field | Type | Required | Description |
@@ -259,7 +268,8 @@ Body fields (`LifecycleStageMoveRequest`):
259
268
  | Field | Type | Required | Description |
260
269
  |---|---|---|---|
261
270
  | `body.target_slug` | `string` | yes | Destination lifecycle slug, e.g. 'suspects', 'leads', 'trials', 'customers', 'churned'. Case and surrounding whitespace are ignored, and a stage's display name is accepted too. |
262
- | `body.dry_run` | `boolean` | no | Company moves only: run every check the move runs (company exists, stage known, Customers/Churned guards) and return the would-be transition without writing anything. Ignored for contact moves. default `false` |
271
+ | `body.confirm_without_subscription` | `boolean` | no | Confirm a move to Customers of a company with no subscription (or a contact with no company or whose company has none). Without it such a move is refused with 409 and detail.code 'customers_without_subscription'. default `false` |
272
+ | `body.dry_run` | `boolean` | no | Run every check the move runs (record exists, stage known, Customers/Churned guards, the no-subscription confirmation) and return the would-be transition without writing anything. default `false` |
263
273
 
264
274
  **Returns** `ApiResponse_LifecycleStageMoveResponse_`: the envelope `{ data: LifecycleStageMoveResponse, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
265
275
 
package/docs/api/seo.d.ts CHANGED
@@ -859,7 +859,7 @@ export interface SeoResearchKeywordsResponse {
859
859
  * refused with a 422 if it carries a scheme or a path.
860
860
  */
861
861
  export interface SeoSaveTrackedKeywordsRequest {
862
- cadence?: "daily" | "weekly";
862
+ cadence?: "daily" | "weekly" | "manual";
863
863
  domain: string;
864
864
  keywords: Array<SeoTrackKeywordItem>;
865
865
  language_code?: string;
package/docs/api/seo.md CHANGED
@@ -1025,7 +1025,7 @@ Body fields (`SeoSaveTrackedKeywordsRequest`):
1025
1025
  |---|---|---|---|
1026
1026
  | `body.domain` | `string` | yes | min length 3, max length 255 |
1027
1027
  | `body.keywords` | `Array<SeoTrackKeywordItem>` | yes | min items 1, max items 100 |
1028
- | `body.cadence` | `"daily" \| "weekly"` | no | default `"daily"` |
1028
+ | `body.cadence` | `"daily" \| "weekly" \| "manual"` | no | default `"daily"` |
1029
1029
  | `body.language_code` | `string` | no | default `"en"`, max length 10 |
1030
1030
  | `body.location_code` | `integer` | no | default `2840` |
1031
1031
 
@@ -193,6 +193,14 @@ Send an `Idempotency-Key` header as well for the app-wide guard.
193
193
  Every execution in the batch is scoped to the caller's org before it is
194
194
  touched; ids belonging to another tenant are simply not found.
195
195
 
196
+ A restart runs each workflow as it is NOW. When one has record steps or a
197
+ record trigger, the key needs the object scopes they exercise (403
198
+ ``missing_scopes`` refuses the whole batch, nothing restarts), and only the
199
+ workflow's owner or a graph8 admin may restart it: for any other member that
200
+ item is reported in ``failed`` with ``owner_or_admin_required`` while the
201
+ rest of the batch goes ahead. When graph8 cannot confirm who is an admin,
202
+ that item is refused, never guessed, and also reported in ``failed``.
203
+
196
204
  **Input**
197
205
 
198
206
  | Field | Type | Required | Description |
@@ -319,6 +327,13 @@ const result = await g8.api.workflows.createWorkbench({ body: {} });
319
327
  Create a new workflow. Pins ``org_id`` and ``runtime_type='workflow'``
320
328
  server-side - the body cannot override either.
321
329
 
330
+ The workflow's OWNER is the authenticated caller, never a body field: a
331
+ body ``created_by`` is dropped (see ``voice_owner_headers``). Record steps
332
+ and record triggers run with the owner's record access, so the key must hold
333
+ the object scopes they exercise (403 ``missing_scopes``). A node or trigger
334
+ config that carries the same key in snake_case and camelCase with values
335
+ that disagree is refused (422 ``conflicting_node_keys``): keep one spelling.
336
+
322
337
  Translates the public ``config`` field to voice's internal
323
338
  ``skill_config`` before forwarding (see module docstring).
324
339
 
@@ -573,6 +588,14 @@ const result = await g8.api.workflows.diffSkillVersions({ path: { action_id: "id
573
588
 
574
589
  Trigger a workflow run. Returns ``execution_id`` for polling.
575
590
 
591
+ A workflow with record steps or a record trigger runs them with its OWNER's
592
+ record access, and this run's input feeds them: the key must hold the object
593
+ scopes they exercise (403 ``missing_scopes``) and its member must own the
594
+ workflow or administer the org (403 ``owner_or_admin_required``, from the
595
+ workflow service, which receives the member as the verified identity). The
596
+ saved workflow is read before the run so that check is never skipped: when
597
+ it cannot be read, the answer is ``502`` and nothing runs.
598
+
576
599
  Pins ``org_id`` server-side; the caller cannot override which org's
577
600
  execution row is created. ``triggered_by`` defaults to the caller's
578
601
  user id when not supplied.
@@ -1908,6 +1931,14 @@ a paused run instead, use `POST /workflows/executions/{id}/resume`.
1908
1931
  The org is forwarded and voice scopes the lookup by it, so one tenant
1909
1932
  cannot restart another's run.
1910
1933
 
1934
+ A restart runs the workflow as it is NOW, with the original or new input.
1935
+ When it has record steps or a record trigger, the key needs the object
1936
+ scopes they exercise (403 ``missing_scopes``), and only the workflow's
1937
+ owner or a graph8 admin may restart it, with reused or new input (403
1938
+ ``owner_or_admin_required``). When graph8 cannot confirm who is an admin the
1939
+ restart is refused, never guessed: the workflow service answers 503, which
1940
+ reaches the caller as ``502`` like its other upstream failures; retry later.
1941
+
1911
1942
  **Input**
1912
1943
 
1913
1944
  | Field | Type | Required | Description |
@@ -1941,7 +1972,14 @@ const result = await g8.api.workflows.restartExecution({ path: { execution_id: "
1941
1972
 
1942
1973
  SPENDS NOTHING. Publishes the old snapshot as a NEW version, live for the
1943
1974
  next run - agents and workflows using the skill pick it up. Append-only, so
1944
- the restore can itself be rolled back. Routine-managed skills refuse (403).
1975
+ the restore can itself be rolled back. Routine-managed skills refuse (403). A
1976
+ restored graph with record steps or a record trigger needs the same object
1977
+ scopes as a create or an update (403 ``missing_scopes``), a restored graph
1978
+ whose snake_case and camelCase node keys disagree is refused (422
1979
+ ``conflicting_node_keys``), and a restore that changes such a workflow's
1980
+ graph is refused (403 ``owner_or_admin_required``) unless the key's member
1981
+ owns the workflow or administers the org. The version's graph is read first
1982
+ to run those checks: 404 when it cannot be found (unknown skill or version).
1945
1983
 
1946
1984
  **Input**
1947
1985
 
@@ -2250,7 +2288,13 @@ const result = await g8.api.workflows.updateSkillTestCase({ path: { action_id: "
2250
2288
  - ★ Hand-written: [`g8.workflows.update()`](../sdk-clients.md#g8-workflows-update)
2251
2289
 
2252
2290
  Update a workflow. The voice update endpoint takes ``org_id`` as a
2253
- query param and the partial body in JSON, so we forward both.
2291
+ query param and the partial body in JSON, so we forward both. A graph with
2292
+ record steps or a record trigger needs the object scopes they exercise
2293
+ (403 ``missing_scopes``), like create, and a node or trigger config whose
2294
+ snake_case and camelCase keys disagree is refused (422
2295
+ ``conflicting_node_keys``). On a workflow with record steps or a record
2296
+ trigger, only its owner or a graph8 admin may change what it runs (403
2297
+ ``owner_or_admin_required``); its name and description stay editable.
2254
2298
 
2255
2299
  Translates the public ``config`` field to voice's internal
2256
2300
  ``skill_config`` before forwarding (see module docstring).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graph8/sdk",
3
- "version": "0.357.0",
3
+ "version": "0.358.0",
4
4
  "description": "graph8 SDK - CRM, enrichment, sequences, campaigns, and tracking for B2B",
5
5
  "license": "MIT",
6
6
  "author": "graph8 <support@graph8.com> (https://graph8.com)",