@graph8/sdk 0.295.2 → 0.302.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/docs/api/seo.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  # `g8.api.seo`: SEO
4
4
 
5
- 11 operations (5 read, 2 write, 4 billable).
5
+ 14 operations (8 read, 2 write, 4 billable).
6
6
 
7
7
  No hand-written client covers this area. Call it through `g8.api.seo.*` as shown below, or by operationId with `g8.api.call(operationId, input)`.
8
8
 
@@ -27,7 +27,10 @@ Exact TypeScript types for every operation on this page, and every schema they u
27
27
  | [`getSeoDomainBacklinks`](#op-getseodomainbacklinks) | `GET /api/v1/seo/domains/{domain}/backlinks` | billable | `intent:run` | Get Seo Domain Backlinks |
28
28
  | [`getSeoDomainOverview`](#op-getseodomainoverview) | `GET /api/v1/seo/domains/{domain}/overview` | billable | `intent:run` | Get Seo Domain Overview |
29
29
  | [`getSeoRankHistory`](#op-getseorankhistory) | `GET /api/v1/seo/rank-tracking/{keyword_id}/history` | read | `intent:read` | Get Seo Rank History |
30
+ | [`getSeoTrackedDomain`](#op-getseotrackeddomain) | `GET /api/v1/seo/domains/tracked/{domain}` | read | `intent:read` | Get Seo Tracked Domain |
30
31
  | [`listSeoAudits`](#op-listseoaudits) | `GET /api/v1/seo/audits` | read | `intent:read` | List Seo Audits |
32
+ | [`listSeoDomainPages`](#op-listseodomainpages) | `GET /api/v1/seo/domains/tracked/{domain}/pages` | read | `intent:read` | List Seo Domain Pages |
33
+ | [`listSeoTrackedDomains`](#op-listseotrackeddomains) | `GET /api/v1/seo/domains/tracked` | read | `intent:read` | List Seo Tracked Domains |
31
34
  | [`listSeoTrackedKeywords`](#op-listseotrackedkeywords) | `GET /api/v1/seo/rank-tracking` | read | `intent:read` | List Seo Tracked Keywords |
32
35
  | [`removeSeoTrackedKeywords`](#op-removeseotrackedkeywords) | `POST /api/v1/seo/rank-tracking/keywords/remove` | write | `intent:write` | Remove Seo Tracked Keywords |
33
36
  | [`researchSeoKeywords`](#op-researchseokeywords) | `POST /api/v1/seo/keywords/research` | billable | `intent:run` | Research Seo Keywords |
@@ -258,6 +261,59 @@ const result = await g8.api.seo.getSeoRankHistory({ path: { keyword_id: "0000000
258
261
 
259
262
  ---
260
263
 
264
+ <a id="op-getseotrackeddomain"></a>
265
+
266
+ ### `g8.api.seo.getSeoTrackedDomain(input)`
267
+
268
+ **Get Seo Tracked Domain**
269
+
270
+ - HTTP: `GET /api/v1/seo/domains/tracked/{domain}`
271
+ - operationId: `get_seo_tracked_domain_seo_domains_tracked__domain__get` (also callable as `g8.api.call("get_seo_tracked_domain_seo_domains_tracked__domain__get", input)`)
272
+ - Tier: `read`: reads data; safe to call and to retry
273
+ - API-key scope: `intent:read`
274
+
275
+ SPENDS NOTHING. One saved domain's snapshot: overview, top keywords, top pages, backlinks.
276
+
277
+ Rendered from what the app last stored; it never calls the provider. 404
278
+ for a domain this organisation does not track. `snapshot_at` says how
279
+ old the snapshot is; it is null until the domain is first refreshed.
280
+
281
+ **Input**
282
+
283
+ | Field | Type | Required | Description |
284
+ |---|---|---|---|
285
+ | `path.domain` | `string` | yes | A saved domain from `GET /seo/domains/tracked`. |
286
+
287
+ **Returns** `ApiResponse_SeoTrackedDomainDetail_`: the envelope `{ data: SeoTrackedDomainDetail, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
288
+
289
+ Other envelope fields: `pagination` (PaginationMeta).
290
+
291
+ `SeoTrackedDomainDetail` fields:
292
+
293
+ | Field | Type | Required | Description |
294
+ |---|---|---|---|
295
+ | `domain` | `string` | yes | |
296
+ | `kind` | `"own" \| "competitor"` | yes | |
297
+ | `backlinks` | `SeoBacklinksOverview \| null` | no | |
298
+ | `change_30d` | `SeoDomainChange \| null` | no | |
299
+ | `data_freshness` | `string` | no | default `"labs-30-90d"` |
300
+ | `is_primary` | `boolean` | no | default `false` |
301
+ | `metrics` | `SeoTrackedDomainMetrics \| null` | no | |
302
+ | `name` | `string \| null` | no | |
303
+ | `overview` | `Record<string, unknown> \| null` | no | |
304
+ | `refreshed` | `boolean` | no | default `false` |
305
+ | `snapshot_at` | `string (date-time) \| null` | no | |
306
+ | `top_keywords` | `Array<Record<string, unknown>>` | no | default `[]` |
307
+ | `top_pages` | `Array<Record<string, unknown>>` | no | default `[]` |
308
+
309
+ **Example**
310
+
311
+ ```ts
312
+ const result = await g8.api.seo.getSeoTrackedDomain({ path: { domain: "acme.com" } });
313
+ ```
314
+
315
+ ---
316
+
261
317
  <a id="op-listseoaudits"></a>
262
318
 
263
319
  ### `g8.api.seo.listSeoAudits(input?)`
@@ -306,6 +362,102 @@ const result = await g8.api.seo.listSeoAudits();
306
362
 
307
363
  ---
308
364
 
365
+ <a id="op-listseodomainpages"></a>
366
+
367
+ ### `g8.api.seo.listSeoDomainPages(input)`
368
+
369
+ **List Seo Domain Pages**
370
+
371
+ - HTTP: `GET /api/v1/seo/domains/tracked/{domain}/pages`
372
+ - operationId: `list_seo_domain_pages_seo_domains_tracked__domain__pages_get` (also callable as `g8.api.call("list_seo_domain_pages_seo_domains_tracked__domain__pages_get", input)`)
373
+ - Tier: `read`: reads data; safe to call and to retry
374
+ - API-key scope: `intent:read`
375
+
376
+ SPENDS NOTHING. The saved ranking pages of a tracked domain, paged and sorted.
377
+
378
+ Read only: it never calls the provider. `refreshed_at` is null when the
379
+ pages were never fetched (fetching them is a paid action in the app).
380
+ An unknown sort column is a 422 naming the allowed ones.
381
+
382
+ **Input**
383
+
384
+ | Field | Type | Required | Description |
385
+ |---|---|---|---|
386
+ | `path.domain` | `string` | yes | A saved domain from `GET /seo/domains/tracked`. |
387
+ | `query.offset` | `integer` | no | Rows to skip (the saved pages are capped at 1,000). default `0` |
388
+ | `query.limit` | `integer` | no | Rows to return. default `50` |
389
+ | `query.sort` | `string` | no | Sort column: estimated_traffic, ranking_keywords_count, best_position, url, traffic_change_30d or audit_issues. default `"estimated_traffic"` |
390
+ | `query.order` | `"asc" \| "desc"` | no | default `"desc"` |
391
+ | `query.q` | `string \| null` | no | Only pages whose URL contains this text. |
392
+
393
+ **Returns** `ApiResponse_SeoDomainPages_`: the envelope `{ data: SeoDomainPages, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
394
+
395
+ Other envelope fields: `pagination` (PaginationMeta).
396
+
397
+ `SeoDomainPages` fields:
398
+
399
+ | Field | Type | Required | Description |
400
+ |---|---|---|---|
401
+ | `cap` | `integer` | yes | |
402
+ | `rows` | `Array<SeoDomainPage>` | yes | |
403
+ | `total` | `integer` | yes | |
404
+ | `audit_completed_at` | `string (date-time) \| null` | no | |
405
+ | `refreshed_at` | `string (date-time) \| null` | no | |
406
+
407
+ **Example**
408
+
409
+ ```ts
410
+ const result = await g8.api.seo.listSeoDomainPages({ path: { domain: "acme.com" } });
411
+ ```
412
+
413
+ ---
414
+
415
+ <a id="op-listseotrackeddomains"></a>
416
+
417
+ ### `g8.api.seo.listSeoTrackedDomains(input?)`
418
+
419
+ **List Seo Tracked Domains**
420
+
421
+ - HTTP: `GET /api/v1/seo/domains/tracked`
422
+ - operationId: `list_seo_tracked_domains_seo_domains_tracked_get` (also callable as `g8.api.call("list_seo_tracked_domains_seo_domains_tracked_get", input)`)
423
+ - Tier: `read`: reads data; safe to call and to retry
424
+ - API-key scope: `intent:read`
425
+
426
+ SPENDS NOTHING. The SEO overview: every saved domain with its last snapshot.
427
+
428
+ Own domains first (the primary one first), then the Radar competitors
429
+ shown beside them, each with its saved metrics and 30-day change. Also
430
+ carries what each PAID refresh would cost (`refresh_credits`,
431
+ `pages_max_credits`, `page_keywords_credits`), so a caller can quote a
432
+ price without spending anything. An organisation whose SEO storage is
433
+ still provisioning gets an empty list, matching the app.
434
+
435
+ **Input**: none.
436
+
437
+ **Returns** `ApiResponse_SeoTrackedDomains_`: the envelope `{ data: SeoTrackedDomains, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
438
+
439
+ Other envelope fields: `pagination` (PaginationMeta).
440
+
441
+ `SeoTrackedDomains` fields:
442
+
443
+ | Field | Type | Required | Description |
444
+ |---|---|---|---|
445
+ | `domains` | `Array<SeoTrackedDomain>` | yes | |
446
+ | `max_own_domains` | `integer` | yes | |
447
+ | `page_keywords_credits` | `integer` | yes | |
448
+ | `page_keywords_limit` | `integer` | yes | |
449
+ | `pages_cap` | `integer` | yes | |
450
+ | `pages_max_credits` | `integer` | yes | |
451
+ | `refresh_credits` | `integer` | yes | |
452
+
453
+ **Example**
454
+
455
+ ```ts
456
+ const result = await g8.api.seo.listSeoTrackedDomains();
457
+ ```
458
+
459
+ ---
460
+
309
461
  <a id="op-listseotrackedkeywords"></a>
310
462
 
311
463
  ### `g8.api.seo.listSeoTrackedKeywords(input?)`
@@ -621,6 +773,34 @@ Mirrors `AuditStateDTO` - the plain-language, recovery-oriented view of where an
621
773
  | `recovery` | `string` | yes | Plain-language, safe next step (may be empty) |
622
774
  | `diagnostic` | `string \| null` | no | Secondary technical detail (raw provider text) |
623
775
 
776
+ <a id="type-seodomainchange"></a>
777
+
778
+ ### `SeoDomainChange`
779
+
780
+ Mirrors `DomainChangeDTO`: the current snapshot against the one nearest 30 days back. `traffic_pct` is null when the baseline traffic was zero.
781
+
782
+ | Field | Type | Required | Description |
783
+ |---|---|---|---|
784
+ | `keywords_delta` | `integer \| null` | no | |
785
+ | `since` | `string \| null` | no | |
786
+ | `traffic_pct` | `number \| null` | no | |
787
+
788
+ <a id="type-seodomainpage"></a>
789
+
790
+ ### `SeoDomainPage`
791
+
792
+ Mirrors `DomainPageDTO`.
793
+
794
+ | Field | Type | Required | Description |
795
+ |---|---|---|---|
796
+ | `estimated_traffic` | `number` | yes | |
797
+ | `ranking_keywords_count` | `integer` | yes | |
798
+ | `url` | `string` | yes | |
799
+ | `audit_issues` | `integer \| null` | no | |
800
+ | `best_position` | `integer \| null` | no | |
801
+ | `top_keyword` | `string \| null` | no | |
802
+ | `traffic_change_30d` | `number \| null` | no | |
803
+
624
804
  <a id="type-seokeywordrow"></a>
625
805
 
626
806
  ### `SeoKeywordRow`
@@ -658,3 +838,33 @@ Mirrors `TrackKeywordItem`.
658
838
  |---|---|---|---|
659
839
  | `keyword` | `string` | yes | min length 1, max length 500 |
660
840
  | `search_volume` | `integer \| null` | no | |
841
+
842
+ <a id="type-seotrackeddomain"></a>
843
+
844
+ ### `SeoTrackedDomain`
845
+
846
+ Mirrors `TrackedDomainDTO`. `kind` is `own` for the organisation's own sites and `competitor` for the Radar competitors shown beside them.
847
+
848
+ | Field | Type | Required | Description |
849
+ |---|---|---|---|
850
+ | `domain` | `string` | yes | |
851
+ | `kind` | `"own" \| "competitor"` | yes | |
852
+ | `change_30d` | `SeoDomainChange \| null` | no | |
853
+ | `is_primary` | `boolean` | no | default `false` |
854
+ | `metrics` | `SeoTrackedDomainMetrics \| null` | no | |
855
+ | `name` | `string \| null` | no | |
856
+ | `snapshot_at` | `string (date-time) \| null` | no | |
857
+
858
+ <a id="type-seotrackeddomainmetrics"></a>
859
+
860
+ ### `SeoTrackedDomainMetrics`
861
+
862
+ Mirrors `TrackedDomainMetricsDTO`.
863
+
864
+ | Field | Type | Required | Description |
865
+ |---|---|---|---|
866
+ | `authority_score` | `number \| null` | no | |
867
+ | `estimated_traffic` | `number \| null` | no | |
868
+ | `organic_keywords` | `integer \| null` | no | |
869
+ | `referring_domains` | `number \| null` | no | |
870
+ | `top3_positions` | `integer \| null` | no | |
@@ -1097,7 +1097,7 @@ export interface WorkOperations {
1097
1097
  };
1098
1098
  }
1099
1099
 
1100
- // 122 schemas referenced above (the same as G8Contract.<Name>).
1100
+ // 123 schemas referenced above (the same as G8Contract.<Name>).
1101
1101
 
1102
1102
  export interface ApiResponse_WorkActivityPage_ {
1103
1103
  data: WorkActivityPage;
@@ -1558,6 +1558,22 @@ export interface WorkChannelDeleteRequest {
1558
1558
  confirmationName: string;
1559
1559
  }
1560
1560
 
1561
+ /**
1562
+ * A channel's icon: a glyph on a color, an emoji, or an uploaded image.
1563
+ *
1564
+ * `glyph` and `color` are ids from the client's curated sets, never raw CSS
1565
+ * or SVG, so nothing a member stores can inject markup or styles into
1566
+ * another member's sidebar. An image is a Work attachment id, never a URL:
1567
+ * readability is re-checked on every read (`readable_attachment_ids`).
1568
+ */
1569
+ export interface WorkChannelIcon {
1570
+ attachmentId?: string | null;
1571
+ color?: string | null;
1572
+ emoji?: string | null;
1573
+ glyph?: string | null;
1574
+ type: "glyph" | "emoji" | "image";
1575
+ }
1576
+
1561
1577
  /** The channels this credential may read. */
1562
1578
  export interface WorkChannelList {
1563
1579
  /** Channels visible to the caller */
@@ -1591,6 +1607,7 @@ export interface WorkChannelSettingsRequest {
1591
1607
  confirmAgentAccess?: boolean;
1592
1608
  description?: string | null;
1593
1609
  displayName?: string | null;
1610
+ icon?: WorkChannelIcon | null;
1594
1611
  memberUserIds?: Array<string>;
1595
1612
  participantAgentIds?: Array<string>;
1596
1613
  visibility?: ("open" | "private") | null;
package/docs/api/work.md CHANGED
@@ -2791,6 +2791,7 @@ Body fields (`WorkChannelSettingsRequest`):
2791
2791
  | `body.confirmAgentAccess` | `boolean` | no | default `false` |
2792
2792
  | `body.description` | `string \| null` | no | max length 1000 |
2793
2793
  | `body.displayName` | `string \| null` | no | max length 255 |
2794
+ | `body.icon` | `WorkChannelIcon \| null` | no | |
2794
2795
  | `body.memberUserIds` | `Array<string>` | no | max items 100 |
2795
2796
  | `body.participantAgentIds` | `Array<string>` | no | max items 32 |
2796
2797
  | `body.visibility` | `"open" \| "private" \| null` | no | |
@@ -2983,6 +2984,20 @@ One Work channel as the room stores it.
2983
2984
  | `system` | `boolean \| null` | no | True for a built-in channel (`#work`, `#signals`) |
2984
2985
  | `visibility` | `string \| null` | no | `open` (self-serve joinable) or `private` (invite only) |
2985
2986
 
2987
+ <a id="type-workchannelicon"></a>
2988
+
2989
+ ### `WorkChannelIcon`
2990
+
2991
+ A channel's icon: a glyph on a color, an emoji, or an uploaded image. `glyph` and `color` are ids from the client's curated sets, never raw CSS or SVG, so nothing a member stores can inject markup or styles into another member's sidebar. An image is a Work attachment id, never a URL: readability is re-checked on every read (`readable_attachment_ids`).
2992
+
2993
+ | Field | Type | Required | Description |
2994
+ |---|---|---|---|
2995
+ | `type` | `"glyph" \| "emoji" \| "image"` | yes | |
2996
+ | `attachmentId` | `string \| null` | no | pattern `^[A-Za-z0-9-]{1,64}$` |
2997
+ | `color` | `string \| null` | no | pattern `^[a-z0-9-]{1,32}$` |
2998
+ | `emoji` | `string \| null` | no | min length 1, max length 16 |
2999
+ | `glyph` | `string \| null` | no | pattern `^[a-z0-9-]{1,40}$` |
3000
+
2986
3001
  <a id="type-workevent"></a>
2987
3002
 
2988
3003
  ### `WorkEvent`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graph8/sdk",
3
- "version": "0.295.2",
3
+ "version": "0.302.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)",