@graph8/sdk 0.251.0 → 0.262.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 (350) hide show
  1. package/README.md +9 -2
  2. package/dist/cli.js +216 -0
  3. package/dist/index.d.mts +105 -7
  4. package/dist/index.d.ts +105 -7
  5. package/dist/index.js +44 -3
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.mjs +44 -3
  8. package/dist/index.mjs.map +1 -1
  9. package/dist/react.d.mts +103 -7
  10. package/dist/react.d.ts +103 -7
  11. package/dist/react.js +62 -11
  12. package/dist/react.js.map +1 -1
  13. package/dist/react.mjs +53 -12
  14. package/dist/react.mjs.map +1 -1
  15. package/dist/types/README.md +7 -0
  16. package/dist/types/agency.d.ts +20 -0
  17. package/dist/types/agentSetup.d.ts +57 -0
  18. package/dist/types/api.d.ts +127 -0
  19. package/dist/types/appClient.d.ts +99 -0
  20. package/dist/types/appPlatform.d.ts +269 -0
  21. package/dist/types/appTokens.d.ts +125 -0
  22. package/dist/types/apps.d.ts +130 -0
  23. package/dist/types/audiences.d.ts +88 -0
  24. package/dist/types/calendar.d.ts +55 -0
  25. package/dist/types/campaigns.d.ts +61 -0
  26. package/dist/types/chat.d.ts +35 -0
  27. package/dist/types/cli.d.ts +14 -0
  28. package/dist/types/companies.d.ts +123 -0
  29. package/dist/types/contacts.d.ts +200 -0
  30. package/dist/types/copilot.d.ts +31 -0
  31. package/dist/types/core.d.ts +1052 -0
  32. package/dist/types/deals.d.ts +215 -0
  33. package/dist/types/enrich.d.ts +51 -0
  34. package/dist/types/fields.d.ts +84 -0
  35. package/dist/types/forms.d.ts +16 -0
  36. package/dist/types/http.d.ts +141 -0
  37. package/dist/types/inbox.d.ts +123 -0
  38. package/dist/types/index.d.ts +63 -0
  39. package/dist/types/intent.d.ts +196 -0
  40. package/dist/types/lists.d.ts +44 -0
  41. package/dist/types/mailboxes.d.ts +240 -0
  42. package/dist/types/marketplace.d.ts +62 -0
  43. package/dist/types/meetings.d.ts +70 -0
  44. package/dist/types/newsletter.d.ts +212 -0
  45. package/dist/types/notes.d.ts +57 -0
  46. package/dist/types/objects.d.ts +281 -0
  47. package/dist/types/pipelines.d.ts +135 -0
  48. package/dist/types/quotes.d.ts +143 -0
  49. package/dist/types/react.d.ts +978 -0
  50. package/dist/types/search.d.ts +99 -0
  51. package/dist/types/sequences.d.ts +255 -0
  52. package/dist/types/signals.d.ts +28 -0
  53. package/dist/types/skills.d.ts +176 -0
  54. package/dist/types/snippet.d.ts +24 -0
  55. package/dist/types/studio.d.ts +161 -0
  56. package/dist/types/tasks.d.ts +101 -0
  57. package/dist/types/types.d.ts +45 -0
  58. package/dist/types/utils.d.ts +21 -0
  59. package/dist/types/version.d.ts +10 -0
  60. package/dist/types/visitors.d.ts +29 -0
  61. package/dist/types/voice.d.ts +304 -0
  62. package/dist/types/webhooks.d.ts +71 -0
  63. package/dist/types/workflows.d.ts +229 -0
  64. package/docs/agents.md +748 -0
  65. package/docs/api/README.md +165 -0
  66. package/docs/api/accounts.d.ts +396 -0
  67. package/docs/api/accounts.md +644 -0
  68. package/docs/api/adCampaigns.d.ts +707 -0
  69. package/docs/api/adCampaigns.md +1091 -0
  70. package/docs/api/adCreatives.d.ts +996 -0
  71. package/docs/api/adCreatives.md +1708 -0
  72. package/docs/api/agency.d.ts +556 -0
  73. package/docs/api/agency.md +845 -0
  74. package/docs/api/agent.d.ts +330 -0
  75. package/docs/api/agent.md +514 -0
  76. package/docs/api/agents.d.ts +1622 -0
  77. package/docs/api/agents.md +2860 -0
  78. package/docs/api/aiInbox.d.ts +1984 -0
  79. package/docs/api/aiInbox.md +3490 -0
  80. package/docs/api/analytics.d.ts +1273 -0
  81. package/docs/api/analytics.md +2095 -0
  82. package/docs/api/apiKeys.d.ts +252 -0
  83. package/docs/api/apiKeys.md +318 -0
  84. package/docs/api/appDeployments.d.ts +236 -0
  85. package/docs/api/appDeployments.md +471 -0
  86. package/docs/api/appDomains.d.ts +171 -0
  87. package/docs/api/appDomains.md +281 -0
  88. package/docs/api/appLogs.d.ts +120 -0
  89. package/docs/api/appLogs.md +159 -0
  90. package/docs/api/appObjects.d.ts +415 -0
  91. package/docs/api/appObjects.md +568 -0
  92. package/docs/api/appPages.d.ts +557 -0
  93. package/docs/api/appPages.md +796 -0
  94. package/docs/api/appPlatformTokens.d.ts +123 -0
  95. package/docs/api/appPlatformTokens.md +172 -0
  96. package/docs/api/appointments.d.ts +2361 -0
  97. package/docs/api/appointments.md +3917 -0
  98. package/docs/api/apps.d.ts +822 -0
  99. package/docs/api/apps.md +1342 -0
  100. package/docs/api/assertUpsert.d.ts +286 -0
  101. package/docs/api/assertUpsert.md +370 -0
  102. package/docs/api/audienceSyncs.d.ts +259 -0
  103. package/docs/api/audienceSyncs.md +395 -0
  104. package/docs/api/brandKit.d.ts +686 -0
  105. package/docs/api/brandKit.md +1133 -0
  106. package/docs/api/bugReports.d.ts +181 -0
  107. package/docs/api/bugReports.md +268 -0
  108. package/docs/api/by-path.md +3260 -0
  109. package/docs/api/calendarInvites.d.ts +117 -0
  110. package/docs/api/calendarInvites.md +148 -0
  111. package/docs/api/campaignWorkflows.d.ts +152 -0
  112. package/docs/api/campaignWorkflows.md +200 -0
  113. package/docs/api/campaigns.d.ts +721 -0
  114. package/docs/api/campaigns.md +1236 -0
  115. package/docs/api/channels.d.ts +171 -0
  116. package/docs/api/channels.md +235 -0
  117. package/docs/api/cliCampaigns.d.ts +205 -0
  118. package/docs/api/cliCampaigns.md +256 -0
  119. package/docs/api/cliPipelines.d.ts +324 -0
  120. package/docs/api/cliPipelines.md +562 -0
  121. package/docs/api/clickHouse.d.ts +115 -0
  122. package/docs/api/clickHouse.md +138 -0
  123. package/docs/api/companies.d.ts +1636 -0
  124. package/docs/api/companies.md +2211 -0
  125. package/docs/api/companyIntelligence.d.ts +299 -0
  126. package/docs/api/companyIntelligence.md +488 -0
  127. package/docs/api/contacts.d.ts +2173 -0
  128. package/docs/api/contacts.md +3143 -0
  129. package/docs/api/content.d.ts +968 -0
  130. package/docs/api/content.md +1667 -0
  131. package/docs/api/contentGridSkills.d.ts +177 -0
  132. package/docs/api/contentGridSkills.md +271 -0
  133. package/docs/api/copilot.d.ts +1017 -0
  134. package/docs/api/copilot.md +1765 -0
  135. package/docs/api/crmSyncs.d.ts +215 -0
  136. package/docs/api/crmSyncs.md +301 -0
  137. package/docs/api/customerSuccess.d.ts +491 -0
  138. package/docs/api/customerSuccess.md +776 -0
  139. package/docs/api/deals.d.ts +1697 -0
  140. package/docs/api/deals.md +2436 -0
  141. package/docs/api/deliverability.d.ts +418 -0
  142. package/docs/api/deliverability.md +677 -0
  143. package/docs/api/desk.d.ts +1765 -0
  144. package/docs/api/desk.md +3007 -0
  145. package/docs/api/dialer.d.ts +1185 -0
  146. package/docs/api/dialer.md +2166 -0
  147. package/docs/api/dialerAnalytics.d.ts +187 -0
  148. package/docs/api/dialerAnalytics.md +257 -0
  149. package/docs/api/documents.d.ts +895 -0
  150. package/docs/api/documents.md +1440 -0
  151. package/docs/api/duplicates.d.ts +195 -0
  152. package/docs/api/duplicates.md +315 -0
  153. package/docs/api/eSign.d.ts +38 -0
  154. package/docs/api/eSign.md +54 -0
  155. package/docs/api/eSignature.d.ts +242 -0
  156. package/docs/api/eSignature.md +341 -0
  157. package/docs/api/enrichment.d.ts +3207 -0
  158. package/docs/api/enrichment.md +5225 -0
  159. package/docs/api/events.d.ts +115 -0
  160. package/docs/api/events.md +105 -0
  161. package/docs/api/fields.d.ts +482 -0
  162. package/docs/api/fields.md +566 -0
  163. package/docs/api/forms.d.ts +1012 -0
  164. package/docs/api/forms.md +1542 -0
  165. package/docs/api/gtmCampaigns.d.ts +662 -0
  166. package/docs/api/gtmCampaigns.md +1044 -0
  167. package/docs/api/gtmContext.d.ts +1187 -0
  168. package/docs/api/gtmContext.md +2112 -0
  169. package/docs/api/gtmDeliverability.d.ts +60 -0
  170. package/docs/api/gtmDeliverability.md +63 -0
  171. package/docs/api/gtmKnowledgeBase.d.ts +76 -0
  172. package/docs/api/gtmKnowledgeBase.md +91 -0
  173. package/docs/api/gtmLaunchHelpers.d.ts +123 -0
  174. package/docs/api/gtmLaunchHelpers.md +148 -0
  175. package/docs/api/gtmLibrary.d.ts +448 -0
  176. package/docs/api/gtmLibrary.md +780 -0
  177. package/docs/api/health.d.ts +39 -0
  178. package/docs/api/health.md +58 -0
  179. package/docs/api/imageLibrary.d.ts +341 -0
  180. package/docs/api/imageLibrary.md +569 -0
  181. package/docs/api/imports.d.ts +157 -0
  182. package/docs/api/imports.md +174 -0
  183. package/docs/api/inbox.d.ts +709 -0
  184. package/docs/api/inbox.md +1067 -0
  185. package/docs/api/install.d.ts +213 -0
  186. package/docs/api/install.md +317 -0
  187. package/docs/api/installedApps.d.ts +131 -0
  188. package/docs/api/installedApps.md +241 -0
  189. package/docs/api/integrationStatus.d.ts +142 -0
  190. package/docs/api/integrationStatus.md +205 -0
  191. package/docs/api/integrations.d.ts +2327 -0
  192. package/docs/api/integrations.md +3791 -0
  193. package/docs/api/intent.d.ts +482 -0
  194. package/docs/api/intent.md +858 -0
  195. package/docs/api/knowledge.d.ts +501 -0
  196. package/docs/api/knowledge.md +843 -0
  197. package/docs/api/knowledgeBase.d.ts +84 -0
  198. package/docs/api/knowledgeBase.md +96 -0
  199. package/docs/api/landingPages.d.ts +1411 -0
  200. package/docs/api/landingPages.md +2488 -0
  201. package/docs/api/leads.d.ts +133 -0
  202. package/docs/api/leads.md +180 -0
  203. package/docs/api/library.d.ts +217 -0
  204. package/docs/api/library.md +338 -0
  205. package/docs/api/linkedIn.d.ts +227 -0
  206. package/docs/api/linkedIn.md +289 -0
  207. package/docs/api/linkedInOutreach.d.ts +727 -0
  208. package/docs/api/linkedInOutreach.md +990 -0
  209. package/docs/api/lists.d.ts +1106 -0
  210. package/docs/api/lists.md +1609 -0
  211. package/docs/api/logs.d.ts +71 -0
  212. package/docs/api/logs.md +70 -0
  213. package/docs/api/mailboxes.d.ts +1050 -0
  214. package/docs/api/mailboxes.md +1690 -0
  215. package/docs/api/marketingIntelligence.d.ts +256 -0
  216. package/docs/api/marketingIntelligence.md +454 -0
  217. package/docs/api/marketplace.d.ts +3173 -0
  218. package/docs/api/marketplace.md +5953 -0
  219. package/docs/api/mcp.d.ts +69 -0
  220. package/docs/api/mcp.md +69 -0
  221. package/docs/api/me.d.ts +54 -0
  222. package/docs/api/me.md +56 -0
  223. package/docs/api/meetings.d.ts +539 -0
  224. package/docs/api/meetings.md +747 -0
  225. package/docs/api/newsletter.d.ts +1613 -0
  226. package/docs/api/newsletter.md +2746 -0
  227. package/docs/api/notes.d.ts +517 -0
  228. package/docs/api/notes.md +888 -0
  229. package/docs/api/notifications.d.ts +94 -0
  230. package/docs/api/notifications.md +105 -0
  231. package/docs/api/objects.d.ts +621 -0
  232. package/docs/api/objects.md +1098 -0
  233. package/docs/api/openSearch.d.ts +234 -0
  234. package/docs/api/openSearch.md +297 -0
  235. package/docs/api/ops.d.ts +299 -0
  236. package/docs/api/ops.md +339 -0
  237. package/docs/api/orgGovernance.d.ts +393 -0
  238. package/docs/api/orgGovernance.md +623 -0
  239. package/docs/api/orgVideos.d.ts +184 -0
  240. package/docs/api/orgVideos.md +252 -0
  241. package/docs/api/organizationSettings.d.ts +626 -0
  242. package/docs/api/organizationSettings.md +911 -0
  243. package/docs/api/phoneNumbers.d.ts +484 -0
  244. package/docs/api/phoneNumbers.md +777 -0
  245. package/docs/api/profile.d.ts +329 -0
  246. package/docs/api/profile.md +540 -0
  247. package/docs/api/programmaticPages.d.ts +400 -0
  248. package/docs/api/programmaticPages.md +626 -0
  249. package/docs/api/providerDomains.d.ts +866 -0
  250. package/docs/api/providerDomains.md +1446 -0
  251. package/docs/api/providerUsage.d.ts +129 -0
  252. package/docs/api/providerUsage.md +186 -0
  253. package/docs/api/public.d.ts +69 -0
  254. package/docs/api/public.md +78 -0
  255. package/docs/api/publicCopilot.d.ts +67 -0
  256. package/docs/api/publicCopilot.md +80 -0
  257. package/docs/api/publicSignals.d.ts +66 -0
  258. package/docs/api/publicSignals.md +71 -0
  259. package/docs/api/publicVisitors.d.ts +97 -0
  260. package/docs/api/publicVisitors.md +118 -0
  261. package/docs/api/quotes.d.ts +1564 -0
  262. package/docs/api/quotes.md +2553 -0
  263. package/docs/api/radar.d.ts +808 -0
  264. package/docs/api/radar.md +1431 -0
  265. package/docs/api/radarReports.d.ts +208 -0
  266. package/docs/api/radarReports.md +306 -0
  267. package/docs/api/recordRoles.d.ts +143 -0
  268. package/docs/api/recordRoles.md +175 -0
  269. package/docs/api/repos.d.ts +146 -0
  270. package/docs/api/repos.md +211 -0
  271. package/docs/api/research.d.ts +295 -0
  272. package/docs/api/research.md +534 -0
  273. package/docs/api/revenue.d.ts +402 -0
  274. package/docs/api/revenue.md +608 -0
  275. package/docs/api/revenueAnalytics.d.ts +147 -0
  276. package/docs/api/revenueAnalytics.md +212 -0
  277. package/docs/api/revenueLifecycle.d.ts +207 -0
  278. package/docs/api/revenueLifecycle.md +274 -0
  279. package/docs/api/revenueRecords.d.ts +372 -0
  280. package/docs/api/revenueRecords.md +563 -0
  281. package/docs/api/roles.d.ts +431 -0
  282. package/docs/api/roles.md +812 -0
  283. package/docs/api/salesCoach.d.ts +877 -0
  284. package/docs/api/salesCoach.md +1540 -0
  285. package/docs/api/sandbox.d.ts +210 -0
  286. package/docs/api/sandbox.md +380 -0
  287. package/docs/api/scans.d.ts +104 -0
  288. package/docs/api/scans.md +136 -0
  289. package/docs/api/scheduleBuy.d.ts +293 -0
  290. package/docs/api/scheduleBuy.md +431 -0
  291. package/docs/api/scraping.d.ts +266 -0
  292. package/docs/api/scraping.md +383 -0
  293. package/docs/api/sdrAnalytics.d.ts +138 -0
  294. package/docs/api/sdrAnalytics.md +246 -0
  295. package/docs/api/search.d.ts +598 -0
  296. package/docs/api/search.md +866 -0
  297. package/docs/api/seo.d.ts +447 -0
  298. package/docs/api/seo.md +660 -0
  299. package/docs/api/sequenceLifecycle.d.ts +439 -0
  300. package/docs/api/sequenceLifecycle.md +513 -0
  301. package/docs/api/sequences.d.ts +1936 -0
  302. package/docs/api/sequences.md +3232 -0
  303. package/docs/api/settings.d.ts +448 -0
  304. package/docs/api/settings.md +731 -0
  305. package/docs/api/signals.d.ts +1441 -0
  306. package/docs/api/signals.md +2526 -0
  307. package/docs/api/signatures.d.ts +719 -0
  308. package/docs/api/signatures.md +1247 -0
  309. package/docs/api/skills.d.ts +230 -0
  310. package/docs/api/skills.md +466 -0
  311. package/docs/api/snippet.d.ts +85 -0
  312. package/docs/api/snippet.md +106 -0
  313. package/docs/api/socialPublishing.d.ts +824 -0
  314. package/docs/api/socialPublishing.md +1245 -0
  315. package/docs/api/studioDocuments.d.ts +244 -0
  316. package/docs/api/studioDocuments.md +348 -0
  317. package/docs/api/support.d.ts +90 -0
  318. package/docs/api/support.md +76 -0
  319. package/docs/api/suppressions.d.ts +241 -0
  320. package/docs/api/suppressions.md +343 -0
  321. package/docs/api/surveys.d.ts +847 -0
  322. package/docs/api/surveys.md +1223 -0
  323. package/docs/api/tasks.d.ts +813 -0
  324. package/docs/api/tasks.md +1344 -0
  325. package/docs/api/teamMembers.d.ts +668 -0
  326. package/docs/api/teamMembers.md +1040 -0
  327. package/docs/api/teams.d.ts +784 -0
  328. package/docs/api/teams.md +1395 -0
  329. package/docs/api/usage.d.ts +277 -0
  330. package/docs/api/usage.md +389 -0
  331. package/docs/api/visitors.d.ts +690 -0
  332. package/docs/api/visitors.md +1075 -0
  333. package/docs/api/voice.d.ts +4661 -0
  334. package/docs/api/voice.md +7905 -0
  335. package/docs/api/webAnalytics.d.ts +964 -0
  336. package/docs/api/webAnalytics.md +1452 -0
  337. package/docs/api/webChat.d.ts +1704 -0
  338. package/docs/api/webChat.md +2048 -0
  339. package/docs/api/webhooks.d.ts +251 -0
  340. package/docs/api/webhooks.md +386 -0
  341. package/docs/api/websiteEditor.d.ts +324 -0
  342. package/docs/api/websiteEditor.md +517 -0
  343. package/docs/api/work.d.ts +2298 -0
  344. package/docs/api/work.md +3096 -0
  345. package/docs/api/workbench.d.ts +2962 -0
  346. package/docs/api/workbench.md +4884 -0
  347. package/docs/api/workflows.d.ts +1218 -0
  348. package/docs/api/workflows.md +2302 -0
  349. package/docs/sdk-clients.md +4339 -0
  350. package/package.json +10 -3
@@ -0,0 +1,2526 @@
1
+ <!-- Generated by sdk/js/scripts/generate-agent-docs.ts from developer-contract/openapi.json. Regenerated on every build. -->
2
+
3
+ # `g8.api.signals`: Signals
4
+
5
+ 56 operations (23 read, 3 destructive, 29 billable, 1 external).
6
+
7
+ No hand-written client covers this area. Call it through `g8.api.signals.*` as shown below, or by operationId with `g8.api.call(operationId, input)`.
8
+
9
+ Every example below assumes this setup (server-side, API key):
10
+
11
+ ```ts
12
+ import { g8 } from "@graph8/sdk";
13
+
14
+ g8.init({ apiKey: process.env.G8_API_KEY! });
15
+ ```
16
+
17
+ Example values are placeholders that match each field's type. Only required fields are shown. Every example is type-checked against the SDK in CI.
18
+
19
+ Exact TypeScript types for every operation on this page, and every schema they use: [signals.d.ts](signals.d.ts).
20
+
21
+ ## Operations
22
+
23
+ | Call | HTTP | Tier | Scope | Summary |
24
+ |---|---|---|---|---|
25
+ | [`addEngagersToList`](#op-addengagerstolist) | `POST /api/v1/social-listeners/posts/{post_id}/engagements/add-to-list` | billable | `intent:run` | Add Engagers To List |
26
+ | [`addPostAuthorToSequence`](#op-addpostauthortosequence) | `POST /api/v1/social-listeners/posts/{post_id}/add-to-sequence` | external | `intent:run` | Add Post Author To Sequence |
27
+ | [`autoSeedAllListeners`](#op-autoseedalllisteners) | `POST /api/v1/social-listeners/auto-seed/all` | billable | `intent:run` | Auto Seed All Listeners |
28
+ | [`autoSeedBrandListener`](#op-autoseedbrandlistener) | `POST /api/v1/social-listeners/auto-seed/brand` | billable | `intent:run` | Auto Seed Brand Listener |
29
+ | [`autoSeedCompetitorListeners`](#op-autoseedcompetitorlisteners) | `POST /api/v1/social-listeners/auto-seed/competitors` | billable | `intent:run` | Auto Seed Competitor Listeners |
30
+ | [`autoSeedEngagementListeners`](#op-autoseedengagementlisteners) | `POST /api/v1/social-listeners/auto-seed/engagement` | billable | `intent:run` | Auto Seed Engagement Listeners |
31
+ | [`autoSeedKeywordListeners`](#op-autoseedkeywordlisteners) | `POST /api/v1/social-listeners/auto-seed/keywords` | billable | `intent:run` | Auto Seed Keyword Listeners |
32
+ | [`bulkCreateListenersFromList`](#op-bulkcreatelistenersfromlist) | `POST /api/v1/social-listeners/bulk-from-list` | billable | `intent:run` | Bulk Create Listeners From List |
33
+ | [`connectXCredentials`](#op-connectxcredentials) | `POST /api/v1/social-listeners/integrations/x` | billable | `intent:run` | Connect X Credentials |
34
+ | [`createListener`](#op-createlistener) | `POST /api/v1/social-listeners` | billable | `intent:run` | Create Listener |
35
+ | [`deleteKeywordUrl`](#op-deletekeywordurl) | `DELETE /api/v1/intent/keyword-urls/{url_id}` | destructive | `intent:delete` | Delete Keyword Url |
36
+ | [`deleteListener`](#op-deletelistener) | `DELETE /api/v1/social-listeners/{listener_id}` | destructive | `intent:delete` | Delete Listener |
37
+ | [`disconnectXCredentials`](#op-disconnectxcredentials) | `DELETE /api/v1/social-listeners/integrations/x` | destructive | `intent:delete` | Disconnect X Credentials |
38
+ | [`generateListenerQuery`](#op-generatelistenerquery) | `POST /api/v1/social-listeners/queries/generate` | billable | `intent:run` | Generate Listener Query |
39
+ | [`getAbmCompanyPersonas`](#op-getabmcompanypersonas) | `GET /api/v1/intent/abm/companies/{company_id}/personas` | read | `intent:read` | Get Abm Company Personas |
40
+ | [`getAutoSeedStatus`](#op-getautoseedstatus) | `GET /api/v1/social-listeners/auto-seed-status` | read | `intent:read` | Get Auto Seed Status |
41
+ | [`getCompanyJobCounts`](#op-getcompanyjobcounts) | `POST /api/v1/hiring-signals/companies/job-counts` | billable | `intent:run` | Get Company Job Counts |
42
+ | [`getHiringJobDetails`](#op-gethiringjobdetails) | `GET /api/v1/hiring-signals/jobs/{job_id}` | read | `intent:read` | Get Hiring Job Details |
43
+ | [`getJobResolutionStatus`](#op-getjobresolutionstatus) | `GET /api/v1/intent/keywords/{keyword_id}/job-resolution` | read | `intent:read` | Get Job Resolution Status |
44
+ | [`getKeywordSyncConfig`](#op-getkeywordsyncconfig) | `GET /api/v1/intent/keywords/{keyword_id}/sync-config` | read | `intent:read` | Get Keyword Sync Config |
45
+ | [`getListener`](#op-getlistener) | `GET /api/v1/social-listeners/{listener_id}` | read | `intent:read` | Get Listener |
46
+ | [`getSocialSettings`](#op-getsocialsettings) | `GET /api/v1/social-listeners/settings` | read | `intent:read` | Get Social Settings |
47
+ | [`getSocialStats`](#op-getsocialstats) | `GET /api/v1/social-listeners/stats` | read | `intent:read` | Get Social Stats |
48
+ | [`getXEffectiveMode`](#op-getxeffectivemode) | `GET /api/v1/social-listeners/integrations/x/mode` | read | `intent:read` | Get X Effective Mode |
49
+ | [`getXIntegration`](#op-getxintegration) | `GET /api/v1/social-listeners/integrations/x` | read | `intent:read` | Get X Integration |
50
+ | [`listAbmCompanies`](#op-listabmcompanies) | `GET /api/v1/intent/abm/companies` | read | `intent:read` | List Abm Companies |
51
+ | [`listCompanyHiringJobs`](#op-listcompanyhiringjobs) | `GET /api/v1/hiring-signals/companies/{linkedin_company_id}/jobs` | read | `intent:read` | List Company Hiring Jobs |
52
+ | [`listCompanyLinkedinPosts`](#op-listcompanylinkedinposts) | `GET /api/v1/hiring-signals/companies/{linkedin_company_id}/linkedin-posts` | read | `intent:read` | List Company Linkedin Posts |
53
+ | [`listJobChangeSignals`](#op-listjobchangesignals) | `GET /api/v1/hiring-signals/job-changes` | read | `intent:read` | List Job Change Signals |
54
+ | [`listListeners`](#op-listlisteners) | `GET /api/v1/social-listeners` | read | `intent:read` | List Listeners |
55
+ | [`listPostsByContact`](#op-listpostsbycontact) | `GET /api/v1/social-listeners/posts/by-contact/{contact_id}` | read | `intent:read` | List Posts By Contact |
56
+ | [`listSourceLists`](#op-listsourcelists) | `GET /api/v1/social-listeners/source-lists` | read | `intent:read` | List Source Lists |
57
+ | [`listTopEngagedAccounts`](#op-listtopengagedaccounts) | `GET /api/v1/social-listeners/engagements/top-accounts` | read | `intent:read` | List Top Engaged Accounts |
58
+ | [`markPost`](#op-markpost) | `POST /api/v1/social-listeners/posts/{post_id}/mark` | billable | `intent:run` | Mark Post |
59
+ | [`matchJobChangeSignals`](#op-matchjobchangesignals) | `POST /api/v1/hiring-signals/job-changes/match` | billable | `intent:run` | Match Job Change Signals |
60
+ | [`previewKeywordUrls`](#op-previewkeywordurls) | `POST /api/v1/intent/keywords/preview` | read | `intent:read` | Preview Keyword Urls |
61
+ | [`previewListenerCost`](#op-previewlistenercost) | `POST /api/v1/social-listeners/preview-cost` | read | `intent:read` | Preview Listener Cost |
62
+ | [`proposeHiringKeywords`](#op-proposehiringkeywords) | `POST /api/v1/intent/keywords/auto-seed-proposals` | billable | `intent:run` | Propose Hiring Keywords |
63
+ | [`resolveHiringCompanyIds`](#op-resolvehiringcompanyids) | `POST /api/v1/hiring-signals/companies/resolve-ids` | billable | `intent:run` | Resolve Hiring Company Ids |
64
+ | [`resolveJobsForKeyword`](#op-resolvejobsforkeyword) | `POST /api/v1/intent/keywords/{keyword_id}/job-resolution` | billable | `intent:run` | Resolve Jobs For Keyword |
65
+ | [`rollupAbmCompanies`](#op-rollupabmcompanies) | `POST /api/v1/intent/abm/rollup` | read | `intent:read` | Rollup Abm Companies |
66
+ | [`saveIntentToContactMetadata`](#op-saveintenttocontactmetadata) | `POST /api/v1/intent/contacts/metadata` | billable | `intent:run` | Save Intent To Contact Metadata |
67
+ | [`saveKeywordSyncConfig`](#op-savekeywordsyncconfig) | `PATCH /api/v1/intent/keywords/{keyword_id}/sync-config` | billable | `intent:run` | Save Keyword Sync Config |
68
+ | [`savePostAuthorAsContact`](#op-savepostauthorascontact) | `POST /api/v1/social-listeners/posts/{post_id}/save-contact` | billable | `intent:run` | Save Post Author As Contact |
69
+ | [`searchHiringAggregators`](#op-searchhiringaggregators) | `POST /api/v1/hiring-signals/aggregators` | billable | `intent:run` | Search Hiring Aggregators |
70
+ | [`searchHiringCompanies`](#op-searchhiringcompanies) | `POST /api/v1/hiring-signals/companies` | billable | `intent:run` | Search Hiring Companies |
71
+ | [`searchHiringDecisionMakers`](#op-searchhiringdecisionmakers) | `POST /api/v1/hiring-signals/decision-makers` | billable | `intent:run` | Search Hiring Decision Makers |
72
+ | [`searchHiringJobs`](#op-searchhiringjobs) | `POST /api/v1/hiring-signals/jobs` | billable | `intent:run` | Search Hiring Jobs |
73
+ | [`searchHiringRecruiters`](#op-searchhiringrecruiters) | `POST /api/v1/hiring-signals/recruiters` | billable | `intent:run` | Search Hiring Recruiters |
74
+ | [`searchMatchedPosts`](#op-searchmatchedposts) | `POST /api/v1/social-listeners/posts/search` | read | `intent:read` | Search Matched Posts |
75
+ | [`searchPostEngagements`](#op-searchpostengagements) | `POST /api/v1/social-listeners/posts/{post_id}/engagements/search` | read | `intent:read` | Search Post Engagements |
76
+ | [`testXCredentials`](#op-testxcredentials) | `POST /api/v1/social-listeners/integrations/x/test` | billable | `intent:run` | Test X Credentials |
77
+ | [`triggerKeywordSync`](#op-triggerkeywordsync) | `POST /api/v1/intent/keywords/{keyword_id}/sync` | billable | `intent:run` | Trigger Keyword Sync |
78
+ | [`updateHiringKeyword`](#op-updatehiringkeyword) | `PATCH /api/v1/intent/keywords/{keyword_id}` | billable | `intent:run` | Update Hiring Keyword |
79
+ | [`updateListener`](#op-updatelistener) | `PATCH /api/v1/social-listeners/{listener_id}` | billable | `intent:run` | Update Listener |
80
+ | [`updateSocialSettings`](#op-updatesocialsettings) | `PATCH /api/v1/social-listeners/settings` | billable | `intent:run` | Update Social Settings |
81
+
82
+ ---
83
+
84
+ <a id="op-addengagerstolist"></a>
85
+
86
+ ### `g8.api.signals.addEngagersToList(input)`
87
+
88
+ **Add Engagers To List**
89
+
90
+ - HTTP: `POST /api/v1/social-listeners/posts/{post_id}/engagements/add-to-list`
91
+ - operationId: `add_engagers_to_list_social_listeners_posts__post_id__engagements_add_to_list_post` (also callable as `g8.api.call("add_engagers_to_list_social_listeners_posts__post_id__engagements_add_to_list_post", input)`)
92
+ - Tier: `billable`: spends credits; the SDK never blindly retries it; confirm cost before bulk use
93
+ - API-key scope: `intent:run`
94
+
95
+ Turn the people who engaged with a post into a graph8 list.
96
+
97
+ CREATES CONTACTS. Engagers with no matching graph8 contact are created as
98
+ stubs, so this grows the contact database as well as the list.
99
+
100
+ Supply `audience_id` for an existing list or `audience_name` to create one.
101
+ The app does not gate this on `signals:write`; this surface does, because
102
+ creating contacts from a public post is a write by any reading and the
103
+ app's omission looks like an oversight rather than a decision.
104
+
105
+ **Input**
106
+
107
+ | Field | Type | Required | Description |
108
+ |---|---|---|---|
109
+ | `path.post_id` | `string` | yes | The post's platform-native id. |
110
+ | `body` | `AddEngagersToListRequest` | yes | Request body; fields below. |
111
+
112
+ Body fields (`AddEngagersToListRequest`):
113
+
114
+ | Field | Type | Required | Description |
115
+ |---|---|---|---|
116
+ | `body.audience_id` | `string \| null` | no | An existing graph8 list. |
117
+ | `body.audience_name` | `string \| null` | no | Create a new graph8 list with this name. max length 255 |
118
+ | `body.engagement_type` | `"comment" \| "reaction" \| null` | no | Only commenters, or only reactors. Omit for both. |
119
+ | `body.platform` | `"x" \| "linkedin" \| "reddit" \| "instagram" \| "youtube"` | no | default `"linkedin"` |
120
+ | `body.post_external_id` | `string \| null` | no | Optional echo of the path id. The PATH value is authoritative. |
121
+
122
+ **Returns** `ApiResponse_SocialPayload_`: the envelope `{ data: SocialPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
123
+
124
+ Other envelope fields: `pagination` (PaginationMeta).
125
+
126
+ **Example**
127
+
128
+ ```ts
129
+ // billable: spends credits; the SDK never blindly retries it; confirm cost before bulk use.
130
+ const result = await g8.api.signals.addEngagersToList({ path: { post_id: "id" }, body: {} });
131
+ ```
132
+
133
+ ---
134
+
135
+ <a id="op-addpostauthortosequence"></a>
136
+
137
+ ### `g8.api.signals.addPostAuthorToSequence(input)`
138
+
139
+ **Add Post Author To Sequence**
140
+
141
+ - HTTP: `POST /api/v1/social-listeners/posts/{post_id}/add-to-sequence`
142
+ - operationId: `add_post_author_to_sequence_social_listeners_posts__post_id__add_to_sequence_post` (also callable as `g8.api.call("add_post_author_to_sequence_social_listeners_posts__post_id__add_to_sequence_post", input)`)
143
+ - Tier: `external`: reaches real people (sends email/SMS, places a call, launches a send); the SDK never blindly retries it; confirm with a human first
144
+ - API-key scope: `intent:run`
145
+
146
+ Enrol a post's author into a sequence.
147
+
148
+ 202, NOT 200: this resolves the author to a contact and publishes an
149
+ enrolment REQUEST. The sequencer consumes it afterwards, and it is that
150
+ consumer - not this call - that starts sending to a real person. A 202 here
151
+ does not mean the person is enrolled, and it does not mean they are not
152
+ about to be.
153
+
154
+ **Input**
155
+
156
+ | Field | Type | Required | Description |
157
+ |---|---|---|---|
158
+ | `path.post_id` | `string` | yes | The post's platform-native id. |
159
+ | `body` | `AddPostToSequenceRequest` | yes | Request body; fields below. |
160
+
161
+ Body fields (`AddPostToSequenceRequest`):
162
+
163
+ | Field | Type | Required | Description |
164
+ |---|---|---|---|
165
+ | `body.sequence_id` | `string` | yes | |
166
+ | `body.platform` | `"x" \| "linkedin" \| "reddit" \| "instagram" \| "youtube"` | no | default `"x"` |
167
+
168
+ **Returns** `ApiResponse_SocialPayload_`: the envelope `{ data: SocialPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
169
+
170
+ Other envelope fields: `pagination` (PaginationMeta).
171
+
172
+ **Example**
173
+
174
+ ```ts
175
+ // external: reaches real people (sends email/SMS, places a call, launches a send); the SDK never blindly retries it; confirm with a human first.
176
+ const result = await g8.api.signals.addPostAuthorToSequence({ path: { post_id: "id" }, body: { sequence_id: "id" } });
177
+ ```
178
+
179
+ ---
180
+
181
+ <a id="op-autoseedalllisteners"></a>
182
+
183
+ ### `g8.api.signals.autoSeedAllListeners(input?)`
184
+
185
+ **Auto Seed All Listeners**
186
+
187
+ - HTTP: `POST /api/v1/social-listeners/auto-seed/all`
188
+ - operationId: `auto_seed_all_listeners_social_listeners_auto_seed_all_post` (also callable as `g8.api.call("auto_seed_all_listeners_social_listeners_auto_seed_all_post", input)`)
189
+ - Tier: `billable`: spends credits; the SDK never blindly retries it; confirm cost before bulk use
190
+ - API-key scope: `intent:run`
191
+
192
+ Run every auto-seed in one go. ASYNCHRONOUS, AND IT SPENDS CREDITS.
193
+
194
+ 202 is returned BEFORE any seeding happens. The brand, competitor and
195
+ engagement stages each make their own charged LLM call afterwards, in a
196
+ background task - so up to three charges land after this response, and a
197
+ caller that only reads the response body will not see any of them. Poll
198
+ `GET /social-listeners/auto-seed-status` with the returned `job_id`.
199
+
200
+ Each stage fails independently: a partial result is normal and is not an
201
+ error.
202
+
203
+ 409 if a run is already in flight.
204
+
205
+ **Input**
206
+
207
+ | Field | Type | Required | Description |
208
+ |---|---|---|---|
209
+ | `body` | `SeedChannelsRequest \| null` | no | Request body; fields below. |
210
+
211
+ Body fields:
212
+
213
+ | Field | Type | Required | Description |
214
+ |---|---|---|---|
215
+ | `body.channels` | `Array<"x" \| "linkedin" \| "reddit" \| "instagram" \| "youtube"> \| null` | no | |
216
+
217
+ **Returns** `ApiResponse_SocialPayload_`: the envelope `{ data: SocialPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
218
+
219
+ Other envelope fields: `pagination` (PaginationMeta).
220
+
221
+ **Example**
222
+
223
+ ```ts
224
+ // billable: spends credits; the SDK never blindly retries it; confirm cost before bulk use.
225
+ const result = await g8.api.signals.autoSeedAllListeners();
226
+ ```
227
+
228
+ ---
229
+
230
+ <a id="op-autoseedbrandlistener"></a>
231
+
232
+ ### `g8.api.signals.autoSeedBrandListener(input?)`
233
+
234
+ **Auto Seed Brand Listener**
235
+
236
+ - HTTP: `POST /api/v1/social-listeners/auto-seed/brand`
237
+ - operationId: `auto_seed_brand_listener_social_listeners_auto_seed_brand_post` (also callable as `g8.api.call("auto_seed_brand_listener_social_listeners_auto_seed_brand_post", input)`)
238
+ - Tier: `billable`: spends credits; the SDK never blindly retries it; confirm cost before bulk use
239
+ - API-key scope: `intent:run`
240
+
241
+ Create a brand listener from the org's brand documents.
242
+
243
+ SPENDS CREDITS - an LLM call extracts the brand and product names. The
244
+ charge happens BEFORE the listeners are inserted, so a failure after
245
+ extraction still costs. 400 if the org has no brand brief to read.
246
+
247
+ **Input**: none.
248
+
249
+ **Returns** `ApiResponse_SocialPayload_`: the envelope `{ data: SocialPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
250
+
251
+ Other envelope fields: `pagination` (PaginationMeta).
252
+
253
+ **Example**
254
+
255
+ ```ts
256
+ // billable: spends credits; the SDK never blindly retries it; confirm cost before bulk use.
257
+ const result = await g8.api.signals.autoSeedBrandListener();
258
+ ```
259
+
260
+ ---
261
+
262
+ <a id="op-autoseedcompetitorlisteners"></a>
263
+
264
+ ### `g8.api.signals.autoSeedCompetitorListeners(input?)`
265
+
266
+ **Auto Seed Competitor Listeners**
267
+
268
+ - HTTP: `POST /api/v1/social-listeners/auto-seed/competitors`
269
+ - operationId: `auto_seed_competitor_listeners_social_listeners_auto_seed_competitors_post` (also callable as `g8.api.call("auto_seed_competitor_listeners_social_listeners_auto_seed_competitors_post", input)`)
270
+ - Tier: `billable`: spends credits; the SDK never blindly retries it; confirm cost before bulk use
271
+ - API-key scope: `intent:run`
272
+
273
+ Create competitor listeners from the org's brand documents.
274
+
275
+ SPENDS CREDITS - an LLM call extracts the competitor names, charged before
276
+ the listeners are inserted.
277
+
278
+ **Input**: none.
279
+
280
+ **Returns** `ApiResponse_SocialPayload_`: the envelope `{ data: SocialPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
281
+
282
+ Other envelope fields: `pagination` (PaginationMeta).
283
+
284
+ **Example**
285
+
286
+ ```ts
287
+ // billable: spends credits; the SDK never blindly retries it; confirm cost before bulk use.
288
+ const result = await g8.api.signals.autoSeedCompetitorListeners();
289
+ ```
290
+
291
+ ---
292
+
293
+ <a id="op-autoseedengagementlisteners"></a>
294
+
295
+ ### `g8.api.signals.autoSeedEngagementListeners(input?)`
296
+
297
+ **Auto Seed Engagement Listeners**
298
+
299
+ - HTTP: `POST /api/v1/social-listeners/auto-seed/engagement`
300
+ - operationId: `auto_seed_engagement_listeners_social_listeners_auto_seed_engagement_post` (also callable as `g8.api.call("auto_seed_engagement_listeners_social_listeners_auto_seed_engagement_post", input)`)
301
+ - Tier: `billable`: spends credits; the SDK never blindly retries it; confirm cost before bulk use
302
+ - API-key scope: `intent:run`
303
+
304
+ Create ICP-shaped engagement listeners.
305
+
306
+ SPENDS CREDITS - one LLM call produces two or three query buckets, charged
307
+ ONCE regardless of how many channels the buckets fan out to.
308
+
309
+ Omit the body entirely to take the app's own default channel set (X alone)
310
+ rather than this contract freezing a copy of it.
311
+
312
+ **Input**
313
+
314
+ | Field | Type | Required | Description |
315
+ |---|---|---|---|
316
+ | `body` | `SeedChannelsRequest \| null` | no | Request body; fields below. |
317
+
318
+ Body fields:
319
+
320
+ | Field | Type | Required | Description |
321
+ |---|---|---|---|
322
+ | `body.channels` | `Array<"x" \| "linkedin" \| "reddit" \| "instagram" \| "youtube"> \| null` | no | |
323
+
324
+ **Returns** `ApiResponse_SocialPayload_`: the envelope `{ data: SocialPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
325
+
326
+ Other envelope fields: `pagination` (PaginationMeta).
327
+
328
+ **Example**
329
+
330
+ ```ts
331
+ // billable: spends credits; the SDK never blindly retries it; confirm cost before bulk use.
332
+ const result = await g8.api.signals.autoSeedEngagementListeners();
333
+ ```
334
+
335
+ ---
336
+
337
+ <a id="op-autoseedkeywordlisteners"></a>
338
+
339
+ ### `g8.api.signals.autoSeedKeywordListeners(input?)`
340
+
341
+ **Auto Seed Keyword Listeners**
342
+
343
+ - HTTP: `POST /api/v1/social-listeners/auto-seed/keywords`
344
+ - operationId: `auto_seed_keyword_listeners_social_listeners_auto_seed_keywords_post` (also callable as `g8.api.call("auto_seed_keyword_listeners_social_listeners_auto_seed_keywords_post", input)`)
345
+ - Tier: `billable`: spends credits; the SDK never blindly retries it; confirm cost before bulk use
346
+ - API-key scope: `intent:run`
347
+
348
+ Create keyword listeners from the org's existing keyword intelligence.
349
+
350
+ The ONLY auto-seed that charges nothing: it reads keywords that were
351
+ already gathered rather than asking an LLM for new ones. Start here.
352
+
353
+ **Input**: none.
354
+
355
+ **Returns** `ApiResponse_SocialPayload_`: the envelope `{ data: SocialPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
356
+
357
+ Other envelope fields: `pagination` (PaginationMeta).
358
+
359
+ **Example**
360
+
361
+ ```ts
362
+ // billable: spends credits; the SDK never blindly retries it; confirm cost before bulk use.
363
+ const result = await g8.api.signals.autoSeedKeywordListeners();
364
+ ```
365
+
366
+ ---
367
+
368
+ <a id="op-bulkcreatelistenersfromlist"></a>
369
+
370
+ ### `g8.api.signals.bulkCreateListenersFromList(input)`
371
+
372
+ **Bulk Create Listeners From List**
373
+
374
+ - HTTP: `POST /api/v1/social-listeners/bulk-from-list`
375
+ - operationId: `bulk_create_listeners_from_list_social_listeners_bulk_from_list_post` (also callable as `g8.api.call("bulk_create_listeners_from_list_social_listeners_bulk_from_list_post", input)`)
376
+ - Tier: `billable`: spends credits; the SDK never blindly retries it; confirm cost before bulk use
377
+ - API-key scope: `intent:run`
378
+
379
+ One `user` listener per social profile on a graph8 list.
380
+
381
+ No platform lookup happens here - handles are resolved lazily by the
382
+ polling worker on first poll, so this does not burn one API call per row at
383
+ creation time.
384
+
385
+ **Input**
386
+
387
+ | Field | Type | Required | Description |
388
+ |---|---|---|---|
389
+ | `body` | `BulkCreateFromListRequest` | yes | Request body; fields below. |
390
+
391
+ Body fields (`BulkCreateFromListRequest`):
392
+
393
+ | Field | Type | Required | Description |
394
+ |---|---|---|---|
395
+ | `body.list_id` | `integer` | yes | The graph8 audience to read profiles from. |
396
+ | `body.listener_type` | `"user"` | no | Only `user` listeners can be bulk-created from a list. default `"user"` |
397
+ | `body.platform` | `"x" \| "linkedin" \| "reddit" \| "instagram" \| "youtube"` | no | default `"x"` |
398
+ | `body.platforms` | `Array<"x" \| "linkedin" \| "reddit" \| "instagram" \| "youtube"> \| null` | no | Create one listener per platform. Overrides `platform`. |
399
+
400
+ **Returns** `ApiResponse_SocialPayload_`: the envelope `{ data: SocialPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
401
+
402
+ Other envelope fields: `pagination` (PaginationMeta).
403
+
404
+ **Example**
405
+
406
+ ```ts
407
+ // billable: spends credits; the SDK never blindly retries it; confirm cost before bulk use.
408
+ const result = await g8.api.signals.bulkCreateListenersFromList({ body: { list_id: 123 } });
409
+ ```
410
+
411
+ ---
412
+
413
+ <a id="op-connectxcredentials"></a>
414
+
415
+ ### `g8.api.signals.connectXCredentials(input)`
416
+
417
+ **Connect X Credentials**
418
+
419
+ - HTTP: `POST /api/v1/social-listeners/integrations/x`
420
+ - operationId: `connect_x_credentials_social_listeners_integrations_x_post` (also callable as `g8.api.call("connect_x_credentials_social_listeners_integrations_x_post", input)`)
421
+ - Tier: `billable`: spends credits; the SDK never blindly retries it; confirm cost before bulk use
422
+ - API-key scope: `intent:run`
423
+
424
+ Store the org's own X developer credentials.
425
+
426
+ WRITE-ONLY. The key, the secret and the bearer token derived from them are
427
+ encrypted at rest and are never returned - not by this route, and not by
428
+ any other on this surface.
429
+
430
+ With credentials stored the org pays X directly and is not bounded by
431
+ graph8's shared quota. Test them first with
432
+ `POST /social-listeners/integrations/x/test`, which validates without
433
+ storing anything.
434
+
435
+ **Input**
436
+
437
+ | Field | Type | Required | Description |
438
+ |---|---|---|---|
439
+ | `body` | `XApiCredentialsRequest` | yes | Request body; fields below. |
440
+
441
+ Body fields (`XApiCredentialsRequest`):
442
+
443
+ | Field | Type | Required | Description |
444
+ |---|---|---|---|
445
+ | `body.api_key` | `string` | yes | X Developer App API key (consumer key). min length 1 |
446
+ | `body.api_secret` | `string` | yes | X Developer App API secret. min length 1 |
447
+
448
+ **Returns** `ApiResponse_SocialPayload_`: the envelope `{ data: SocialPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
449
+
450
+ Other envelope fields: `pagination` (PaginationMeta).
451
+
452
+ **Example**
453
+
454
+ ```ts
455
+ // billable: spends credits; the SDK never blindly retries it; confirm cost before bulk use.
456
+ const result = await g8.api.signals.connectXCredentials({ body: { api_key: "example", api_secret: "example" } });
457
+ ```
458
+
459
+ ---
460
+
461
+ <a id="op-createlistener"></a>
462
+
463
+ ### `g8.api.signals.createListener(input)`
464
+
465
+ **Create Listener**
466
+
467
+ - HTTP: `POST /api/v1/social-listeners`
468
+ - operationId: `create_listener_social_listeners_post` (also callable as `g8.api.call("create_listener_social_listeners_post", input)`)
469
+ - Tier: `billable`: spends credits; the SDK never blindly retries it; confirm cost before bulk use
470
+ - API-key scope: `intent:run`
471
+
472
+ Start watching something.
473
+
474
+ THIS CAN SPEND CREDITS: a `brand` listener with no `query` has one built by
475
+ an LLM call, which is charged. Supply `query`, or call
476
+ `POST /social-listeners/queries/generate` first, to see what you are
477
+ committing to.
478
+
479
+ A `user` listener additionally resolves `target_handle` against the
480
+ platform, which consumes the org's X API quota.
481
+
482
+ Set `monthly_credit_cap` unless you have set an org-wide one - it is the
483
+ only per-listener bound on what this costs.
484
+
485
+ **Input**
486
+
487
+ | Field | Type | Required | Description |
488
+ |---|---|---|---|
489
+ | `body` | `CreateListenerRequest` | yes | Request body; fields below. |
490
+
491
+ Body fields (`CreateListenerRequest`):
492
+
493
+ | Field | Type | Required | Description |
494
+ |---|---|---|---|
495
+ | `body.listener_type` | `"brand" \| "competitor" \| "keyword" \| "engagement" \| "user"` | yes | `brand` and `competitor` watch a named entity, `keyword` watches a query, `engagement` watches an ICP-shaped bucket, `user` watches one account's posts. |
496
+ | `body.name` | `string` | yes | min length 1 |
497
+ | `body.filters` | `Record<string, unknown>` | no | |
498
+ | `body.force_rebuild_brand` | `boolean` | no | Rebuild a brand query even though one exists. Spends a credit to do it. default `false` |
499
+ | `body.monthly_credit_cap` | `integer \| null` | no | Per-listener ceiling on credits. The one field that BOUNDS what this costs. min 0 |
500
+ | `body.platform` | `"x" \| "linkedin" \| "reddit" \| "instagram" \| "youtube"` | no | default `"x"` |
501
+ | `body.poll_interval_sec` | `integer \| null` | no | How often the worker polls. Shorter means more matches AND more spend. min 60 |
502
+ | `body.query` | `string \| null` | no | Platform-native search query. OMITTING this on a `brand` listener makes the app build one with an LLM call, which SPENDS CREDITS. Supply a query, or call `POST /social-listeners/queries/generate` first if you want to see it before committing. |
503
+ | `body.target_handle` | `string \| null` | no | Required for a `user` listener: the account to watch. |
504
+
505
+ **Returns** `ApiResponse_SocialPayload_`: the envelope `{ data: SocialPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
506
+
507
+ Other envelope fields: `pagination` (PaginationMeta).
508
+
509
+ **Example**
510
+
511
+ ```ts
512
+ // billable: spends credits; the SDK never blindly retries it; confirm cost before bulk use.
513
+ const result = await g8.api.signals.createListener({ body: { listener_type: "brand", name: "Example" } });
514
+ ```
515
+
516
+ ---
517
+
518
+ <a id="op-deletekeywordurl"></a>
519
+
520
+ ### `g8.api.signals.deleteKeywordUrl(input)`
521
+
522
+ **Delete Keyword Url**
523
+
524
+ - HTTP: `DELETE /api/v1/intent/keyword-urls/{url_id}`
525
+ - operationId: `delete_keyword_url_intent_keyword_urls__url_id__delete` (also callable as `g8.api.call("delete_keyword_url_intent_keyword_urls__url_id__delete", input)`)
526
+ - Tier: `destructive`: deletes or archives data; confirm with a human before calling
527
+ - API-key scope: `intent:delete`
528
+
529
+ Remove one URL from a keyword's matched set (soft delete).
530
+
531
+ **Input**
532
+
533
+ | Field | Type | Required | Description |
534
+ |---|---|---|---|
535
+ | `path.url_id` | `string (uuid)` | yes | The keyword URL's id. |
536
+
537
+ **Returns** `ApiResponse_IntentPayload_`: the envelope `{ data: IntentPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
538
+
539
+ Other envelope fields: `pagination` (PaginationMeta).
540
+
541
+ **Example**
542
+
543
+ ```ts
544
+ // destructive: deletes or archives data; confirm with a human before calling.
545
+ const result = await g8.api.signals.deleteKeywordUrl({ path: { url_id: "00000000-0000-0000-0000-000000000000" } });
546
+ ```
547
+
548
+ ---
549
+
550
+ <a id="op-deletelistener"></a>
551
+
552
+ ### `g8.api.signals.deleteListener(input)`
553
+
554
+ **Delete Listener**
555
+
556
+ - HTTP: `DELETE /api/v1/social-listeners/{listener_id}`
557
+ - operationId: `delete_listener_social_listeners__listener_id__delete` (also callable as `g8.api.call("delete_listener_social_listeners__listener_id__delete", input)`)
558
+ - Tier: `destructive`: deletes or archives data; confirm with a human before calling
559
+ - API-key scope: `intent:delete`
560
+
561
+ Delete a listener.
562
+
563
+ Gated on `signals:delete` specifically, not on `signals:write` - the app
564
+ separates them, and so does this. To stop the spend without losing the
565
+ matched posts, PATCH `is_active: false` instead.
566
+
567
+ **Input**
568
+
569
+ | Field | Type | Required | Description |
570
+ |---|---|---|---|
571
+ | `path.listener_id` | `string (uuid)` | yes | The listener's id. |
572
+
573
+ **Returns** `ApiResponse_SocialPayload_`: the envelope `{ data: SocialPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
574
+
575
+ Other envelope fields: `pagination` (PaginationMeta).
576
+
577
+ **Example**
578
+
579
+ ```ts
580
+ // destructive: deletes or archives data; confirm with a human before calling.
581
+ const result = await g8.api.signals.deleteListener({ path: { listener_id: "00000000-0000-0000-0000-000000000000" } });
582
+ ```
583
+
584
+ ---
585
+
586
+ <a id="op-disconnectxcredentials"></a>
587
+
588
+ ### `g8.api.signals.disconnectXCredentials(input?)`
589
+
590
+ **Disconnect X Credentials**
591
+
592
+ - HTTP: `DELETE /api/v1/social-listeners/integrations/x`
593
+ - operationId: `disconnect_x_credentials_social_listeners_integrations_x_delete` (also callable as `g8.api.call("disconnect_x_credentials_social_listeners_integrations_x_delete", input)`)
594
+ - Tier: `destructive`: deletes or archives data; confirm with a human before calling
595
+ - API-key scope: `intent:delete`
596
+
597
+ Remove the org's own X credentials.
598
+
599
+ THIS PAUSES LISTENERS. Every active X listener is paused; if graph8's
600
+ shared mode is available they are immediately reactivated under it, with an
601
+ alert per listener. If it is not, they stay paused and stop matching.
602
+
603
+ **Input**: none.
604
+
605
+ **Returns** `ApiResponse_SocialPayload_`: the envelope `{ data: SocialPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
606
+
607
+ Other envelope fields: `pagination` (PaginationMeta).
608
+
609
+ **Example**
610
+
611
+ ```ts
612
+ // destructive: deletes or archives data; confirm with a human before calling.
613
+ const result = await g8.api.signals.disconnectXCredentials();
614
+ ```
615
+
616
+ ---
617
+
618
+ <a id="op-generatelistenerquery"></a>
619
+
620
+ ### `g8.api.signals.generateListenerQuery(input)`
621
+
622
+ **Generate Listener Query**
623
+
624
+ - HTTP: `POST /api/v1/social-listeners/queries/generate`
625
+ - operationId: `generate_listener_query_social_listeners_queries_generate_post` (also callable as `g8.api.call("generate_listener_query_social_listeners_queries_generate_post", input)`)
626
+ - Tier: `billable`: spends credits; the SDK never blindly retries it; confirm cost before bulk use
627
+ - API-key scope: `intent:run`
628
+
629
+ Turn a plain-English description into a platform-native query.
630
+
631
+ THIS SPENDS CREDITS - it is an LLM call. It returns the query rather than
632
+ creating a listener, so the query can be read, edited and reused across
633
+ several listeners for the price of one generation.
634
+
635
+ **Input**
636
+
637
+ | Field | Type | Required | Description |
638
+ |---|---|---|---|
639
+ | `body` | `GenerateQueryRequest` | yes | Request body; fields below. |
640
+
641
+ Body fields (`GenerateQueryRequest`):
642
+
643
+ | Field | Type | Required | Description |
644
+ |---|---|---|---|
645
+ | `body.description` | `string` | yes | min length 1, max length 1000 |
646
+ | `body.listener_type` | `"brand" \| "competitor" \| "keyword" \| "engagement" \| "user"` | yes | |
647
+
648
+ **Returns** `ApiResponse_SocialPayload_`: the envelope `{ data: SocialPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
649
+
650
+ Other envelope fields: `pagination` (PaginationMeta).
651
+
652
+ **Example**
653
+
654
+ ```ts
655
+ // billable: spends credits; the SDK never blindly retries it; confirm cost before bulk use.
656
+ const result = await g8.api.signals.generateListenerQuery({ body: { description: "example", listener_type: "brand" } });
657
+ ```
658
+
659
+ ---
660
+
661
+ <a id="op-getabmcompanypersonas"></a>
662
+
663
+ ### `g8.api.signals.getAbmCompanyPersonas(input)`
664
+
665
+ **Get Abm Company Personas**
666
+
667
+ - HTTP: `GET /api/v1/intent/abm/companies/{company_id}/personas`
668
+ - operationId: `get_abm_company_personas_intent_abm_companies__company_id__personas_get` (also callable as `g8.api.call("get_abm_company_personas_intent_abm_companies__company_id__personas_get", input)`)
669
+ - Tier: `read`: reads data; safe to call and to retry
670
+ - API-key scope: `intent:read`
671
+
672
+ Who to contact at one account showing intent: its buying committee, persona by persona.
673
+
674
+ **Input**
675
+
676
+ | Field | Type | Required | Description |
677
+ |---|---|---|---|
678
+ | `path.company_id` | `integer` | yes | Company id. |
679
+ | `query.days` | `integer` | no | Look-back window in days. default `30` |
680
+ | `query.export_mode` | `"signals_only" \| "icp_plus_signals" \| "all_icp_personas"` | no | The same three modes as a keyword's sync config, so this previews what a sync exports. default `"icp_plus_signals"` |
681
+ | `query.icp_id` | `string (uuid) \| null` | no | Score against this ICP. |
682
+
683
+ **Returns** `ApiResponse_IntentPayload_`: the envelope `{ data: IntentPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
684
+
685
+ Other envelope fields: `pagination` (PaginationMeta).
686
+
687
+ **Example**
688
+
689
+ ```ts
690
+ const result = await g8.api.signals.getAbmCompanyPersonas({ path: { company_id: 1 } });
691
+ ```
692
+
693
+ ---
694
+
695
+ <a id="op-getautoseedstatus"></a>
696
+
697
+ ### `g8.api.signals.getAutoSeedStatus(input?)`
698
+
699
+ **Get Auto Seed Status**
700
+
701
+ - HTTP: `GET /api/v1/social-listeners/auto-seed-status`
702
+ - operationId: `get_auto_seed_status_social_listeners_auto_seed_status_get` (also callable as `g8.api.call("get_auto_seed_status_social_listeners_auto_seed_status_get", input)`)
703
+ - Tier: `read`: reads data; safe to call and to retry
704
+ - API-key scope: `intent:read`
705
+
706
+ How the asynchronous `/auto-seed/all` run is going.
707
+
708
+ The only way to see what that call did: it answers 202 before any of the
709
+ seeding, or any of the credit spend, has happened.
710
+
711
+ **Input**
712
+
713
+ | Field | Type | Required | Description |
714
+ |---|---|---|---|
715
+ | `query.job_id` | `string \| null` | no | A job id from `/auto-seed/all`. Omit for the most recent run. |
716
+
717
+ **Returns** `ApiResponse_SocialPayload_`: the envelope `{ data: SocialPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
718
+
719
+ Other envelope fields: `pagination` (PaginationMeta).
720
+
721
+ **Example**
722
+
723
+ ```ts
724
+ const result = await g8.api.signals.getAutoSeedStatus();
725
+ ```
726
+
727
+ ---
728
+
729
+ <a id="op-getcompanyjobcounts"></a>
730
+
731
+ ### `g8.api.signals.getCompanyJobCounts(input)`
732
+
733
+ **Get Company Job Counts**
734
+
735
+ - HTTP: `POST /api/v1/hiring-signals/companies/job-counts`
736
+ - operationId: `get_company_job_counts_hiring_signals_companies_job_counts_post` (also callable as `g8.api.call("get_company_job_counts_hiring_signals_companies_job_counts_post", input)`)
737
+ - Tier: `billable`: spends credits; the SDK never blindly retries it; confirm cost before bulk use
738
+ - API-key scope: `intent:run`
739
+
740
+ Active-job counts for a page of companies, in one call.
741
+
742
+ Capped at 1000 lcids: this is for decorating a grid page, not scanning a
743
+ corpus.
744
+
745
+ **Input**
746
+
747
+ | Field | Type | Required | Description |
748
+ |---|---|---|---|
749
+ | `body` | `CompanyJobCountsRequest` | yes | Request body; fields below. |
750
+
751
+ Body fields (`CompanyJobCountsRequest`):
752
+
753
+ | Field | Type | Required | Description |
754
+ |---|---|---|---|
755
+ | `body.linkedin_company_ids` | `Array<integer>` | no | LinkedIn company ids (lcids). Capped at 1000 - one grid page, not a corpus scan. max items 1000 |
756
+ | `body.window_days` | `integer` | no | default `60`, min 1, max 365 |
757
+
758
+ **Returns** `ApiResponse_dict_`: the envelope `{ data: Record<string, unknown>, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
759
+
760
+ Other envelope fields: `pagination` (PaginationMeta).
761
+
762
+ **Example**
763
+
764
+ ```ts
765
+ // billable: spends credits; the SDK never blindly retries it; confirm cost before bulk use.
766
+ const result = await g8.api.signals.getCompanyJobCounts({ body: {} });
767
+ ```
768
+
769
+ ---
770
+
771
+ <a id="op-gethiringjobdetails"></a>
772
+
773
+ ### `g8.api.signals.getHiringJobDetails(input)`
774
+
775
+ **Get Hiring Job Details**
776
+
777
+ - HTTP: `GET /api/v1/hiring-signals/jobs/{job_id}`
778
+ - operationId: `get_hiring_job_details_hiring_signals_jobs__job_id__get` (also callable as `g8.api.call("get_hiring_job_details_hiring_signals_jobs__job_id__get", input)`)
779
+ - Tier: `read`: reads data; safe to call and to retry
780
+ - API-key scope: `intent:read`
781
+
782
+ One posting, with its company, its recruiter and the company's other jobs.
783
+
784
+ **Input**
785
+
786
+ | Field | Type | Required | Description |
787
+ |---|---|---|---|
788
+ | `path.job_id` | `integer` | yes | Job id. |
789
+
790
+ **Returns** `ApiResponse_JobDetails_`: the envelope `{ data: JobDetails, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
791
+
792
+ Other envelope fields: `pagination` (PaginationMeta).
793
+
794
+ `JobDetails` fields:
795
+
796
+ | Field | Type | Required | Description |
797
+ |---|---|---|---|
798
+ | `company_name` | `string \| null` | no | |
799
+ | `job_id` | `integer \| null` | no | |
800
+ | `job_location` | `string \| null` | no | |
801
+ | `linkedin_company_id` | `integer \| null` | no | |
802
+ | `posted_at` | `string (date-time) \| null` | no | |
803
+ | `title` | `string \| null` | no | |
804
+
805
+ **Example**
806
+
807
+ ```ts
808
+ const result = await g8.api.signals.getHiringJobDetails({ path: { job_id: 123 } });
809
+ ```
810
+
811
+ ---
812
+
813
+ <a id="op-getjobresolutionstatus"></a>
814
+
815
+ ### `g8.api.signals.getJobResolutionStatus(input)`
816
+
817
+ **Get Job Resolution Status**
818
+
819
+ - HTTP: `GET /api/v1/intent/keywords/{keyword_id}/job-resolution`
820
+ - operationId: `get_job_resolution_status_intent_keywords__keyword_id__job_resolution_get` (also callable as `g8.api.call("get_job_resolution_status_intent_keywords__keyword_id__job_resolution_get", input)`)
821
+ - Tier: `read`: reads data; safe to call and to retry
822
+ - API-key scope: `intent:read`
823
+
824
+ When the resolver last ran for this keyword, and what it emitted. Empty if it never has.
825
+
826
+ **Input**
827
+
828
+ | Field | Type | Required | Description |
829
+ |---|---|---|---|
830
+ | `path.keyword_id` | `string (uuid)` | yes | The keyword's id. |
831
+
832
+ **Returns** `ApiResponse_IntentPayload_`: the envelope `{ data: IntentPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
833
+
834
+ Other envelope fields: `pagination` (PaginationMeta).
835
+
836
+ **Example**
837
+
838
+ ```ts
839
+ const result = await g8.api.signals.getJobResolutionStatus({ path: { keyword_id: "00000000-0000-0000-0000-000000000000" } });
840
+ ```
841
+
842
+ ---
843
+
844
+ <a id="op-getkeywordsyncconfig"></a>
845
+
846
+ ### `g8.api.signals.getKeywordSyncConfig(input)`
847
+
848
+ **Get Keyword Sync Config**
849
+
850
+ - HTTP: `GET /api/v1/intent/keywords/{keyword_id}/sync-config`
851
+ - operationId: `get_keyword_sync_config_intent_keywords__keyword_id__sync_config_get` (also callable as `g8.api.call("get_keyword_sync_config_intent_keywords__keyword_id__sync_config_get", input)`)
852
+ - Tier: `read`: reads data; safe to call and to retry
853
+ - API-key scope: `intent:read`
854
+
855
+ Which list this keyword feeds, and whether on a schedule. Defaults when never configured.
856
+
857
+ **Input**
858
+
859
+ | Field | Type | Required | Description |
860
+ |---|---|---|---|
861
+ | `path.keyword_id` | `string (uuid)` | yes | The keyword's id. |
862
+
863
+ **Returns** `ApiResponse_IntentPayload_`: the envelope `{ data: IntentPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
864
+
865
+ Other envelope fields: `pagination` (PaginationMeta).
866
+
867
+ **Example**
868
+
869
+ ```ts
870
+ const result = await g8.api.signals.getKeywordSyncConfig({ path: { keyword_id: "00000000-0000-0000-0000-000000000000" } });
871
+ ```
872
+
873
+ ---
874
+
875
+ <a id="op-getlistener"></a>
876
+
877
+ ### `g8.api.signals.getListener(input)`
878
+
879
+ **Get Listener**
880
+
881
+ - HTTP: `GET /api/v1/social-listeners/{listener_id}`
882
+ - operationId: `get_listener_social_listeners__listener_id__get` (also callable as `g8.api.call("get_listener_social_listeners__listener_id__get", input)`)
883
+ - Tier: `read`: reads data; safe to call and to retry
884
+ - API-key scope: `intent:read`
885
+
886
+ One listener, with its match count and running credit burn.
887
+
888
+ **Input**
889
+
890
+ | Field | Type | Required | Description |
891
+ |---|---|---|---|
892
+ | `path.listener_id` | `string (uuid)` | yes | The listener's id. |
893
+
894
+ **Returns** `ApiResponse_SocialPayload_`: the envelope `{ data: SocialPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
895
+
896
+ Other envelope fields: `pagination` (PaginationMeta).
897
+
898
+ **Example**
899
+
900
+ ```ts
901
+ const result = await g8.api.signals.getListener({ path: { listener_id: "00000000-0000-0000-0000-000000000000" } });
902
+ ```
903
+
904
+ ---
905
+
906
+ <a id="op-getsocialsettings"></a>
907
+
908
+ ### `g8.api.signals.getSocialSettings(input?)`
909
+
910
+ **Get Social Settings**
911
+
912
+ - HTTP: `GET /api/v1/social-listeners/settings`
913
+ - operationId: `get_social_settings_social_listeners_settings_get` (also callable as `g8.api.call("get_social_settings_social_listeners_settings_get", input)`)
914
+ - Tier: `read`: reads data; safe to call and to retry
915
+ - API-key scope: `intent:read`
916
+
917
+ Org-wide social listening settings, including every spend ceiling.
918
+
919
+ **Input**: none.
920
+
921
+ **Returns** `ApiResponse_SocialPayload_`: the envelope `{ data: SocialPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
922
+
923
+ Other envelope fields: `pagination` (PaginationMeta).
924
+
925
+ **Example**
926
+
927
+ ```ts
928
+ const result = await g8.api.signals.getSocialSettings();
929
+ ```
930
+
931
+ ---
932
+
933
+ <a id="op-getsocialstats"></a>
934
+
935
+ ### `g8.api.signals.getSocialStats(input?)`
936
+
937
+ **Get Social Stats**
938
+
939
+ - HTTP: `GET /api/v1/social-listeners/stats`
940
+ - operationId: `get_social_stats_social_listeners_stats_get` (also callable as `g8.api.call("get_social_stats_social_listeners_stats_get", input)`)
941
+ - Tier: `read`: reads data; safe to call and to retry
942
+ - API-key scope: `intent:read`
943
+
944
+ Match counts, listener counts and platform spend to date.
945
+
946
+ The number to watch against `monthly_credit_cap`.
947
+
948
+ **Input**: none.
949
+
950
+ **Returns** `ApiResponse_SocialPayload_`: the envelope `{ data: SocialPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
951
+
952
+ Other envelope fields: `pagination` (PaginationMeta).
953
+
954
+ **Example**
955
+
956
+ ```ts
957
+ const result = await g8.api.signals.getSocialStats();
958
+ ```
959
+
960
+ ---
961
+
962
+ <a id="op-getxeffectivemode"></a>
963
+
964
+ ### `g8.api.signals.getXEffectiveMode(input?)`
965
+
966
+ **Get X Effective Mode**
967
+
968
+ - HTTP: `GET /api/v1/social-listeners/integrations/x/mode`
969
+ - operationId: `get_x_effective_mode_social_listeners_integrations_x_mode_get` (also callable as `g8.api.call("get_x_effective_mode_social_listeners_integrations_x_mode_get", input)`)
970
+ - Tier: `read`: reads data; safe to call and to retry
971
+ - API-key scope: `intent:read`
972
+
973
+ Which X credentials this org is ACTUALLY polling with, and how much of
974
+ the shared allowance is left.
975
+
976
+ Not the same question as `GET /social-listeners/integrations/x`: an org can
977
+ have credentials stored and still be on shared mode, and an org on shared
978
+ mode is competing for a quota it does not control. This is the number to
979
+ read when listeners stop matching.
980
+
981
+ **Input**: none.
982
+
983
+ **Returns** `ApiResponse_SocialPayload_`: the envelope `{ data: SocialPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
984
+
985
+ Other envelope fields: `pagination` (PaginationMeta).
986
+
987
+ **Example**
988
+
989
+ ```ts
990
+ const result = await g8.api.signals.getXEffectiveMode();
991
+ ```
992
+
993
+ ---
994
+
995
+ <a id="op-getxintegration"></a>
996
+
997
+ ### `g8.api.signals.getXIntegration(input?)`
998
+
999
+ **Get X Integration**
1000
+
1001
+ - HTTP: `GET /api/v1/social-listeners/integrations/x`
1002
+ - operationId: `get_x_integration_social_listeners_integrations_x_get` (also callable as `g8.api.call("get_x_integration_social_listeners_integrations_x_get", input)`)
1003
+ - Tier: `read`: reads data; safe to call and to retry
1004
+ - API-key scope: `intent:read`
1005
+
1006
+ Whether the org has its own X credentials stored, and since when.
1007
+
1008
+ Reports that a connection exists. It does not report what it is - see
1009
+ `POST /social-listeners/integrations/x`.
1010
+
1011
+ **Input**: none.
1012
+
1013
+ **Returns** `ApiResponse_SocialPayload_`: the envelope `{ data: SocialPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1014
+
1015
+ Other envelope fields: `pagination` (PaginationMeta).
1016
+
1017
+ **Example**
1018
+
1019
+ ```ts
1020
+ const result = await g8.api.signals.getXIntegration();
1021
+ ```
1022
+
1023
+ ---
1024
+
1025
+ <a id="op-listabmcompanies"></a>
1026
+
1027
+ ### `g8.api.signals.listAbmCompanies(input?)`
1028
+
1029
+ **List Abm Companies**
1030
+
1031
+ - HTTP: `GET /api/v1/intent/abm/companies`
1032
+ - operationId: `list_abm_companies_intent_abm_companies_get` (also callable as `g8.api.call("list_abm_companies_intent_abm_companies_get", input)`)
1033
+ - Tier: `read`: reads data; safe to call and to retry
1034
+ - API-key scope: `intent:read`
1035
+
1036
+ Accounts showing intent, one scored row per company, with buying-committee coverage.
1037
+
1038
+ **Input**
1039
+
1040
+ | Field | Type | Required | Description |
1041
+ |---|---|---|---|
1042
+ | `query.days` | `integer` | no | Look-back window in days. default `30` |
1043
+ | `query.keyword_ids` | `string \| null` | no | Comma-separated keyword ids to restrict to. |
1044
+ | `query.icp_id` | `string (uuid) \| null` | no | Score against this ICP. |
1045
+ | `query.page` | `integer` | no | default `1` |
1046
+ | `query.limit` | `integer` | no | default `50` |
1047
+ | `query.agFilterModel` | `string \| null` | no | Grid filter model as JSON, passed through unchanged. |
1048
+ | `query.agSortModel` | `string \| null` | no | Grid sort model as JSON (`colId`, `sort`). |
1049
+
1050
+ **Returns** `ApiResponse_IntentPayload_`: the envelope `{ data: IntentPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1051
+
1052
+ Other envelope fields: `pagination` (PaginationMeta).
1053
+
1054
+ **Example**
1055
+
1056
+ ```ts
1057
+ const result = await g8.api.signals.listAbmCompanies();
1058
+ ```
1059
+
1060
+ ---
1061
+
1062
+ <a id="op-listcompanyhiringjobs"></a>
1063
+
1064
+ ### `g8.api.signals.listCompanyHiringJobs(input)`
1065
+
1066
+ **List Company Hiring Jobs**
1067
+
1068
+ - HTTP: `GET /api/v1/hiring-signals/companies/{linkedin_company_id}/jobs`
1069
+ - operationId: `list_company_hiring_jobs_hiring_signals_companies__linkedin_company_id__jobs_get` (also callable as `g8.api.call("list_company_hiring_jobs_hiring_signals_companies__linkedin_company_id__jobs_get", input)`)
1070
+ - Tier: `read`: reads data; safe to call and to retry
1071
+ - API-key scope: `intent:read`
1072
+
1073
+ Recent postings at one company.
1074
+
1075
+ **Input**
1076
+
1077
+ | Field | Type | Required | Description |
1078
+ |---|---|---|---|
1079
+ | `path.linkedin_company_id` | `integer` | yes | LinkedIn company id (lcid). |
1080
+ | `query.limit` | `integer` | no | default `50` |
1081
+ | `query.window_days` | `integer` | no | default `60` |
1082
+ | `query.include_subsidiaries` | `boolean` | no | Expand the lcid to its subsidiaries, so a parent company's view surfaces postings made under a child lcid. On by default because the parent is usually who the customer is selling to. default `true` |
1083
+
1084
+ **Returns** `ApiResponse_JobSearchResponse_`: the envelope `{ data: JobSearchResponse, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1085
+
1086
+ Other envelope fields: `pagination` (PaginationMeta).
1087
+
1088
+ `JobSearchResponse` fields:
1089
+
1090
+ | Field | Type | Required | Description |
1091
+ |---|---|---|---|
1092
+ | `results` | `Array<Record<string, unknown>>` | no | |
1093
+ | `total` | `integer` | no | default `0` |
1094
+
1095
+ **Example**
1096
+
1097
+ ```ts
1098
+ const result = await g8.api.signals.listCompanyHiringJobs({ path: { linkedin_company_id: 123 } });
1099
+ ```
1100
+
1101
+ ---
1102
+
1103
+ <a id="op-listcompanylinkedinposts"></a>
1104
+
1105
+ ### `g8.api.signals.listCompanyLinkedinPosts(input)`
1106
+
1107
+ **List Company Linkedin Posts**
1108
+
1109
+ - HTTP: `GET /api/v1/hiring-signals/companies/{linkedin_company_id}/linkedin-posts`
1110
+ - operationId: `list_company_linkedin_posts_hiring_signals_companies__linkedin_company_id__linkedin_posts_get` (also callable as `g8.api.call("list_company_linkedin_posts_hiring_signals_companies__linkedin_company_id__linkedin_posts_get", input)`)
1111
+ - Tier: `read`: reads data; safe to call and to retry
1112
+ - API-key scope: `intent:read`
1113
+
1114
+ Recent organic LinkedIn posts from one company.
1115
+
1116
+ `window_days` is optional here, unlike on the jobs endpoint: an omitted
1117
+ window means "newest regardless of age", not "default of 60". Defaulting
1118
+ it would silently hide a company that posts rarely.
1119
+
1120
+ **Input**
1121
+
1122
+ | Field | Type | Required | Description |
1123
+ |---|---|---|---|
1124
+ | `path.linkedin_company_id` | `integer` | yes | LinkedIn company id (lcid). |
1125
+ | `query.limit` | `integer` | no | default `50` |
1126
+ | `query.window_days` | `integer \| null` | no | Optional age cap in days. OMIT to get the newest posts regardless of age. |
1127
+
1128
+ **Returns** `ApiResponse_JobSearchResponse_`: the envelope `{ data: JobSearchResponse, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1129
+
1130
+ Other envelope fields: `pagination` (PaginationMeta).
1131
+
1132
+ `JobSearchResponse` fields:
1133
+
1134
+ | Field | Type | Required | Description |
1135
+ |---|---|---|---|
1136
+ | `results` | `Array<Record<string, unknown>>` | no | |
1137
+ | `total` | `integer` | no | default `0` |
1138
+
1139
+ **Example**
1140
+
1141
+ ```ts
1142
+ const result = await g8.api.signals.listCompanyLinkedinPosts({ path: { linkedin_company_id: 123 } });
1143
+ ```
1144
+
1145
+ ---
1146
+
1147
+ <a id="op-listjobchangesignals"></a>
1148
+
1149
+ ### `g8.api.signals.listJobChangeSignals(input?)`
1150
+
1151
+ **List Job Change Signals**
1152
+
1153
+ - HTTP: `GET /api/v1/hiring-signals/job-changes`
1154
+ - operationId: `list_job_change_signals_hiring_signals_job_changes_get` (also callable as `g8.api.call("list_job_change_signals_hiring_signals_job_changes_get", input)`)
1155
+ - Tier: `read`: reads data; safe to call and to retry
1156
+ - API-key scope: `intent:read`
1157
+
1158
+ Contacts who changed employer.
1159
+
1160
+ Identifying fields are REDACTED unless the key's user holds a Signals
1161
+ write capability - these are named people who moved, which is exactly the
1162
+ data a read-only role is not meant to export. The capability is resolved
1163
+ from the same principal the browser resolves it from.
1164
+
1165
+ **Input**
1166
+
1167
+ | Field | Type | Required | Description |
1168
+ |---|---|---|---|
1169
+ | `query.contact_id` | `integer \| null` | no | Filter to a single contact. |
1170
+ | `query.listener_id` | `string \| null` | no | Filter to a single Talent Moves listener. |
1171
+ | `query.since` | `string \| null` | no | Only events detected at or after this ISO timestamp. |
1172
+ | `query.limit` | `integer` | no | default `50` |
1173
+ | `query.offset` | `integer` | no | default `0` |
1174
+
1175
+ **Returns** `ApiResponse_JobChangeSignalsResponse_`: the envelope `{ data: JobChangeSignalsResponse, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1176
+
1177
+ Other envelope fields: `pagination` (PaginationMeta).
1178
+
1179
+ `JobChangeSignalsResponse` fields:
1180
+
1181
+ | Field | Type | Required | Description |
1182
+ |---|---|---|---|
1183
+ | `signals` | `Array<Record<string, unknown>>` | no | |
1184
+ | `total` | `integer` | no | default `0` |
1185
+
1186
+ **Example**
1187
+
1188
+ ```ts
1189
+ const result = await g8.api.signals.listJobChangeSignals();
1190
+ ```
1191
+
1192
+ ---
1193
+
1194
+ <a id="op-listlisteners"></a>
1195
+
1196
+ ### `g8.api.signals.listListeners(input?)`
1197
+
1198
+ **List Listeners**
1199
+
1200
+ - HTTP: `GET /api/v1/social-listeners`
1201
+ - operationId: `list_listeners_social_listeners_get` (also callable as `g8.api.call("list_listeners_social_listeners_get", input)`)
1202
+ - Tier: `read`: reads data; safe to call and to retry
1203
+ - API-key scope: `intent:read`
1204
+
1205
+ Every listener in the org, with its state.
1206
+
1207
+ **Input**: none.
1208
+
1209
+ **Returns** `ApiResponse_SocialCollection_`: the envelope `{ data: SocialCollection, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1210
+
1211
+ Other envelope fields: `pagination` (PaginationMeta).
1212
+
1213
+ `SocialCollection` fields:
1214
+
1215
+ | Field | Type | Required | Description |
1216
+ |---|---|---|---|
1217
+ | `items` | `Array<unknown>` | no | |
1218
+
1219
+ **Example**
1220
+
1221
+ ```ts
1222
+ const result = await g8.api.signals.listListeners();
1223
+ ```
1224
+
1225
+ ---
1226
+
1227
+ <a id="op-listpostsbycontact"></a>
1228
+
1229
+ ### `g8.api.signals.listPostsByContact(input)`
1230
+
1231
+ **List Posts By Contact**
1232
+
1233
+ - HTTP: `GET /api/v1/social-listeners/posts/by-contact/{contact_id}`
1234
+ - operationId: `list_posts_by_contact_social_listeners_posts_by_contact__contact_id__get` (also callable as `g8.api.call("list_posts_by_contact_social_listeners_posts_by_contact__contact_id__get", input)`)
1235
+ - Tier: `read`: reads data; safe to call and to retry
1236
+ - API-key scope: `intent:read`
1237
+
1238
+ Everything one graph8 contact has posted that a listener matched.
1239
+
1240
+ Matches on the resolved contact link first and falls back to a
1241
+ case-insensitive handle match, so it still finds posts recorded before the
1242
+ author was resolved to a contact.
1243
+
1244
+ 404 for a contact outside the key's record scope - the same answer as a
1245
+ contact that does not exist, so the two cannot be told apart.
1246
+
1247
+ **Input**
1248
+
1249
+ | Field | Type | Required | Description |
1250
+ |---|---|---|---|
1251
+ | `path.contact_id` | `integer` | yes | Contact id. |
1252
+ | `query.limit` | `integer` | no | default `100` |
1253
+
1254
+ **Returns** `ApiResponse_SocialCollection_`: the envelope `{ data: SocialCollection, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1255
+
1256
+ Other envelope fields: `pagination` (PaginationMeta).
1257
+
1258
+ `SocialCollection` fields:
1259
+
1260
+ | Field | Type | Required | Description |
1261
+ |---|---|---|---|
1262
+ | `items` | `Array<unknown>` | no | |
1263
+
1264
+ **Example**
1265
+
1266
+ ```ts
1267
+ const result = await g8.api.signals.listPostsByContact({ path: { contact_id: 123 } });
1268
+ ```
1269
+
1270
+ ---
1271
+
1272
+ <a id="op-listsourcelists"></a>
1273
+
1274
+ ### `g8.api.signals.listSourceLists(input?)`
1275
+
1276
+ **List Source Lists**
1277
+
1278
+ - HTTP: `GET /api/v1/social-listeners/source-lists`
1279
+ - operationId: `list_source_lists_social_listeners_source_lists_get` (also callable as `g8.api.call("list_source_lists_social_listeners_source_lists_get", input)`)
1280
+ - Tier: `read`: reads data; safe to call and to retry
1281
+ - API-key scope: `intent:read`
1282
+
1283
+ graph8 lists that can be used as the source for `/bulk-from-list`.
1284
+
1285
+ **Input**
1286
+
1287
+ | Field | Type | Required | Description |
1288
+ |---|---|---|---|
1289
+ | `query.audience_type` | `string \| null` | no | Filter to one audience type. |
1290
+ | `query.active_only` | `boolean` | no | Only lists still in use. default `true` |
1291
+
1292
+ **Returns** `ApiResponse_SocialCollection_`: the envelope `{ data: SocialCollection, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1293
+
1294
+ Other envelope fields: `pagination` (PaginationMeta).
1295
+
1296
+ `SocialCollection` fields:
1297
+
1298
+ | Field | Type | Required | Description |
1299
+ |---|---|---|---|
1300
+ | `items` | `Array<unknown>` | no | |
1301
+
1302
+ **Example**
1303
+
1304
+ ```ts
1305
+ const result = await g8.api.signals.listSourceLists();
1306
+ ```
1307
+
1308
+ ---
1309
+
1310
+ <a id="op-listtopengagedaccounts"></a>
1311
+
1312
+ ### `g8.api.signals.listTopEngagedAccounts(input?)`
1313
+
1314
+ **List Top Engaged Accounts**
1315
+
1316
+ - HTTP: `GET /api/v1/social-listeners/engagements/top-accounts`
1317
+ - operationId: `list_top_engaged_accounts_social_listeners_engagements_top_accounts_get` (also callable as `g8.api.call("list_top_engaged_accounts_social_listeners_engagements_top_accounts_get", input)`)
1318
+ - Tier: `read`: reads data; safe to call and to retry
1319
+ - API-key scope: `intent:read`
1320
+
1321
+ The accounts that engage with you most often.
1322
+
1323
+ The warm-audience view: someone who has commented on four of your posts is
1324
+ a different prospect from someone who liked one.
1325
+
1326
+ **Input**
1327
+
1328
+ | Field | Type | Required | Description |
1329
+ |---|---|---|---|
1330
+ | `query.days` | `integer` | no | default `30` |
1331
+ | `query.platform` | `"x" \| "linkedin" \| "reddit" \| "instagram" \| "youtube" \| null` | no | |
1332
+ | `query.min_posts` | `integer` | no | Only accounts that engaged this often. default `2` |
1333
+ | `query.limit` | `integer` | no | default `50` |
1334
+
1335
+ **Returns** `ApiResponse_SocialCollection_`: the envelope `{ data: SocialCollection, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1336
+
1337
+ Other envelope fields: `pagination` (PaginationMeta).
1338
+
1339
+ `SocialCollection` fields:
1340
+
1341
+ | Field | Type | Required | Description |
1342
+ |---|---|---|---|
1343
+ | `items` | `Array<unknown>` | no | |
1344
+
1345
+ **Example**
1346
+
1347
+ ```ts
1348
+ const result = await g8.api.signals.listTopEngagedAccounts();
1349
+ ```
1350
+
1351
+ ---
1352
+
1353
+ <a id="op-markpost"></a>
1354
+
1355
+ ### `g8.api.signals.markPost(input)`
1356
+
1357
+ **Mark Post**
1358
+
1359
+ - HTTP: `POST /api/v1/social-listeners/posts/{post_id}/mark`
1360
+ - operationId: `mark_post_social_listeners_posts__post_id__mark_post` (also callable as `g8.api.call("mark_post_social_listeners_posts__post_id__mark_post", input)`)
1361
+ - Tier: `billable`: spends credits; the SDK never blindly retries it; confirm cost before bulk use
1362
+ - API-key scope: `intent:run`
1363
+
1364
+ Triage a matched post as reviewed or dismissed.
1365
+
1366
+ `platform` is part of the identity, not a filter - the same id means
1367
+ different posts on different platforms.
1368
+
1369
+ **Input**
1370
+
1371
+ | Field | Type | Required | Description |
1372
+ |---|---|---|---|
1373
+ | `path.post_id` | `string` | yes | The post's platform-native id. |
1374
+ | `body` | `MarkPostRequest` | yes | Request body; fields below. |
1375
+ | `query.platform` | `"x" \| "linkedin" \| "reddit" \| "instagram" \| "youtube"` | no | Which platform the post id belongs to. default `"x"` |
1376
+
1377
+ Body fields (`MarkPostRequest`):
1378
+
1379
+ | Field | Type | Required | Description |
1380
+ |---|---|---|---|
1381
+ | `body.status` | `"reviewed" \| "dismissed"` | yes | |
1382
+
1383
+ **Returns** `ApiResponse_SocialPayload_`: the envelope `{ data: SocialPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1384
+
1385
+ Other envelope fields: `pagination` (PaginationMeta).
1386
+
1387
+ **Example**
1388
+
1389
+ ```ts
1390
+ // billable: spends credits; the SDK never blindly retries it; confirm cost before bulk use.
1391
+ const result = await g8.api.signals.markPost({ path: { post_id: "id" }, body: { status: "reviewed" } });
1392
+ ```
1393
+
1394
+ ---
1395
+
1396
+ <a id="op-matchjobchangesignals"></a>
1397
+
1398
+ ### `g8.api.signals.matchJobChangeSignals(input)`
1399
+
1400
+ **Match Job Change Signals**
1401
+
1402
+ - HTTP: `POST /api/v1/hiring-signals/job-changes/match`
1403
+ - operationId: `match_job_change_signals_hiring_signals_job_changes_match_post` (also callable as `g8.api.call("match_job_change_signals_hiring_signals_job_changes_match_post", input)`)
1404
+ - Tier: `billable`: spends credits; the SDK never blindly retries it; confirm cost before bulk use
1405
+ - API-key scope: `intent:run`
1406
+
1407
+ Which of these LinkedIn profiles changed job in the last 90 days.
1408
+
1409
+ A lookup, not a search: it answers a question about a list the caller
1410
+ already has, which is why it takes URLs rather than filters.
1411
+
1412
+ **Input**
1413
+
1414
+ | Field | Type | Required | Description |
1415
+ |---|---|---|---|
1416
+ | `body` | `JobChangeMatchRequest` | yes | Request body; fields below. |
1417
+
1418
+ Body fields (`JobChangeMatchRequest`):
1419
+
1420
+ | Field | Type | Required | Description |
1421
+ |---|---|---|---|
1422
+ | `body.linkedin_urls` | `Array<string>` | yes | LinkedIn profile URLs to match against the last 90 days of job-change events. min items 1, max items 1000 |
1423
+
1424
+ **Returns** `ApiResponse_JobChangeSignalsResponse_`: the envelope `{ data: JobChangeSignalsResponse, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1425
+
1426
+ Other envelope fields: `pagination` (PaginationMeta).
1427
+
1428
+ `JobChangeSignalsResponse` fields:
1429
+
1430
+ | Field | Type | Required | Description |
1431
+ |---|---|---|---|
1432
+ | `signals` | `Array<Record<string, unknown>>` | no | |
1433
+ | `total` | `integer` | no | default `0` |
1434
+
1435
+ **Example**
1436
+
1437
+ ```ts
1438
+ // billable: spends credits; the SDK never blindly retries it; confirm cost before bulk use.
1439
+ const result = await g8.api.signals.matchJobChangeSignals({ body: { linkedin_urls: ["https://example.com"] } });
1440
+ ```
1441
+
1442
+ ---
1443
+
1444
+ <a id="op-previewkeywordurls"></a>
1445
+
1446
+ ### `g8.api.signals.previewKeywordUrls(input)`
1447
+
1448
+ **Preview Keyword Urls**
1449
+
1450
+ - HTTP: `POST /api/v1/intent/keywords/preview`
1451
+ - operationId: `preview_keyword_urls_intent_keywords_preview_post` (also callable as `g8.api.call("preview_keyword_urls_intent_keywords_preview_post", input)`)
1452
+ - Tier: `read`: reads data; safe to call and to retry
1453
+ - API-key scope: `intent:read`
1454
+
1455
+ Estimate how many URLs a keyword and filters would match, WITHOUT creating it.
1456
+
1457
+ Reads pages already crawled; starts no crawl and creates nothing. Returns
1458
+ `estimated_url_count`, `baseline_url_count` and a `filter_impact` breakdown.
1459
+
1460
+ **Input**
1461
+
1462
+ | Field | Type | Required | Description |
1463
+ |---|---|---|---|
1464
+ | `body` | `PreviewKeywordUrlsRequest` | yes | Request body; fields below. |
1465
+
1466
+ Body fields (`PreviewKeywordUrlsRequest`):
1467
+
1468
+ | Field | Type | Required | Description |
1469
+ |---|---|---|---|
1470
+ | `body.keyword` | `string` | yes | The keyword to preview. min length 1 |
1471
+ | `body.search_filters` | `KeywordFilters` | no | Filters to preview it with. |
1472
+
1473
+ **Returns** `ApiResponse_IntentPayload_`: the envelope `{ data: IntentPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1474
+
1475
+ Other envelope fields: `pagination` (PaginationMeta).
1476
+
1477
+ **Example**
1478
+
1479
+ ```ts
1480
+ const result = await g8.api.signals.previewKeywordUrls({ body: { keyword: "example" } });
1481
+ ```
1482
+
1483
+ ---
1484
+
1485
+ <a id="op-previewlistenercost"></a>
1486
+
1487
+ ### `g8.api.signals.previewListenerCost(input)`
1488
+
1489
+ **Preview Listener Cost**
1490
+
1491
+ - HTTP: `POST /api/v1/social-listeners/preview-cost`
1492
+ - operationId: `preview_listener_cost_social_listeners_preview_cost_post` (also callable as `g8.api.call("preview_listener_cost_social_listeners_preview_cost_post", input)`)
1493
+ - Tier: `read`: reads data; safe to call and to retry
1494
+ - API-key scope: `intent:read`
1495
+
1496
+ What a listener WOULD cost per month. CHARGES NOTHING.
1497
+
1498
+ A pure estimate: it samples at most ten results to project a posts-per-day
1499
+ rate, caches the answer for an hour, and returns arithmetic.
1500
+ `credits_per_month_estimate` is a projection for a listener that does not
1501
+ exist yet, not a debit.
1502
+
1503
+ Tiered `read` for that reason, so a read-only key can find out what
1504
+ something costs before anyone commits to it. POST only because the query is
1505
+ a body.
1506
+
1507
+ **Input**
1508
+
1509
+ | Field | Type | Required | Description |
1510
+ |---|---|---|---|
1511
+ | `body` | `PreviewCostRequest` | yes | Request body; fields below. |
1512
+
1513
+ Body fields (`PreviewCostRequest`):
1514
+
1515
+ | Field | Type | Required | Description |
1516
+ |---|---|---|---|
1517
+ | `body.listener_type` | `"brand" \| "competitor" \| "keyword" \| "engagement" \| "user"` | yes | |
1518
+ | `body.platform` | `"x" \| "linkedin" \| "reddit" \| "instagram" \| "youtube"` | no | default `"x"` |
1519
+ | `body.poll_interval_sec` | `integer` | no | The interval to cost. Shorter intervals cost more. default `600`, min 60 |
1520
+ | `body.query` | `string \| null` | no | |
1521
+ | `body.target_handle` | `string \| null` | no | |
1522
+
1523
+ **Returns** `ApiResponse_SocialPayload_`: the envelope `{ data: SocialPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1524
+
1525
+ Other envelope fields: `pagination` (PaginationMeta).
1526
+
1527
+ **Example**
1528
+
1529
+ ```ts
1530
+ const result = await g8.api.signals.previewListenerCost({ body: { listener_type: "brand" } });
1531
+ ```
1532
+
1533
+ ---
1534
+
1535
+ <a id="op-proposehiringkeywords"></a>
1536
+
1537
+ ### `g8.api.signals.proposeHiringKeywords(input)`
1538
+
1539
+ **Propose Hiring Keywords**
1540
+
1541
+ - HTTP: `POST /api/v1/intent/keywords/auto-seed-proposals`
1542
+ - operationId: `propose_hiring_keywords_intent_keywords_auto_seed_proposals_post` (also callable as `g8.api.call("propose_hiring_keywords_intent_keywords_auto_seed_proposals_post", input)`)
1543
+ - Tier: `billable`: spends credits; the SDK never blindly retries it; confirm cost before bulk use
1544
+ - API-key scope: `intent:run`
1545
+
1546
+ Propose hiring listeners from the org's own personas and ICP.
1547
+
1548
+ PROPOSALS, not keywords: nothing is created - add the ones you want with
1549
+ `POST /intent/keywords/add`. Generating them runs a model, so the org must
1550
+ have credit (402 otherwise). Falls back to a starter set when the org has no
1551
+ context documents yet.
1552
+
1553
+ **Input**
1554
+
1555
+ | Field | Type | Required | Description |
1556
+ |---|---|---|---|
1557
+ | `body` | `AutoSeedProposalsRequest` | yes | Request body; fields below. |
1558
+
1559
+ Body fields (`AutoSeedProposalsRequest`):
1560
+
1561
+ | Field | Type | Required | Description |
1562
+ |---|---|---|---|
1563
+ | `body.signal_type` | `"jobs" \| "job_changes"` | no | `jobs` (Hiring Wave) or `job_changes` (Talent Moves). default `"jobs"` |
1564
+
1565
+ **Returns** `ApiResponse_IntentPayload_`: the envelope `{ data: IntentPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1566
+
1567
+ Other envelope fields: `pagination` (PaginationMeta).
1568
+
1569
+ **Example**
1570
+
1571
+ ```ts
1572
+ // billable: spends credits; the SDK never blindly retries it; confirm cost before bulk use.
1573
+ const result = await g8.api.signals.proposeHiringKeywords({ body: {} });
1574
+ ```
1575
+
1576
+ ---
1577
+
1578
+ <a id="op-resolvehiringcompanyids"></a>
1579
+
1580
+ ### `g8.api.signals.resolveHiringCompanyIds(input)`
1581
+
1582
+ **Resolve Hiring Company Ids**
1583
+
1584
+ - HTTP: `POST /api/v1/hiring-signals/companies/resolve-ids`
1585
+ - operationId: `resolve_hiring_company_ids_hiring_signals_companies_resolve_ids_post` (also callable as `g8.api.call("resolve_hiring_company_ids_hiring_signals_companies_resolve_ids_post", input)`)
1586
+ - Tier: `billable`: spends credits; the SDK never blindly retries it; confirm cost before bulk use
1587
+ - API-key scope: `intent:run`
1588
+
1589
+ Turn LinkedIn company ids into graph8 company ids.
1590
+
1591
+ This is the step that makes a Hiring Signals result usable: the search
1592
+ returns lcids, and building a list or enrolling a sequence needs graph8
1593
+ ids. The handler caps the input server-side regardless of what is sent.
1594
+
1595
+ **Input**
1596
+
1597
+ | Field | Type | Required | Description |
1598
+ |---|---|---|---|
1599
+ | `body` | `ResolveCompanyIdsRequest` | yes | Request body; fields below. |
1600
+
1601
+ Body fields (`ResolveCompanyIdsRequest`):
1602
+
1603
+ | Field | Type | Required | Description |
1604
+ |---|---|---|---|
1605
+ | `body.linkedin_company_ids` | `Array<integer>` | no | |
1606
+
1607
+ **Returns** `ApiResponse_dict_`: the envelope `{ data: Record<string, unknown>, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1608
+
1609
+ Other envelope fields: `pagination` (PaginationMeta).
1610
+
1611
+ **Example**
1612
+
1613
+ ```ts
1614
+ // billable: spends credits; the SDK never blindly retries it; confirm cost before bulk use.
1615
+ const result = await g8.api.signals.resolveHiringCompanyIds({ body: {} });
1616
+ ```
1617
+
1618
+ ---
1619
+
1620
+ <a id="op-resolvejobsforkeyword"></a>
1621
+
1622
+ ### `g8.api.signals.resolveJobsForKeyword(input)`
1623
+
1624
+ **Resolve Jobs For Keyword**
1625
+
1626
+ - HTTP: `POST /api/v1/intent/keywords/{keyword_id}/job-resolution`
1627
+ - operationId: `resolve_jobs_for_keyword_intent_keywords__keyword_id__job_resolution_post` (also callable as `g8.api.call("resolve_jobs_for_keyword_intent_keywords__keyword_id__job_resolution_post", input)`)
1628
+ - Tier: `billable`: spends credits; the SDK never blindly retries it; confirm cost before bulk use
1629
+ - API-key scope: `intent:run`
1630
+
1631
+ Run the jobs resolver for this keyword NOW, instead of waiting for the hourly run.
1632
+
1633
+ Synchronous: returns the decision makers and recruiters emitted and the
1634
+ wall time taken.
1635
+
1636
+ **Input**
1637
+
1638
+ | Field | Type | Required | Description |
1639
+ |---|---|---|---|
1640
+ | `path.keyword_id` | `string (uuid)` | yes | The keyword's id. |
1641
+
1642
+ **Returns** `ApiResponse_IntentPayload_`: the envelope `{ data: IntentPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1643
+
1644
+ Other envelope fields: `pagination` (PaginationMeta).
1645
+
1646
+ **Example**
1647
+
1648
+ ```ts
1649
+ // billable: spends credits; the SDK never blindly retries it; confirm cost before bulk use.
1650
+ const result = await g8.api.signals.resolveJobsForKeyword({ path: { keyword_id: "00000000-0000-0000-0000-000000000000" } });
1651
+ ```
1652
+
1653
+ ---
1654
+
1655
+ <a id="op-rollupabmcompanies"></a>
1656
+
1657
+ ### `g8.api.signals.rollupAbmCompanies(input)`
1658
+
1659
+ **Rollup Abm Companies**
1660
+
1661
+ - HTTP: `POST /api/v1/intent/abm/rollup`
1662
+ - operationId: `rollup_abm_companies_intent_abm_rollup_post` (also callable as `g8.api.call("rollup_abm_companies_intent_abm_rollup_post", input)`)
1663
+ - Tier: `read`: reads data; safe to call and to retry
1664
+ - API-key scope: `intent:read`
1665
+
1666
+ Account strength, high-intent flag and persona coverage for up to 500 named companies.
1667
+
1668
+ A read: POST only because the id list is a body. Returned under `rollups`,
1669
+ keyed by company id.
1670
+
1671
+ **Input**
1672
+
1673
+ | Field | Type | Required | Description |
1674
+ |---|---|---|---|
1675
+ | `body` | `AbmRollupRequest` | yes | Request body; fields below. |
1676
+
1677
+ Body fields (`AbmRollupRequest`):
1678
+
1679
+ | Field | Type | Required | Description |
1680
+ |---|---|---|---|
1681
+ | `body.company_ids` | `Array<integer>` | yes | Company ids, at most 500 per call - the app refuses more; chunk larger sets. max items 500 |
1682
+ | `body.days` | `integer` | no | Look-back window in days. default `30` |
1683
+
1684
+ **Returns** `ApiResponse_IntentPayload_`: the envelope `{ data: IntentPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1685
+
1686
+ Other envelope fields: `pagination` (PaginationMeta).
1687
+
1688
+ **Example**
1689
+
1690
+ ```ts
1691
+ const result = await g8.api.signals.rollupAbmCompanies({ body: { company_ids: [123] } });
1692
+ ```
1693
+
1694
+ ---
1695
+
1696
+ <a id="op-saveintenttocontactmetadata"></a>
1697
+
1698
+ ### `g8.api.signals.saveIntentToContactMetadata(input)`
1699
+
1700
+ **Save Intent To Contact Metadata**
1701
+
1702
+ - HTTP: `POST /api/v1/intent/contacts/metadata`
1703
+ - operationId: `save_intent_to_contact_metadata_intent_contacts_metadata_post` (also callable as `g8.api.call("save_intent_to_contact_metadata_intent_contacts_metadata_post", input)`)
1704
+ - Tier: `billable`: spends credits; the SDK never blindly retries it; confirm cost before bulk use
1705
+ - API-key scope: `intent:run`
1706
+
1707
+ Write each contact's resolved intent onto the contact record, in the background.
1708
+
1709
+ 202: the work runs after the response, on THIS request's own background
1710
+ tasks. The org is always the key's own; `force_update` overwrites intent
1711
+ metadata already present instead of only filling gaps.
1712
+
1713
+ **Input**
1714
+
1715
+ | Field | Type | Required | Description |
1716
+ |---|---|---|---|
1717
+ | `body` | `SaveIntentToMetadataRequest` | yes | Request body; fields below. |
1718
+
1719
+ Body fields (`SaveIntentToMetadataRequest`):
1720
+
1721
+ | Field | Type | Required | Description |
1722
+ |---|---|---|---|
1723
+ | `body.force_update` | `boolean` | no | Overwrite intent metadata already on a contact, rather than only filling gaps. default `false` |
1724
+
1725
+ **Returns** `ApiResponse_IntentPayload_`: the envelope `{ data: IntentPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1726
+
1727
+ Other envelope fields: `pagination` (PaginationMeta).
1728
+
1729
+ **Example**
1730
+
1731
+ ```ts
1732
+ // billable: spends credits; the SDK never blindly retries it; confirm cost before bulk use.
1733
+ const result = await g8.api.signals.saveIntentToContactMetadata({ body: {} });
1734
+ ```
1735
+
1736
+ ---
1737
+
1738
+ <a id="op-savekeywordsyncconfig"></a>
1739
+
1740
+ ### `g8.api.signals.saveKeywordSyncConfig(input)`
1741
+
1742
+ **Save Keyword Sync Config**
1743
+
1744
+ - HTTP: `PATCH /api/v1/intent/keywords/{keyword_id}/sync-config`
1745
+ - operationId: `save_keyword_sync_config_intent_keywords__keyword_id__sync_config_patch` (also callable as `g8.api.call("save_keyword_sync_config_intent_keywords__keyword_id__sync_config_patch", input)`)
1746
+ - Tier: `billable`: spends credits; the SDK never blindly retries it; confirm cost before bulk use
1747
+ - API-key scope: `intent:run`
1748
+
1749
+ Wire this keyword to a list (upsert).
1750
+
1751
+ `auto_sync_enabled: true` is the consequential field: from then on the
1752
+ keyword's matches are pushed into `list_id` on a schedule, and anything
1753
+ downstream of that list runs on the people it found.
1754
+
1755
+ **Input**
1756
+
1757
+ | Field | Type | Required | Description |
1758
+ |---|---|---|---|
1759
+ | `path.keyword_id` | `string (uuid)` | yes | The keyword's id. |
1760
+ | `body` | `KeywordSyncConfigRequest` | yes | Request body; fields below. |
1761
+
1762
+ Body fields (`KeywordSyncConfigRequest`):
1763
+
1764
+ | Field | Type | Required | Description |
1765
+ |---|---|---|---|
1766
+ | `body.auto_sync_enabled` | `boolean` | no | Push on a schedule, without anyone calling anything, rather than only on request. default `false` |
1767
+ | `body.committee_id` | `string (uuid) \| null` | no | Buying committee whose personas are exported. |
1768
+ | `body.export_mode` | `"signals_only" \| "icp_plus_signals" \| "all_icp_personas"` | no | `signals_only` exports only the people a signal named; `icp_plus_signals` adds the ICP's personas at those companies; `all_icp_personas` exports every persona regardless of signal. default `"icp_plus_signals"` |
1769
+ | `body.icp_id` | `string (uuid) \| null` | no | Score matches against this ICP. |
1770
+ | `body.list_id` | `integer \| null` | no | The list matches are pushed into. |
1771
+
1772
+ **Returns** `ApiResponse_IntentPayload_`: the envelope `{ data: IntentPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1773
+
1774
+ Other envelope fields: `pagination` (PaginationMeta).
1775
+
1776
+ **Example**
1777
+
1778
+ ```ts
1779
+ // billable: spends credits; the SDK never blindly retries it; confirm cost before bulk use.
1780
+ const result = await g8.api.signals.saveKeywordSyncConfig({
1781
+ path: { keyword_id: "00000000-0000-0000-0000-000000000000" },
1782
+ body: {},
1783
+ });
1784
+ ```
1785
+
1786
+ ---
1787
+
1788
+ <a id="op-savepostauthorascontact"></a>
1789
+
1790
+ ### `g8.api.signals.savePostAuthorAsContact(input)`
1791
+
1792
+ **Save Post Author As Contact**
1793
+
1794
+ - HTTP: `POST /api/v1/social-listeners/posts/{post_id}/save-contact`
1795
+ - operationId: `save_post_author_as_contact_social_listeners_posts__post_id__save_contact_post` (also callable as `g8.api.call("save_post_author_as_contact_social_listeners_posts__post_id__save_contact_post", input)`)
1796
+ - Tier: `billable`: spends credits; the SDK never blindly retries it; confirm cost before bulk use
1797
+ - API-key scope: `intent:run`
1798
+
1799
+ Turn one post's author into a graph8 contact.
1800
+
1801
+ Resolves an existing contact where there is one rather than duplicating.
1802
+ No enrichment happens here and no credit is spent - the contact is created
1803
+ from what the post already carries.
1804
+
1805
+ **Input**
1806
+
1807
+ | Field | Type | Required | Description |
1808
+ |---|---|---|---|
1809
+ | `path.post_id` | `string` | yes | The post's platform-native id. |
1810
+ | `query.platform` | `"x" \| "linkedin" \| "reddit" \| "instagram" \| "youtube"` | no | default `"x"` |
1811
+
1812
+ **Returns** `ApiResponse_SocialPayload_`: the envelope `{ data: SocialPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1813
+
1814
+ Other envelope fields: `pagination` (PaginationMeta).
1815
+
1816
+ **Example**
1817
+
1818
+ ```ts
1819
+ // billable: spends credits; the SDK never blindly retries it; confirm cost before bulk use.
1820
+ const result = await g8.api.signals.savePostAuthorAsContact({ path: { post_id: "id" } });
1821
+ ```
1822
+
1823
+ ---
1824
+
1825
+ <a id="op-searchhiringaggregators"></a>
1826
+
1827
+ ### `g8.api.signals.searchHiringAggregators(input)`
1828
+
1829
+ **Search Hiring Aggregators**
1830
+
1831
+ - HTTP: `POST /api/v1/hiring-signals/aggregators`
1832
+ - operationId: `search_hiring_aggregators_hiring_signals_aggregators_post` (also callable as `g8.api.call("search_hiring_aggregators_hiring_signals_aggregators_post", input)`)
1833
+ - Tier: `billable`: spends credits; the SDK never blindly retries it; confirm cost before bulk use
1834
+ - API-key scope: `intent:run`
1835
+
1836
+ What `exclude_aggregators` suppressed.
1837
+
1838
+ The audit trail for the suppression: a job board is not a company that is
1839
+ hiring, but a caller should be able to see what was dropped rather than
1840
+ take it on trust.
1841
+
1842
+ **Input**
1843
+
1844
+ | Field | Type | Required | Description |
1845
+ |---|---|---|---|
1846
+ | `body` | `JobSearchRequest` | yes | Request body; fields below. |
1847
+
1848
+ Body fields (`JobSearchRequest`):
1849
+
1850
+ | Field | Type | Required | Description |
1851
+ |---|---|---|---|
1852
+ | `body.keywords` | `Array<string>` | yes | Job-title keywords. OR semantics - any match counts. min items 1 |
1853
+ | `body.contacts_per_company` | `integer` | no | default `10`, min 1, max 50 |
1854
+ | `body.exclude_aggregators` | `boolean` | no | Drop postings from job-board aggregators. On by default because an aggregator is not a company that is hiring - it is a company that lists other people's jobs. `/jobs/search/aggregators` returns exactly what this suppressed, so a caller can audit it. default `true` |
1855
+ | `body.include_recruiters` | `boolean` | no | Run the recruiter aggregation and enrichment hop. Set false to skip two round-trips when only Companies and Decision-makers are needed. default `true` |
1856
+ | `body.limit` | `integer` | no | Page size. Capped at 200 to bound the ClickHouse cost. default `50`, min 1, max 200 |
1857
+ | `body.location_contains` | `string \| null` | no | Free-text token matched case-insensitively against the job location. |
1858
+ | `body.offset` | `integer` | no | default `0`, min 0 |
1859
+ | `body.parent_linkedin_company_id` | `integer \| null` | no | Scope to one parent company and its subsidiaries. Omit to search everywhere. |
1860
+ | `body.per_company_cap` | `integer` | no | Max postings counted per company. default `50`, min 1, max 10000 |
1861
+ | `body.persona_department` | `Array<string> \| null` | no | Decision-maker department filter. |
1862
+ | `body.persona_seniority` | `Array<string> \| null` | no | Decision-maker seniority filter. |
1863
+ | `body.persona_title_contains` | `string \| null` | no | Decision-maker title substring filter. |
1864
+ | `body.recruiter_limit` | `integer` | no | Recruiter paging, INDEPENDENT of `limit`/`offset`: one recruiter can serve many companies, so the two counts diverge and a caller can page one tab without touching the other. default `50`, min 1, max 200 |
1865
+ | `body.recruiter_offset` | `integer` | no | default `0`, min 0 |
1866
+ | `body.window_days` | `integer` | no | How far back to look for postings. default `30`, min 1, max 365 |
1867
+
1868
+ **Returns** `ApiResponse_JobSearchResponse_`: the envelope `{ data: JobSearchResponse, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1869
+
1870
+ Other envelope fields: `pagination` (PaginationMeta).
1871
+
1872
+ `JobSearchResponse` fields:
1873
+
1874
+ | Field | Type | Required | Description |
1875
+ |---|---|---|---|
1876
+ | `results` | `Array<Record<string, unknown>>` | no | |
1877
+ | `total` | `integer` | no | default `0` |
1878
+
1879
+ **Example**
1880
+
1881
+ ```ts
1882
+ // billable: spends credits; the SDK never blindly retries it; confirm cost before bulk use.
1883
+ const result = await g8.api.signals.searchHiringAggregators({ body: { keywords: ["example"] } });
1884
+ ```
1885
+
1886
+ ---
1887
+
1888
+ <a id="op-searchhiringcompanies"></a>
1889
+
1890
+ ### `g8.api.signals.searchHiringCompanies(input)`
1891
+
1892
+ **Search Hiring Companies**
1893
+
1894
+ - HTTP: `POST /api/v1/hiring-signals/companies`
1895
+ - operationId: `search_hiring_companies_hiring_signals_companies_post` (also callable as `g8.api.call("search_hiring_companies_hiring_signals_companies_post", input)`)
1896
+ - Tier: `billable`: spends credits; the SDK never blindly retries it; confirm cost before bulk use
1897
+ - API-key scope: `intent:run`
1898
+
1899
+ The companies behind those postings, rolled up.
1900
+
1901
+ `per_company_cap` bounds how many of one company's postings count toward
1902
+ its score, so a company with 400 open roles does not drown the ranking.
1903
+
1904
+ **Input**
1905
+
1906
+ | Field | Type | Required | Description |
1907
+ |---|---|---|---|
1908
+ | `body` | `JobSearchRequest` | yes | Request body; fields below. |
1909
+
1910
+ Body fields (`JobSearchRequest`):
1911
+
1912
+ | Field | Type | Required | Description |
1913
+ |---|---|---|---|
1914
+ | `body.keywords` | `Array<string>` | yes | Job-title keywords. OR semantics - any match counts. min items 1 |
1915
+ | `body.contacts_per_company` | `integer` | no | default `10`, min 1, max 50 |
1916
+ | `body.exclude_aggregators` | `boolean` | no | Drop postings from job-board aggregators. On by default because an aggregator is not a company that is hiring - it is a company that lists other people's jobs. `/jobs/search/aggregators` returns exactly what this suppressed, so a caller can audit it. default `true` |
1917
+ | `body.include_recruiters` | `boolean` | no | Run the recruiter aggregation and enrichment hop. Set false to skip two round-trips when only Companies and Decision-makers are needed. default `true` |
1918
+ | `body.limit` | `integer` | no | Page size. Capped at 200 to bound the ClickHouse cost. default `50`, min 1, max 200 |
1919
+ | `body.location_contains` | `string \| null` | no | Free-text token matched case-insensitively against the job location. |
1920
+ | `body.offset` | `integer` | no | default `0`, min 0 |
1921
+ | `body.parent_linkedin_company_id` | `integer \| null` | no | Scope to one parent company and its subsidiaries. Omit to search everywhere. |
1922
+ | `body.per_company_cap` | `integer` | no | Max postings counted per company. default `50`, min 1, max 10000 |
1923
+ | `body.persona_department` | `Array<string> \| null` | no | Decision-maker department filter. |
1924
+ | `body.persona_seniority` | `Array<string> \| null` | no | Decision-maker seniority filter. |
1925
+ | `body.persona_title_contains` | `string \| null` | no | Decision-maker title substring filter. |
1926
+ | `body.recruiter_limit` | `integer` | no | Recruiter paging, INDEPENDENT of `limit`/`offset`: one recruiter can serve many companies, so the two counts diverge and a caller can page one tab without touching the other. default `50`, min 1, max 200 |
1927
+ | `body.recruiter_offset` | `integer` | no | default `0`, min 0 |
1928
+ | `body.window_days` | `integer` | no | How far back to look for postings. default `30`, min 1, max 365 |
1929
+
1930
+ **Returns** `ApiResponse_JobSearchResponse_`: the envelope `{ data: JobSearchResponse, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1931
+
1932
+ Other envelope fields: `pagination` (PaginationMeta).
1933
+
1934
+ `JobSearchResponse` fields:
1935
+
1936
+ | Field | Type | Required | Description |
1937
+ |---|---|---|---|
1938
+ | `results` | `Array<Record<string, unknown>>` | no | |
1939
+ | `total` | `integer` | no | default `0` |
1940
+
1941
+ **Example**
1942
+
1943
+ ```ts
1944
+ // billable: spends credits; the SDK never blindly retries it; confirm cost before bulk use.
1945
+ const result = await g8.api.signals.searchHiringCompanies({ body: { keywords: ["example"] } });
1946
+ ```
1947
+
1948
+ ---
1949
+
1950
+ <a id="op-searchhiringdecisionmakers"></a>
1951
+
1952
+ ### `g8.api.signals.searchHiringDecisionMakers(input)`
1953
+
1954
+ **Search Hiring Decision Makers**
1955
+
1956
+ - HTTP: `POST /api/v1/hiring-signals/decision-makers`
1957
+ - operationId: `search_hiring_decision_makers_hiring_signals_decision_makers_post` (also callable as `g8.api.call("search_hiring_decision_makers_hiring_signals_decision_makers_post", input)`)
1958
+ - Tier: `billable`: spends credits; the SDK never blindly retries it; confirm cost before bulk use
1959
+ - API-key scope: `intent:run`
1960
+
1961
+ People to talk to at the hiring companies.
1962
+
1963
+ Scoped by the `persona_*` filters, capped per company by
1964
+ `contacts_per_company` - the point is a shortlist per account, not every
1965
+ employee.
1966
+
1967
+ **Input**
1968
+
1969
+ | Field | Type | Required | Description |
1970
+ |---|---|---|---|
1971
+ | `body` | `JobSearchRequest` | yes | Request body; fields below. |
1972
+
1973
+ Body fields (`JobSearchRequest`):
1974
+
1975
+ | Field | Type | Required | Description |
1976
+ |---|---|---|---|
1977
+ | `body.keywords` | `Array<string>` | yes | Job-title keywords. OR semantics - any match counts. min items 1 |
1978
+ | `body.contacts_per_company` | `integer` | no | default `10`, min 1, max 50 |
1979
+ | `body.exclude_aggregators` | `boolean` | no | Drop postings from job-board aggregators. On by default because an aggregator is not a company that is hiring - it is a company that lists other people's jobs. `/jobs/search/aggregators` returns exactly what this suppressed, so a caller can audit it. default `true` |
1980
+ | `body.include_recruiters` | `boolean` | no | Run the recruiter aggregation and enrichment hop. Set false to skip two round-trips when only Companies and Decision-makers are needed. default `true` |
1981
+ | `body.limit` | `integer` | no | Page size. Capped at 200 to bound the ClickHouse cost. default `50`, min 1, max 200 |
1982
+ | `body.location_contains` | `string \| null` | no | Free-text token matched case-insensitively against the job location. |
1983
+ | `body.offset` | `integer` | no | default `0`, min 0 |
1984
+ | `body.parent_linkedin_company_id` | `integer \| null` | no | Scope to one parent company and its subsidiaries. Omit to search everywhere. |
1985
+ | `body.per_company_cap` | `integer` | no | Max postings counted per company. default `50`, min 1, max 10000 |
1986
+ | `body.persona_department` | `Array<string> \| null` | no | Decision-maker department filter. |
1987
+ | `body.persona_seniority` | `Array<string> \| null` | no | Decision-maker seniority filter. |
1988
+ | `body.persona_title_contains` | `string \| null` | no | Decision-maker title substring filter. |
1989
+ | `body.recruiter_limit` | `integer` | no | Recruiter paging, INDEPENDENT of `limit`/`offset`: one recruiter can serve many companies, so the two counts diverge and a caller can page one tab without touching the other. default `50`, min 1, max 200 |
1990
+ | `body.recruiter_offset` | `integer` | no | default `0`, min 0 |
1991
+ | `body.window_days` | `integer` | no | How far back to look for postings. default `30`, min 1, max 365 |
1992
+
1993
+ **Returns** `ApiResponse_JobSearchResponse_`: the envelope `{ data: JobSearchResponse, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1994
+
1995
+ Other envelope fields: `pagination` (PaginationMeta).
1996
+
1997
+ `JobSearchResponse` fields:
1998
+
1999
+ | Field | Type | Required | Description |
2000
+ |---|---|---|---|
2001
+ | `results` | `Array<Record<string, unknown>>` | no | |
2002
+ | `total` | `integer` | no | default `0` |
2003
+
2004
+ **Example**
2005
+
2006
+ ```ts
2007
+ // billable: spends credits; the SDK never blindly retries it; confirm cost before bulk use.
2008
+ const result = await g8.api.signals.searchHiringDecisionMakers({ body: { keywords: ["example"] } });
2009
+ ```
2010
+
2011
+ ---
2012
+
2013
+ <a id="op-searchhiringjobs"></a>
2014
+
2015
+ ### `g8.api.signals.searchHiringJobs(input)`
2016
+
2017
+ **Search Hiring Jobs**
2018
+
2019
+ - HTTP: `POST /api/v1/hiring-signals/jobs`
2020
+ - operationId: `search_hiring_jobs_hiring_signals_jobs_post` (also callable as `g8.api.call("search_hiring_jobs_hiring_signals_jobs_post", input)`)
2021
+ - Tier: `billable`: spends credits; the SDK never blindly retries it; confirm cost before bulk use
2022
+ - API-key scope: `intent:run`
2023
+
2024
+ Raw job postings matching the keywords. The default view.
2025
+
2026
+ **Input**
2027
+
2028
+ | Field | Type | Required | Description |
2029
+ |---|---|---|---|
2030
+ | `body` | `JobSearchRequest` | yes | Request body; fields below. |
2031
+
2032
+ Body fields (`JobSearchRequest`):
2033
+
2034
+ | Field | Type | Required | Description |
2035
+ |---|---|---|---|
2036
+ | `body.keywords` | `Array<string>` | yes | Job-title keywords. OR semantics - any match counts. min items 1 |
2037
+ | `body.contacts_per_company` | `integer` | no | default `10`, min 1, max 50 |
2038
+ | `body.exclude_aggregators` | `boolean` | no | Drop postings from job-board aggregators. On by default because an aggregator is not a company that is hiring - it is a company that lists other people's jobs. `/jobs/search/aggregators` returns exactly what this suppressed, so a caller can audit it. default `true` |
2039
+ | `body.include_recruiters` | `boolean` | no | Run the recruiter aggregation and enrichment hop. Set false to skip two round-trips when only Companies and Decision-makers are needed. default `true` |
2040
+ | `body.limit` | `integer` | no | Page size. Capped at 200 to bound the ClickHouse cost. default `50`, min 1, max 200 |
2041
+ | `body.location_contains` | `string \| null` | no | Free-text token matched case-insensitively against the job location. |
2042
+ | `body.offset` | `integer` | no | default `0`, min 0 |
2043
+ | `body.parent_linkedin_company_id` | `integer \| null` | no | Scope to one parent company and its subsidiaries. Omit to search everywhere. |
2044
+ | `body.per_company_cap` | `integer` | no | Max postings counted per company. default `50`, min 1, max 10000 |
2045
+ | `body.persona_department` | `Array<string> \| null` | no | Decision-maker department filter. |
2046
+ | `body.persona_seniority` | `Array<string> \| null` | no | Decision-maker seniority filter. |
2047
+ | `body.persona_title_contains` | `string \| null` | no | Decision-maker title substring filter. |
2048
+ | `body.recruiter_limit` | `integer` | no | Recruiter paging, INDEPENDENT of `limit`/`offset`: one recruiter can serve many companies, so the two counts diverge and a caller can page one tab without touching the other. default `50`, min 1, max 200 |
2049
+ | `body.recruiter_offset` | `integer` | no | default `0`, min 0 |
2050
+ | `body.window_days` | `integer` | no | How far back to look for postings. default `30`, min 1, max 365 |
2051
+
2052
+ **Returns** `ApiResponse_JobSearchResponse_`: the envelope `{ data: JobSearchResponse, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
2053
+
2054
+ Other envelope fields: `pagination` (PaginationMeta).
2055
+
2056
+ `JobSearchResponse` fields:
2057
+
2058
+ | Field | Type | Required | Description |
2059
+ |---|---|---|---|
2060
+ | `results` | `Array<Record<string, unknown>>` | no | |
2061
+ | `total` | `integer` | no | default `0` |
2062
+
2063
+ **Example**
2064
+
2065
+ ```ts
2066
+ // billable: spends credits; the SDK never blindly retries it; confirm cost before bulk use.
2067
+ const result = await g8.api.signals.searchHiringJobs({ body: { keywords: ["example"] } });
2068
+ ```
2069
+
2070
+ ---
2071
+
2072
+ <a id="op-searchhiringrecruiters"></a>
2073
+
2074
+ ### `g8.api.signals.searchHiringRecruiters(input)`
2075
+
2076
+ **Search Hiring Recruiters**
2077
+
2078
+ - HTTP: `POST /api/v1/hiring-signals/recruiters`
2079
+ - operationId: `search_hiring_recruiters_hiring_signals_recruiters_post` (also callable as `g8.api.call("search_hiring_recruiters_hiring_signals_recruiters_post", input)`)
2080
+ - Tier: `billable`: spends credits; the SDK never blindly retries it; confirm cost before bulk use
2081
+ - API-key scope: `intent:run`
2082
+
2083
+ The recruiters who posted the matching jobs.
2084
+
2085
+ Paged by `recruiter_limit`/`recruiter_offset`, INDEPENDENTLY of the
2086
+ companies paging: one recruiter can serve many companies, so the two
2087
+ counts diverge and paging one must not move the other.
2088
+
2089
+ **Input**
2090
+
2091
+ | Field | Type | Required | Description |
2092
+ |---|---|---|---|
2093
+ | `body` | `JobSearchRequest` | yes | Request body; fields below. |
2094
+
2095
+ Body fields (`JobSearchRequest`):
2096
+
2097
+ | Field | Type | Required | Description |
2098
+ |---|---|---|---|
2099
+ | `body.keywords` | `Array<string>` | yes | Job-title keywords. OR semantics - any match counts. min items 1 |
2100
+ | `body.contacts_per_company` | `integer` | no | default `10`, min 1, max 50 |
2101
+ | `body.exclude_aggregators` | `boolean` | no | Drop postings from job-board aggregators. On by default because an aggregator is not a company that is hiring - it is a company that lists other people's jobs. `/jobs/search/aggregators` returns exactly what this suppressed, so a caller can audit it. default `true` |
2102
+ | `body.include_recruiters` | `boolean` | no | Run the recruiter aggregation and enrichment hop. Set false to skip two round-trips when only Companies and Decision-makers are needed. default `true` |
2103
+ | `body.limit` | `integer` | no | Page size. Capped at 200 to bound the ClickHouse cost. default `50`, min 1, max 200 |
2104
+ | `body.location_contains` | `string \| null` | no | Free-text token matched case-insensitively against the job location. |
2105
+ | `body.offset` | `integer` | no | default `0`, min 0 |
2106
+ | `body.parent_linkedin_company_id` | `integer \| null` | no | Scope to one parent company and its subsidiaries. Omit to search everywhere. |
2107
+ | `body.per_company_cap` | `integer` | no | Max postings counted per company. default `50`, min 1, max 10000 |
2108
+ | `body.persona_department` | `Array<string> \| null` | no | Decision-maker department filter. |
2109
+ | `body.persona_seniority` | `Array<string> \| null` | no | Decision-maker seniority filter. |
2110
+ | `body.persona_title_contains` | `string \| null` | no | Decision-maker title substring filter. |
2111
+ | `body.recruiter_limit` | `integer` | no | Recruiter paging, INDEPENDENT of `limit`/`offset`: one recruiter can serve many companies, so the two counts diverge and a caller can page one tab without touching the other. default `50`, min 1, max 200 |
2112
+ | `body.recruiter_offset` | `integer` | no | default `0`, min 0 |
2113
+ | `body.window_days` | `integer` | no | How far back to look for postings. default `30`, min 1, max 365 |
2114
+
2115
+ **Returns** `ApiResponse_JobSearchResponse_`: the envelope `{ data: JobSearchResponse, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
2116
+
2117
+ Other envelope fields: `pagination` (PaginationMeta).
2118
+
2119
+ `JobSearchResponse` fields:
2120
+
2121
+ | Field | Type | Required | Description |
2122
+ |---|---|---|---|
2123
+ | `results` | `Array<Record<string, unknown>>` | no | |
2124
+ | `total` | `integer` | no | default `0` |
2125
+
2126
+ **Example**
2127
+
2128
+ ```ts
2129
+ // billable: spends credits; the SDK never blindly retries it; confirm cost before bulk use.
2130
+ const result = await g8.api.signals.searchHiringRecruiters({ body: { keywords: ["example"] } });
2131
+ ```
2132
+
2133
+ ---
2134
+
2135
+ <a id="op-searchmatchedposts"></a>
2136
+
2137
+ ### `g8.api.signals.searchMatchedPosts(input)`
2138
+
2139
+ **Search Matched Posts**
2140
+
2141
+ - HTTP: `POST /api/v1/social-listeners/posts/search`
2142
+ - operationId: `search_matched_posts_social_listeners_posts_search_post` (also callable as `g8.api.call("search_matched_posts_social_listeners_posts_search_post", input)`)
2143
+ - Tier: `read`: reads data; safe to call and to retry
2144
+ - API-key scope: `intent:read`
2145
+
2146
+ Posts the listeners have already matched.
2147
+
2148
+ A PAGINATED DATABASE READ. It makes no live platform call and spends
2149
+ nothing - the fetching is done by the polling worker, not by this call. The
2150
+ app spells it `/fetch`, which reads like it goes and gets them; it does
2151
+ not, and the path here says so.
2152
+
2153
+ Tiered `read` for the same reason: a key granted "read my signals" has to
2154
+ be able to read a matched post.
2155
+
2156
+ **Input**
2157
+
2158
+ | Field | Type | Required | Description |
2159
+ |---|---|---|---|
2160
+ | `body` | `SearchPostsRequest` | yes | Request body; fields below. |
2161
+
2162
+ Body fields (`SearchPostsRequest`):
2163
+
2164
+ | Field | Type | Required | Description |
2165
+ |---|---|---|---|
2166
+ | `body.conditions` | `Array<Record<string, unknown>>` | no | Grid-style filter expressions, passed through unchanged. Their grammar is the app's, not this contract's - a typed model here would freeze a filter language that still moves. |
2167
+ | `body.has_contact` | `boolean \| null` | no | Only posts whose author resolved to a graph8 contact. |
2168
+ | `body.hide_low_confidence` | `boolean \| null` | no | Hide posts the classifier scored confidently LOW (< 0.5), while keeping never-classified ones visible. Not the same as `min_score=0.5`, which would also hide the unscored. |
2169
+ | `body.limit` | `integer` | no | default `100`, min 1, max 200 |
2170
+ | `body.listener_id` | `string (uuid) \| null` | no | |
2171
+ | `body.max_score` | `number \| null` | no | min 0, max 1 |
2172
+ | `body.min_score` | `number \| null` | no | min 0, max 1 |
2173
+ | `body.page` | `integer` | no | default `1`, min 1 |
2174
+ | `body.platform` | `"x" \| "linkedin" \| "reddit" \| "instagram" \| "youtube" \| null` | no | |
2175
+ | `body.since` | `string (date-time) \| null` | no | |
2176
+ | `body.status` | `string \| null` | no | `new`, `reviewed` or `dismissed`. |
2177
+ | `body.until` | `string (date-time) \| null` | no | |
2178
+
2179
+ **Returns** `ApiResponse_SocialCollection_`: the envelope `{ data: SocialCollection, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
2180
+
2181
+ Other envelope fields: `pagination` (PaginationMeta).
2182
+
2183
+ `SocialCollection` fields:
2184
+
2185
+ | Field | Type | Required | Description |
2186
+ |---|---|---|---|
2187
+ | `items` | `Array<unknown>` | no | |
2188
+
2189
+ **Example**
2190
+
2191
+ ```ts
2192
+ const result = await g8.api.signals.searchMatchedPosts({ body: {} });
2193
+ ```
2194
+
2195
+ ---
2196
+
2197
+ <a id="op-searchpostengagements"></a>
2198
+
2199
+ ### `g8.api.signals.searchPostEngagements(input)`
2200
+
2201
+ **Search Post Engagements**
2202
+
2203
+ - HTTP: `POST /api/v1/social-listeners/posts/{post_id}/engagements/search`
2204
+ - operationId: `search_post_engagements_social_listeners_posts__post_id__engagements_search_post` (also callable as `g8.api.call("search_post_engagements_social_listeners_posts__post_id__engagements_search_post", input)`)
2205
+ - Tier: `read`: reads data; safe to call and to retry
2206
+ - API-key scope: `intent:read`
2207
+
2208
+ Who commented on or reacted to one matched post.
2209
+
2210
+ Also a paginated database read - the engagements were stored by the worker,
2211
+ and only when `fetch_engagements` is on for that channel. An empty result
2212
+ can mean "nobody engaged" OR "engagement fetching is off"; check
2213
+ `GET /social-listeners/settings`.
2214
+
2215
+ **Input**
2216
+
2217
+ | Field | Type | Required | Description |
2218
+ |---|---|---|---|
2219
+ | `path.post_id` | `string` | yes | The post's platform-native id. |
2220
+ | `body` | `SearchPostEngagementsRequest` | yes | Request body; fields below. |
2221
+
2222
+ Body fields (`SearchPostEngagementsRequest`):
2223
+
2224
+ | Field | Type | Required | Description |
2225
+ |---|---|---|---|
2226
+ | `body.engagement_type` | `"comment" \| "reaction" \| null` | no | |
2227
+ | `body.limit` | `integer` | no | default `100`, min 1, max 200 |
2228
+ | `body.page` | `integer` | no | default `1`, min 1 |
2229
+ | `body.platform` | `"x" \| "linkedin" \| "reddit" \| "instagram" \| "youtube"` | no | default `"x"` |
2230
+
2231
+ **Returns** `ApiResponse_SocialCollection_`: the envelope `{ data: SocialCollection, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
2232
+
2233
+ Other envelope fields: `pagination` (PaginationMeta).
2234
+
2235
+ `SocialCollection` fields:
2236
+
2237
+ | Field | Type | Required | Description |
2238
+ |---|---|---|---|
2239
+ | `items` | `Array<unknown>` | no | |
2240
+
2241
+ **Example**
2242
+
2243
+ ```ts
2244
+ const result = await g8.api.signals.searchPostEngagements({ path: { post_id: "id" }, body: {} });
2245
+ ```
2246
+
2247
+ ---
2248
+
2249
+ <a id="op-testxcredentials"></a>
2250
+
2251
+ ### `g8.api.signals.testXCredentials(input)`
2252
+
2253
+ **Test X Credentials**
2254
+
2255
+ - HTTP: `POST /api/v1/social-listeners/integrations/x/test`
2256
+ - operationId: `test_x_credentials_social_listeners_integrations_x_test_post` (also callable as `g8.api.call("test_x_credentials_social_listeners_integrations_x_test_post", input)`)
2257
+ - Tier: `billable`: spends credits; the SDK never blindly retries it; confirm cost before bulk use
2258
+ - API-key scope: `intent:run`
2259
+
2260
+ Check credentials against X without storing them.
2261
+
2262
+ Persists NOTHING, whether the check passes or fails. Run this before
2263
+ `POST /social-listeners/integrations/x` so a typo does not pause every
2264
+ listener the org has.
2265
+
2266
+ **Input**
2267
+
2268
+ | Field | Type | Required | Description |
2269
+ |---|---|---|---|
2270
+ | `body` | `XApiCredentialsRequest` | yes | Request body; fields below. |
2271
+
2272
+ Body fields (`XApiCredentialsRequest`):
2273
+
2274
+ | Field | Type | Required | Description |
2275
+ |---|---|---|---|
2276
+ | `body.api_key` | `string` | yes | X Developer App API key (consumer key). min length 1 |
2277
+ | `body.api_secret` | `string` | yes | X Developer App API secret. min length 1 |
2278
+
2279
+ **Returns** `ApiResponse_SocialPayload_`: the envelope `{ data: SocialPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
2280
+
2281
+ Other envelope fields: `pagination` (PaginationMeta).
2282
+
2283
+ **Example**
2284
+
2285
+ ```ts
2286
+ // billable: spends credits; the SDK never blindly retries it; confirm cost before bulk use.
2287
+ const result = await g8.api.signals.testXCredentials({ body: { api_key: "example", api_secret: "example" } });
2288
+ ```
2289
+
2290
+ ---
2291
+
2292
+ <a id="op-triggerkeywordsync"></a>
2293
+
2294
+ ### `g8.api.signals.triggerKeywordSync(input)`
2295
+
2296
+ **Trigger Keyword Sync**
2297
+
2298
+ - HTTP: `POST /api/v1/intent/keywords/{keyword_id}/sync`
2299
+ - operationId: `trigger_keyword_sync_intent_keywords__keyword_id__sync_post` (also callable as `g8.api.call("trigger_keyword_sync_intent_keywords__keyword_id__sync_post", input)`)
2300
+ - Tier: `billable`: spends credits; the SDK never blindly retries it; confirm cost before bulk use
2301
+ - API-key scope: `intent:run`
2302
+
2303
+ Queue an immediate sync of this keyword's matches into its configured list.
2304
+
2305
+ **Input**
2306
+
2307
+ | Field | Type | Required | Description |
2308
+ |---|---|---|---|
2309
+ | `path.keyword_id` | `string (uuid)` | yes | The keyword's id. |
2310
+
2311
+ **Returns** `ApiResponse_IntentPayload_`: the envelope `{ data: IntentPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
2312
+
2313
+ Other envelope fields: `pagination` (PaginationMeta).
2314
+
2315
+ **Example**
2316
+
2317
+ ```ts
2318
+ // billable: spends credits; the SDK never blindly retries it; confirm cost before bulk use.
2319
+ const result = await g8.api.signals.triggerKeywordSync({ path: { keyword_id: "00000000-0000-0000-0000-000000000000" } });
2320
+ ```
2321
+
2322
+ ---
2323
+
2324
+ <a id="op-updatehiringkeyword"></a>
2325
+
2326
+ ### `g8.api.signals.updateHiringKeyword(input)`
2327
+
2328
+ **Update Hiring Keyword**
2329
+
2330
+ - HTTP: `PATCH /api/v1/intent/keywords/{keyword_id}`
2331
+ - operationId: `update_hiring_keyword_intent_keywords__keyword_id__patch` (also callable as `g8.api.call("update_hiring_keyword_intent_keywords__keyword_id__patch", input)`)
2332
+ - Tier: `billable`: spends credits; the SDK never blindly retries it; confirm cost before bulk use
2333
+ - API-key scope: `intent:run`
2334
+
2335
+ Edit a HIRING listener in place: its name, filters or watchlist scope.
2336
+
2337
+ Only `jobs` and `job_changes` listeners are editable here; any other keyword
2338
+ is a 404. `search_filters` is a FULL REPLACEMENT.
2339
+
2340
+ **Input**
2341
+
2342
+ | Field | Type | Required | Description |
2343
+ |---|---|---|---|
2344
+ | `path.keyword_id` | `string (uuid)` | yes | The keyword's id. |
2345
+ | `body` | `UpdateKeywordRequest` | yes | Request body; fields below. |
2346
+
2347
+ Body fields (`UpdateKeywordRequest`):
2348
+
2349
+ | Field | Type | Required | Description |
2350
+ |---|---|---|---|
2351
+ | `body.keyword` | `string \| null` | no | The listener's name. Must not be blank. |
2352
+ | `body.search_filters` | `Record<string, unknown> \| null` | no | FULL REPLACEMENT of the filter object, not a merge - filters left out are dropped. `window_days` must be 1-365 and `contacts_per_company` 1-50 when present. |
2353
+ | `body.watchlist_source` | `string \| null` | no | Talent Moves watchlist scope, as a JSON-encoded string. |
2354
+
2355
+ **Returns** `ApiResponse_IntentPayload_`: the envelope `{ data: IntentPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
2356
+
2357
+ Other envelope fields: `pagination` (PaginationMeta).
2358
+
2359
+ **Example**
2360
+
2361
+ ```ts
2362
+ // billable: spends credits; the SDK never blindly retries it; confirm cost before bulk use.
2363
+ const result = await g8.api.signals.updateHiringKeyword({
2364
+ path: { keyword_id: "00000000-0000-0000-0000-000000000000" },
2365
+ body: {},
2366
+ });
2367
+ ```
2368
+
2369
+ ---
2370
+
2371
+ <a id="op-updatelistener"></a>
2372
+
2373
+ ### `g8.api.signals.updateListener(input)`
2374
+
2375
+ **Update Listener**
2376
+
2377
+ - HTTP: `PATCH /api/v1/social-listeners/{listener_id}`
2378
+ - operationId: `update_listener_social_listeners__listener_id__patch` (also callable as `g8.api.call("update_listener_social_listeners__listener_id__patch", input)`)
2379
+ - Tier: `billable`: spends credits; the SDK never blindly retries it; confirm cost before bulk use
2380
+ - API-key scope: `intent:run`
2381
+
2382
+ Partial update. Omitted fields are left alone.
2383
+
2384
+ `is_active: false` pauses polling without losing the listener or its
2385
+ history - the way to stop spend without destroying what has been matched.
2386
+
2387
+ Changing `target_handle` on a `user` listener re-resolves the account
2388
+ against the platform, which consumes X API quota.
2389
+
2390
+ **Input**
2391
+
2392
+ | Field | Type | Required | Description |
2393
+ |---|---|---|---|
2394
+ | `path.listener_id` | `string (uuid)` | yes | The listener's id. |
2395
+ | `body` | `PatchListenerRequest` | yes | Request body; fields below. |
2396
+
2397
+ Body fields (`PatchListenerRequest`):
2398
+
2399
+ | Field | Type | Required | Description |
2400
+ |---|---|---|---|
2401
+ | `body.filters` | `Record<string, unknown> \| null` | no | |
2402
+ | `body.is_active` | `boolean \| null` | no | False pauses polling without deleting the listener. |
2403
+ | `body.monthly_credit_cap` | `integer \| null` | no | min 0 |
2404
+ | `body.name` | `string \| null` | no | |
2405
+ | `body.poll_interval_sec` | `integer \| null` | no | min 60 |
2406
+ | `body.query` | `string \| null` | no | |
2407
+ | `body.target_handle` | `string \| null` | no | |
2408
+
2409
+ **Returns** `ApiResponse_SocialPayload_`: the envelope `{ data: SocialPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
2410
+
2411
+ Other envelope fields: `pagination` (PaginationMeta).
2412
+
2413
+ **Example**
2414
+
2415
+ ```ts
2416
+ // billable: spends credits; the SDK never blindly retries it; confirm cost before bulk use.
2417
+ const result = await g8.api.signals.updateListener({
2418
+ path: { listener_id: "00000000-0000-0000-0000-000000000000" },
2419
+ body: {},
2420
+ });
2421
+ ```
2422
+
2423
+ ---
2424
+
2425
+ <a id="op-updatesocialsettings"></a>
2426
+
2427
+ ### `g8.api.signals.updateSocialSettings(input)`
2428
+
2429
+ **Update Social Settings**
2430
+
2431
+ - HTTP: `PATCH /api/v1/social-listeners/settings`
2432
+ - operationId: `update_social_settings_social_listeners_settings_patch` (also callable as `g8.api.call("update_social_settings_social_listeners_settings_patch", input)`)
2433
+ - Tier: `billable`: spends credits; the SDK never blindly retries it; confirm cost before bulk use
2434
+ - API-key scope: `intent:run`
2435
+
2436
+ Change the org's spend ceilings and capture rules.
2437
+
2438
+ ADMIN ONLY, and gated twice for two different reasons. The app declares
2439
+ `require_signals_write` as a dependency AND checks
2440
+ `user.has_role_in_org(org_id, "Admin")` in its BODY. That second check
2441
+ reads `User.roles`, which `get_api_user` never populates - so for an API
2442
+ key it answers False no matter who minted it. `require_org_admin` is the
2443
+ API-key-native half and `with_org_role` makes the app's own half answer
2444
+ correctly rather than refusing everyone.
2445
+
2446
+ This is the surface that BOUNDS what social listening costs. Raising
2447
+ `monthly_credit_cap` or turning `auto_pause_on_cap` off removes the brake.
2448
+
2449
+ **Input**
2450
+
2451
+ | Field | Type | Required | Description |
2452
+ |---|---|---|---|
2453
+ | `body` | `PatchSocialSettingsRequest` | yes | Request body; fields below. |
2454
+
2455
+ Body fields (`PatchSocialSettingsRequest`):
2456
+
2457
+ | Field | Type | Required | Description |
2458
+ |---|---|---|---|
2459
+ | `body.alert_threshold_pct` | `integer \| null` | no | Alert at this percentage of the cap. min 0, max 100 |
2460
+ | `body.auto_archive_days` | `integer \| null` | no | min 0 |
2461
+ | `body.auto_create_contacts` | `boolean \| null` | no | |
2462
+ | `body.auto_pause_on_cap` | `boolean \| null` | no | Stop polling when the cap is reached, rather than alerting. |
2463
+ | `body.channel_settings` | `Record<string, ChannelSettingsRule> \| null` | no | Keyed by platform. Keys the app does not recognise are dropped by its own merge - it rebuilds the map from the supported set. |
2464
+ | `body.classifier_model` | `string \| null` | no | |
2465
+ | `body.contact_capture` | `Record<string, ContactCaptureRule> \| null` | no | |
2466
+ | `body.monthly_credit_cap` | `integer \| null` | no | min 0 |
2467
+ | `body.other_channels_monthly_credit_cap` | `integer \| null` | no | Org-wide monthly credit ceiling across the non-X channels (LinkedIn, Reddit, Instagram, YouTube) together. 0 means no org-wide ceiling; the per-channel caps in `channel_settings` still apply. min 0 |
2468
+
2469
+ **Returns** `ApiResponse_SocialPayload_`: the envelope `{ data: SocialPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
2470
+
2471
+ Other envelope fields: `pagination` (PaginationMeta).
2472
+
2473
+ **Example**
2474
+
2475
+ ```ts
2476
+ // billable: spends credits; the SDK never blindly retries it; confirm cost before bulk use.
2477
+ const result = await g8.api.signals.updateSocialSettings({ body: {} });
2478
+ ```
2479
+
2480
+ ---
2481
+
2482
+ ## Referenced types
2483
+
2484
+ Named types that appear in the tables above. Full TypeScript definitions: `G8Contract.<Name>` (`import type { G8Contract } from "@graph8/sdk"`).
2485
+
2486
+ <a id="type-channelsettingsrule"></a>
2487
+
2488
+ ### `ChannelSettingsRule`
2489
+
2490
+ Per-channel spend and volume ceilings.
2491
+
2492
+ | Field | Type | Required | Description |
2493
+ |---|---|---|---|
2494
+ | `enabled` | `boolean` | no | default `true` |
2495
+ | `fetch_engagements` | `boolean` | no | Fetch who engaged with each matched post. Multiplies what a poll costs. default `false` |
2496
+ | `max_comments_per_post` | `integer` | no | default `50`, min 0 |
2497
+ | `max_reactions_per_post` | `integer` | no | default `100`, min 0 |
2498
+ | `monthly_credit_cap` | `integer` | no | default `0`, min 0 |
2499
+ | `per_poll_result_cap` | `integer` | no | default `50`, min 0 |
2500
+
2501
+ <a id="type-contactcapturerule"></a>
2502
+
2503
+ ### `ContactCaptureRule`
2504
+
2505
+ When a matched post's author becomes a graph8 contact.
2506
+
2507
+ | Field | Type | Required | Description |
2508
+ |---|---|---|---|
2509
+ | `enabled` | `boolean` | no | default `true` |
2510
+ | `min_followers` | `integer` | no | default `0`, min 0 |
2511
+ | `only_when_classified` | `boolean` | no | default `false` |
2512
+
2513
+ <a id="type-keywordfilters"></a>
2514
+
2515
+ ### `KeywordFilters`
2516
+
2517
+ The filters a keyword's URL set is shaped by. Mirrors the app's `KeywordSearchFilters`, including its bounds. Keys beyond the typed ones are accepted and passed through, as the app accepts them.
2518
+
2519
+ | Field | Type | Required | Description |
2520
+ |---|---|---|---|
2521
+ | `audience` | `"b2b" \| "b2c" \| "both"` | no | `b2b`, `b2c` or `both`. default `"both"` |
2522
+ | `exclude_domains` | `Array<string>` | no | Domains to drop. |
2523
+ | `exclude_page_types` | `Array<"news" \| "finance" \| "forum" \| "vendor_marketing">` | no | Page types to drop from the URL set. |
2524
+ | `llm_triage` | `boolean` | no | Run a model pass over candidate pages. default `false` |
2525
+ | `max_urls_per_domain` | `integer` | no | Soft cap so no single domain dominates the set. default `5`, min 1, max 20 |
2526
+ | `min_commercial_intent_level` | `integer` | no | Drop pages scored below this commercial intent. default `0`, min 0, max 100 |