@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,2302 @@
1
+ <!-- Generated by sdk/js/scripts/generate-agent-docs.ts from developer-contract/openapi.json. Regenerated on every build. -->
2
+
3
+ # `g8.api.workflows`: Workflows
4
+
5
+ 59 operations (30 read, 10 write, 4 destructive, 15 external).
6
+
7
+ 21 of these also have a hand-written method (`g8.workflows`), marked **★** below. Prefer the hand-written method when one exists: it unwraps the `data` envelope and takes friendlier arguments. See [../sdk-clients.md](../sdk-clients.md).
8
+
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: [workflows.d.ts](workflows.d.ts).
20
+
21
+ ## Operations
22
+
23
+ | Call | HTTP | Tier | Scope | Summary |
24
+ |---|---|---|---|---|
25
+ | [`approveExecution`](#op-approveexecution) | `POST /api/v1/workflows/executions/approve` | external | `workflows:run` | Approve a run waiting on a human |
26
+ | [`attachSkillCollections`](#op-attachskillcollections) | `POST /api/v1/skills/{action_id}/collections` | write | `workflows:write` | Give a skill collections to retrieve from |
27
+ | [`bulkRestartExecutions`](#op-bulkrestartexecutions) | `POST /api/v1/workflows/executions/bulk-restart` | external | `workflows:run` | Restart many workflow executions |
28
+ | [`createSkillTestCase`](#op-createskilltestcase) | `POST /api/v1/skills/{action_id}/test-cases` | write | `workflows:write` | Save a test case for a skill |
29
+ | [`createWorkbench`](#op-createworkbench) | `POST /api/v1/workflows/workbenches` | external | `workflows:run` | Create a workbench (so a workflow has somewhere to write) |
30
+ | [`createWorkflow`](#op-createworkflow) ★ | `POST /api/v1/workflows` | external | `workflows:run` | Create a workflow |
31
+ | [`deleteSkillTestCase`](#op-deleteskilltestcase) | `DELETE /api/v1/skills/{action_id}/test-cases/{test_case_id}` | destructive | `workflows:delete` | Delete a test case |
32
+ | [`deleteWorkflow`](#op-deleteworkflow) ★ | `DELETE /api/v1/workflows/{action_id}` | destructive | `workflows:delete` | Delete a workflow |
33
+ | [`deleteWorkflowIntegration`](#op-deleteworkflowintegration) | `DELETE /api/v1/workflows/integrations/{provider_name}` | destructive | `workflows:delete` | Disconnect a workflow integration |
34
+ | [`describeFormFields`](#op-describeformfields) ★ | `GET /api/v1/workflows/forms/{form_id}/fields` | read | `workflows:read` | Discover form field names from recent submissions (resolver helper) |
35
+ | [`detachSkillCollection`](#op-detachskillcollection) | `DELETE /api/v1/skills/{action_id}/collections/{collection_id}` | destructive | `workflows:delete` | Stop a skill retrieving from a collection |
36
+ | [`diffSkillVersions`](#op-diffskillversions) | `GET /api/v1/skills/{action_id}/versions/{version_id}/diff` | read | `workflows:read` | Diff two versions of a skill |
37
+ | [`executeWorkflow`](#op-executeworkflow) ★ | `POST /api/v1/workflows/{action_id}/execute` | external | `workflows:run` | Execute a workflow |
38
+ | [`getExecution`](#op-getexecution) ★ | `GET /api/v1/workflows/executions/{execution_id}` | read | `workflows:read` | Get execution status / result |
39
+ | [`getExecutionStats`](#op-getexecutionstats) | `GET /api/v1/workflows/stats/executions` | read | `workflows:read` | Run health for the organisation or one skill |
40
+ | [`getNodeTypesSchema`](#op-getnodetypesschema) ★ | `GET /api/v1/workflows/node-types/schema` | read | `workflows:read` | Catalog of all workflow node types and their config schemas |
41
+ | [`getTriggerActivity`](#op-gettriggeractivity) | `GET /api/v1/workflows/stats/trigger-activity` | read | `workflows:read` | Whether workflow triggers are being evaluated |
42
+ | [`getTriggerStatus`](#op-gettriggerstatus) ★ | `GET /api/v1/workflows/{action_id}/trigger-status` | read | `workflows:read` | Trigger status (cursor + config) for a workflow |
43
+ | [`getWorkflow`](#op-getworkflow) ★ | `GET /api/v1/workflows/{action_id}` | read | `workflows:read` | Get a workflow's full graph |
44
+ | [`getWorkflowIntegration`](#op-getworkflowintegration) | `GET /api/v1/workflows/integrations/{provider_name}` | read | `workflows:read` | Get one workflow integration |
45
+ | [`getWorkflowNodeStats`](#op-getworkflownodestats) | `GET /api/v1/workflows/node-stats` | read | `workflows:read` | Per-node success and failure rates for a workflow |
46
+ | [`getWorkflowRunSummary`](#op-getworkflowrunsummary) | `GET /api/v1/workflows/run-summary` | read | `workflows:read` | Has this workflow ever run? |
47
+ | [`inferSkillVariable`](#op-inferskillvariable) | `POST /api/v1/skills/infer-variable` | write | `workflows:write` | Infer one skill variable from a record |
48
+ | [`listDispositions`](#op-listdispositions) ★ | `GET /api/v1/workflows/dispositions` | read | `workflows:read` | List valid call disposition values (system + this org's custom) |
49
+ | [`listInboxTags`](#op-listinboxtags) | `GET /api/v1/workflows/inbox-tags` | read | `workflows:read` | List AI Inbox tags for the org (resolver helper) |
50
+ | [`listLinkedinSenders`](#op-listlinkedinsenders) | `GET /api/v1/workflows/integrations/linkedin/senders` | read | `workflows:read` | List LinkedIn sender accounts for the org (resolver helper) |
51
+ | [`listMcpServers`](#op-listmcpservers) ★ | `GET /api/v1/workflows/mcp-servers` | read | `workflows:read` | List MCP servers connected to the org (resolver helper) |
52
+ | [`listRecentWorkflowRuns`](#op-listrecentworkflowruns) | `GET /api/v1/workflows/{action_id}/runs/recent` | read | `workflows:read` | Recent runs of one workflow |
53
+ | [`listRoamGroups`](#op-listroamgroups) ★ | `GET /api/v1/workflows/integrations/roam/groups` | read | `workflows:read` | List Roam groups connected to the org (resolver helper) |
54
+ | [`listRoamUsers`](#op-listroamusers) ★ | `GET /api/v1/workflows/integrations/roam/users` | read | `workflows:read` | List Roam users connected to the org (resolver helper) |
55
+ | [`listSkillCollections`](#op-listskillcollections) | `GET /api/v1/skills/{action_id}/collections` | read | `workflows:read` | Collections a skill retrieves from |
56
+ | [`listSkillTestCases`](#op-listskilltestcases) | `GET /api/v1/skills/{action_id}/test-cases` | read | `workflows:read` | List a skill's saved test cases |
57
+ | [`listSkillTestRuns`](#op-listskilltestruns) | `GET /api/v1/skills/{action_id}/test-runs` | read | `workflows:read` | A skill's test-run history |
58
+ | [`listSkillVersions`](#op-listskillversions) | `GET /api/v1/skills/{action_id}/versions` | read | `workflows:read` | A skill's versions |
59
+ | [`listSlackChannels`](#op-listslackchannels) ★ | `GET /api/v1/workflows/integrations/slack/channels` | read | `workflows:read` | List Slack channels for the org (resolver helper) |
60
+ | [`listSlackUsers`](#op-listslackusers) ★ | `GET /api/v1/workflows/integrations/slack/users` | read | `workflows:read` | List Slack users for the org (resolver helper) |
61
+ | [`listWorkbenches`](#op-listworkbenches) | `GET /api/v1/workflows/workbenches` | read | `workflows:read` | List workbenches for the org (resolver helper) |
62
+ | [`listWorkflowExecutions`](#op-listworkflowexecutions) | `GET /api/v1/workflows/executions` | read | `workflows:read` | List workflow executions for the caller's org (recover a lost execution_id) |
63
+ | [`listWorkflowIntegrations`](#op-listworkflowintegrations) | `GET /api/v1/workflows/integrations` | read | `workflows:read` | List connected workflow integrations |
64
+ | [`listWorkflows`](#op-listworkflows) ★ | `GET /api/v1/workflows` | read | `workflows:read` | List workflows for the caller's org |
65
+ | [`parseScriptParameters`](#op-parsescriptparameters) | `POST /api/v1/skills/parse-script-parameters` | write | `workflows:write` | Detect a script's parameters from its code |
66
+ | [`pauseExecution`](#op-pauseexecution) ★ | `POST /api/v1/workflows/executions/{execution_id}/pause` | external | `workflows:run` | Pause a running execution (tenant-checked) |
67
+ | [`planInlineWorkflow`](#op-planinlineworkflow) | `POST /api/v1/workflows/plan` | read | `workflows:read` | Preview a normalized execution plan for an inline workflow graph |
68
+ | [`planWorkflow`](#op-planworkflow) | `POST /api/v1/workflows/{action_id}/plan` | read | `workflows:read` | Preview a normalized execution plan for a saved workflow |
69
+ | [`rejectExecution`](#op-rejectexecution) | `POST /api/v1/workflows/executions/reject` | write | `workflows:write` | Reject a run waiting on a human |
70
+ | [`requestExecutionChanges`](#op-requestexecutionchanges) | `POST /api/v1/workflows/executions/request-changes` | external | `workflows:run` | Answer a human-approval step with changes requested |
71
+ | [`resetTriggerCursor`](#op-resettriggercursor) ★ | `POST /api/v1/workflows/{action_id}/trigger-reset` | external | `workflows:run` | Reset the trigger cursor to now |
72
+ | [`resolveSkillTemplates`](#op-resolveskilltemplates) | `POST /api/v1/skills/resolve-templates` | write | `workflows:write` | Resolve skill template names to ids |
73
+ | [`restartExecution`](#op-restartexecution) | `POST /api/v1/workflows/executions/{execution_id}/restart` | external | `workflows:run` | Restart one workflow execution |
74
+ | [`restoreSkillVersion`](#op-restoreskillversion) | `POST /api/v1/skills/{action_id}/versions/{version_id}/restore` | write | `workflows:write` | Restore an earlier version of a skill |
75
+ | [`resumeExecution`](#op-resumeexecution) ★ | `POST /api/v1/workflows/executions/{execution_id}/resume` | external | `workflows:run` | Resume a paused execution (tenant-checked) |
76
+ | [`runSkillTestSuite`](#op-runskilltestsuite) | `POST /api/v1/skills/{action_id}/test-runs` | external | `workflows:run` | Run every saved test case against a skill |
77
+ | [`saveWorkflowIntegration`](#op-saveworkflowintegration) | `POST /api/v1/workflows/integrations/{provider_name}` | write | `workflows:write` | Connect or update a workflow integration |
78
+ | [`stopExecution`](#op-stopexecution) ★ | `POST /api/v1/workflows/executions/{execution_id}/stop` | external | `workflows:run` | Permanently stop an execution (tenant-checked) |
79
+ | [`testIntegrationCredential`](#op-testintegrationcredential) | `POST /api/v1/workflows/integrations/{provider_name}/test` | external | `workflows:run` | Try a Roam or Slack token |
80
+ | [`testSkillOnce`](#op-testskillonce) | `POST /api/v1/skills/{action_id}/test` | write | `workflows:write` | Dry-run a skill once |
81
+ | [`updateSkillTestCase`](#op-updateskilltestcase) | `PUT /api/v1/skills/{action_id}/test-cases/{test_case_id}` | write | `workflows:write` | Update a test case |
82
+ | [`updateWorkflow`](#op-updateworkflow) ★ | `PUT /api/v1/workflows/{action_id}` | external | `workflows:run` | Update a workflow's graph |
83
+ | [`validateWorkflow`](#op-validateworkflow) ★ | `POST /api/v1/workflows/validate` | external | `workflows:run` | Validate a workflow graph (structural + reference resolution) |
84
+
85
+ ---
86
+
87
+ <a id="op-approveexecution"></a>
88
+
89
+ ### `g8.api.workflows.approveExecution(input)`
90
+
91
+ **Approve a run waiting on a human**
92
+
93
+ - HTTP: `POST /api/v1/workflows/executions/approve`
94
+ - operationId: `approve_execution_workflows_executions_approve_post` (also callable as `g8.api.call("approve_execution_workflows_executions_approve_post", input)`)
95
+ - 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
96
+ - API-key scope: `workflows:run`
97
+
98
+ REACHES OUTSIDE GRAPH8 when the approved step does: the paused run
99
+ RESUMES and performs the action it was holding (a send, an API call, a
100
+ write). 403 when `approved_by` may not approve it; 404 for another
101
+ organisation's run.
102
+
103
+ **Input**
104
+
105
+ | Field | Type | Required | Description |
106
+ |---|---|---|---|
107
+ | `body` | `ExecutionApproval` | yes | Request body; fields below. |
108
+
109
+ Body fields (`ExecutionApproval`):
110
+
111
+ | Field | Type | Required | Description |
112
+ |---|---|---|---|
113
+ | `body.approved_by` | `string` | yes | Who approved; voice checks they may. min length 1 |
114
+ | `body.workflow_id` | `string` | yes | The paused run's workflow id. min length 1 |
115
+ | `body.notes` | `string \| null` | no | max length 2000 |
116
+
117
+ **Returns** `ApiResponse_VoicePayload_`: the envelope `{ data: VoicePayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
118
+
119
+ Other envelope fields: `pagination` (PaginationMeta).
120
+
121
+ **Example**
122
+
123
+ ```ts
124
+ // external: reaches real people (sends email/SMS, places a call, launches a send); the SDK never blindly retries it; confirm with a human first.
125
+ const result = await g8.api.workflows.approveExecution({ body: { approved_by: "example", workflow_id: "id" } });
126
+ ```
127
+
128
+ ---
129
+
130
+ <a id="op-attachskillcollections"></a>
131
+
132
+ ### `g8.api.workflows.attachSkillCollections(input)`
133
+
134
+ **Give a skill collections to retrieve from**
135
+
136
+ - HTTP: `POST /api/v1/skills/{action_id}/collections`
137
+ - operationId: `attach_skill_collections_skills__action_id__collections_post` (also callable as `g8.api.call("attach_skill_collections_skills__action_id__collections_post", input)`)
138
+ - Tier: `write`: creates or changes records; the SDK sends an Idempotency-Key and retries transient failures
139
+ - API-key scope: `workflows:write`
140
+
141
+ ADDITIVE, not a replace: attaching does not detach what is already there.
142
+
143
+ Takes effect on the next run. A collection with no vectors retrieves
144
+ nothing - check `/voice/collections/{id}/vector-status` if a skill seems
145
+ to be ignoring what you gave it.
146
+
147
+ **Input**
148
+
149
+ | Field | Type | Required | Description |
150
+ |---|---|---|---|
151
+ | `path.action_id` | `string` | yes | Skill or workflow `action_id`. |
152
+ | `body` | `Body_attach_skill_collections_skills__action_id__collections_post` | yes | Request body; fields below. |
153
+
154
+ Body fields (`Body_attach_skill_collections_skills__action_id__collections_post`):
155
+
156
+ | Field | Type | Required | Description |
157
+ |---|---|---|---|
158
+ | `body.collection_ids` | `Array<integer>` | yes | Collections to attach. Additive - existing links survive. min items 1 |
159
+
160
+ **Returns** `ApiResponse_VoicePayload_`: the envelope `{ data: VoicePayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
161
+
162
+ Other envelope fields: `pagination` (PaginationMeta).
163
+
164
+ **Example**
165
+
166
+ ```ts
167
+ const result = await g8.api.workflows.attachSkillCollections({ path: { action_id: "id" }, body: { collection_ids: [123] } });
168
+ ```
169
+
170
+ ---
171
+
172
+ <a id="op-bulkrestartexecutions"></a>
173
+
174
+ ### `g8.api.workflows.bulkRestartExecutions(input?)`
175
+
176
+ **Restart many workflow executions**
177
+
178
+ - HTTP: `POST /api/v1/workflows/executions/bulk-restart`
179
+ - operationId: `bulk_restart_executions_workflows_executions_bulk_restart_post` (also callable as `g8.api.call("bulk_restart_executions_workflows_executions_bulk_restart_post", input)`)
180
+ - 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
181
+ - API-key scope: `workflows:run`
182
+
183
+ "Re-run all failed", in one call. EVERY NODE RUNS AGAIN.
184
+
185
+ Not a resume: a restart begins at the start, so nodes that already
186
+ succeeded run a second time - including anything that sent a message,
187
+ called an API or spent credits the first time.
188
+
189
+ Voice applies a 60-second idempotency window to this route, so an
190
+ accidental double-submit inside that window does not double-run the batch.
191
+ Send an `Idempotency-Key` header as well for the app-wide guard.
192
+
193
+ Every execution in the batch is scoped to the caller's org before it is
194
+ touched; ids belonging to another tenant are simply not found.
195
+
196
+ **Input**
197
+
198
+ | Field | Type | Required | Description |
199
+ |---|---|---|---|
200
+ | `body` | `Record<string, unknown>` | no | Request body; fields below. |
201
+
202
+ **Returns** `ApiResponse_VoicePayload_`: the envelope `{ data: VoicePayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
203
+
204
+ Other envelope fields: `pagination` (PaginationMeta).
205
+
206
+ **Example**
207
+
208
+ ```ts
209
+ // external: reaches real people (sends email/SMS, places a call, launches a send); the SDK never blindly retries it; confirm with a human first.
210
+ const result = await g8.api.workflows.bulkRestartExecutions();
211
+ ```
212
+
213
+ ---
214
+
215
+ <a id="op-createskilltestcase"></a>
216
+
217
+ ### `g8.api.workflows.createSkillTestCase(input)`
218
+
219
+ **Save a test case for a skill**
220
+
221
+ - HTTP: `POST /api/v1/skills/{action_id}/test-cases`
222
+ - operationId: `create_skill_test_case_skills__action_id__test_cases_post` (also callable as `g8.api.call("create_skill_test_case_skills__action_id__test_cases_post", input)`)
223
+ - Tier: `write`: creates or changes records; the SDK sends an Idempotency-Key and retries transient failures
224
+ - API-key scope: `workflows:write`
225
+
226
+ Saving a case RUNS NOTHING. Only `POST .../test-runs` runs the skill.
227
+
228
+ That separation is the point: building a suite is free, and executing it
229
+ is the operation that costs.
230
+
231
+ **Input**
232
+
233
+ | Field | Type | Required | Description |
234
+ |---|---|---|---|
235
+ | `path.action_id` | `string` | yes | Skill or workflow `action_id`. |
236
+ | `body` | `Body_create_skill_test_case_skills__action_id__test_cases_post` | yes | Request body; fields below. |
237
+
238
+ Body fields (`Body_create_skill_test_case_skills__action_id__test_cases_post`):
239
+
240
+ | Field | Type | Required | Description |
241
+ |---|---|---|---|
242
+ | `body.input_data` | `Record<string, unknown>` | yes | The fixture, same shape as an execution's input. |
243
+ | `body.name` | `string` | yes | Human label. min length 1, max length 200 |
244
+ | `body.assertion_config` | `Record<string, unknown> \| null` | no | Extra configuration for the assertion. |
245
+ | `body.assertion_type` | `string` | no | "exact", "contains" or "llm_judge". `llm_judge` is skipped by dry runs. default `"contains"` |
246
+ | `body.expected_output` | `unknown \| null` | no | What the assertion compares against. |
247
+
248
+ **Returns** `ApiResponse_VoicePayload_`: the envelope `{ data: VoicePayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
249
+
250
+ Other envelope fields: `pagination` (PaginationMeta).
251
+
252
+ **Example**
253
+
254
+ ```ts
255
+ const result = await g8.api.workflows.createSkillTestCase({
256
+ path: { action_id: "id" },
257
+ body: { input_data: {}, name: "Example" },
258
+ });
259
+ ```
260
+
261
+ ---
262
+
263
+ <a id="op-createworkbench"></a>
264
+
265
+ ### `g8.api.workflows.createWorkbench(input)`
266
+
267
+ **Create a workbench (so a workflow has somewhere to write)**
268
+
269
+ - HTTP: `POST /api/v1/workflows/workbenches`
270
+ - operationId: `create_workbench_workflows_workbenches_post` (also callable as `g8.api.call("create_workbench_workflows_workbenches_post", input)`)
271
+ - 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
272
+ - API-key scope: `workflows:run`
273
+
274
+ Create an empty workbench and return its `workbench_id`.
275
+
276
+ The missing half of the loop: an agent could be TOLD a workbench id but could
277
+ never make one, so "build me a workflow that collects X into a new workbench"
278
+ always needed a human to go and click New Workbench first.
279
+
280
+ ``entity_type`` is optional and must be ``contact`` or ``company`` when given;
281
+ a blank workbench may defer it, which is what the underlying command already
282
+ allows. ``created_by`` is the authenticated caller and is never read from the
283
+ request, so a key cannot attribute a workbench to someone else.
284
+
285
+ The webhook API key the browser route returns on create is deliberately NOT
286
+ surfaced here. It is a write credential for a different ingestion path, it is
287
+ returned exactly once, and nothing in the workflow surface needs it — an agent
288
+ that never sees it cannot leak it into a workflow config or a chat transcript.
289
+
290
+ **Input**
291
+
292
+ | Field | Type | Required | Description |
293
+ |---|---|---|---|
294
+ | `body` | `Record<string, unknown>` | yes | Request body; fields below. |
295
+
296
+ **Returns** `Record<string, unknown>`.
297
+
298
+ **Example**
299
+
300
+ ```ts
301
+ // external: reaches real people (sends email/SMS, places a call, launches a send); the SDK never blindly retries it; confirm with a human first.
302
+ const result = await g8.api.workflows.createWorkbench({ body: {} });
303
+ ```
304
+
305
+ ---
306
+
307
+ <a id="op-createworkflow"></a>
308
+
309
+ ### `g8.api.workflows.createWorkflow(input)`
310
+
311
+ **Create a workflow**
312
+
313
+ - HTTP: `POST /api/v1/workflows`
314
+ - operationId: `create_workflow_workflows_post` (also callable as `g8.api.call("create_workflow_workflows_post", input)`)
315
+ - 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
316
+ - API-key scope: `workflows:run`
317
+ - ★ Hand-written: [`g8.workflows.create()`](../sdk-clients.md#g8-workflows-create)
318
+
319
+ Create a new workflow. Pins ``org_id`` and ``runtime_type='workflow'``
320
+ server-side - the body cannot override either.
321
+
322
+ Translates the public ``config`` field to voice's internal
323
+ ``skill_config`` before forwarding (see module docstring).
324
+
325
+ **Input**
326
+
327
+ | Field | Type | Required | Description |
328
+ |---|---|---|---|
329
+ | `body` | `Record<string, unknown>` | yes | Request body; fields below. |
330
+
331
+ **Returns** `Record<string, unknown>`.
332
+
333
+ **Example**
334
+
335
+ ```ts
336
+ // external: reaches real people (sends email/SMS, places a call, launches a send); the SDK never blindly retries it; confirm with a human first.
337
+ const result = await g8.api.workflows.createWorkflow({ body: {} });
338
+ ```
339
+
340
+ ---
341
+
342
+ <a id="op-deleteskilltestcase"></a>
343
+
344
+ ### `g8.api.workflows.deleteSkillTestCase(input)`
345
+
346
+ **Delete a test case**
347
+
348
+ - HTTP: `DELETE /api/v1/skills/{action_id}/test-cases/{test_case_id}`
349
+ - operationId: `delete_skill_test_case_skills__action_id__test_cases__test_case_id__delete` (also callable as `g8.api.call("delete_skill_test_case_skills__action_id__test_cases__test_case_id__delete", input)`)
350
+ - Tier: `destructive`: deletes or archives data; confirm with a human before calling
351
+ - API-key scope: `workflows:delete`
352
+
353
+ The case goes; its HISTORICAL RUNS SURVIVE, still carrying its id.
354
+
355
+ So a deleted case leaves readable history rather than orphaning it - past
356
+ runs in `GET .../test-runs` keep working.
357
+
358
+ **Input**
359
+
360
+ | Field | Type | Required | Description |
361
+ |---|---|---|---|
362
+ | `path.action_id` | `string` | yes | Skill or workflow `action_id`. |
363
+ | `path.test_case_id` | `string` | yes | Test case id. |
364
+
365
+ **Returns** `ApiResponse_VoicePayload_`: the envelope `{ data: VoicePayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
366
+
367
+ Other envelope fields: `pagination` (PaginationMeta).
368
+
369
+ **Example**
370
+
371
+ ```ts
372
+ // destructive: deletes or archives data; confirm with a human before calling.
373
+ const result = await g8.api.workflows.deleteSkillTestCase({ path: { action_id: "id", test_case_id: "id" } });
374
+ ```
375
+
376
+ ---
377
+
378
+ <a id="op-deleteworkflow"></a>
379
+
380
+ ### `g8.api.workflows.deleteWorkflow(input)`
381
+
382
+ **Delete a workflow**
383
+
384
+ - HTTP: `DELETE /api/v1/workflows/{action_id}`
385
+ - operationId: `delete_workflow_workflows__action_id__delete` (also callable as `g8.api.call("delete_workflow_workflows__action_id__delete", input)`)
386
+ - Tier: `destructive`: deletes or archives data; confirm with a human before calling
387
+ - API-key scope: `workflows:delete`
388
+ - ★ Hand-written: [`g8.workflows.delete()`](../sdk-clients.md#g8-workflows-delete)
389
+
390
+ Delete a workflow. Voice's delete returns ``{"success": true, ...}``
391
+ on success and 403 for system defaults - both pass through.
392
+
393
+ **Input**
394
+
395
+ | Field | Type | Required | Description |
396
+ |---|---|---|---|
397
+ | `path.action_id` | `string` | yes | Workflow action_id. |
398
+
399
+ **Returns** `Record<string, unknown>`.
400
+
401
+ **Example**
402
+
403
+ ```ts
404
+ // destructive: deletes or archives data; confirm with a human before calling.
405
+ const result = await g8.api.workflows.deleteWorkflow({ path: { action_id: "id" } });
406
+ ```
407
+
408
+ ---
409
+
410
+ <a id="op-deleteworkflowintegration"></a>
411
+
412
+ ### `g8.api.workflows.deleteWorkflowIntegration(input)`
413
+
414
+ **Disconnect a workflow integration**
415
+
416
+ - HTTP: `DELETE /api/v1/workflows/integrations/{provider_name}`
417
+ - operationId: `delete_workflow_integration_workflows_integrations__provider_name__delete` (also callable as `g8.api.call("delete_workflow_integration_workflows_integrations__provider_name__delete", input)`)
418
+ - Tier: `destructive`: deletes or archives data; confirm with a human before calling
419
+ - API-key scope: `workflows:delete`
420
+
421
+ Removes the stored credential and configuration. NOT REVERSIBLE.
422
+
423
+ Any workflow node using this provider starts failing at its next run.
424
+
425
+ **Input**
426
+
427
+ | Field | Type | Required | Description |
428
+ |---|---|---|---|
429
+ | `path.provider_name` | `string` | yes | Provider name. |
430
+
431
+ **Returns** `ApiResponse_VoicePayload_`: the envelope `{ data: VoicePayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
432
+
433
+ Other envelope fields: `pagination` (PaginationMeta).
434
+
435
+ **Example**
436
+
437
+ ```ts
438
+ // destructive: deletes or archives data; confirm with a human before calling.
439
+ const result = await g8.api.workflows.deleteWorkflowIntegration({ path: { provider_name: "Example" } });
440
+ ```
441
+
442
+ ---
443
+
444
+ <a id="op-describeformfields"></a>
445
+
446
+ ### `g8.api.workflows.describeFormFields(input)`
447
+
448
+ **Discover form field names from recent submissions (resolver helper)**
449
+
450
+ - HTTP: `GET /api/v1/workflows/forms/{form_id}/fields`
451
+ - operationId: `describe_form_fields_workflows_forms__form_id__fields_get` (also callable as `g8.api.call("describe_form_fields_workflows_forms__form_id__fields_get", input)`)
452
+ - Tier: `read`: reads data; safe to call and to retry
453
+ - API-key scope: `workflows:read`
454
+ - ★ Hand-written: [`g8.workflows.listFormFields()`](../sdk-clients.md#g8-workflows-listformfields)
455
+
456
+ Sample recent submissions for a form and return the unique field names.
457
+
458
+ Use this to populate the ``form_fields[]`` array on a
459
+ ``new_form_submitted`` trigger node config at create time, mirroring
460
+ what ``NodeConfigPanel.handleFormSelect`` does on the frontend when
461
+ the user selects a form in the dropdown.
462
+
463
+ Without these names pre-populated, downstream nodes cannot reference
464
+ submitted values via ``${<trigger_node_id>.<field>}`` until the user
465
+ re-selects the form in the UI.
466
+
467
+ Calls ``forms`` handlers in-process (no voice round-trip). Forms data
468
+ lives in ClickHouse via ``apps.forms()`` — sampled submissions are
469
+ paginated server-side; we only ever read ``per_page=10`` here.
470
+
471
+ Returns ``{form_id, fields: [str], sample_size: int}``. Empty
472
+ ``fields`` means no submissions exist yet — the caller should fall
473
+ back to asking the user for the field list, or accept that
474
+ ``${trigger.<field>}`` references will only resolve once a real
475
+ submission arrives.
476
+
477
+ **Input**
478
+
479
+ | Field | Type | Required | Description |
480
+ |---|---|---|---|
481
+ | `path.form_id` | `string` | yes | HTML form id (form_tag_id) |
482
+
483
+ **Returns** `Record<string, unknown>`.
484
+
485
+ **Example**
486
+
487
+ ```ts
488
+ const result = await g8.api.workflows.describeFormFields({ path: { form_id: "id" } });
489
+ ```
490
+
491
+ ---
492
+
493
+ <a id="op-detachskillcollection"></a>
494
+
495
+ ### `g8.api.workflows.detachSkillCollection(input)`
496
+
497
+ **Stop a skill retrieving from a collection**
498
+
499
+ - HTTP: `DELETE /api/v1/skills/{action_id}/collections/{collection_id}`
500
+ - operationId: `detach_skill_collection_skills__action_id__collections__collection_id__delete` (also callable as `g8.api.call("detach_skill_collection_skills__action_id__collections__collection_id__delete", input)`)
501
+ - Tier: `destructive`: deletes or archives data; confirm with a human before calling
502
+ - API-key scope: `workflows:delete`
503
+
504
+ Breaks the LINK only. The collection and its files are untouched.
505
+
506
+ **Input**
507
+
508
+ | Field | Type | Required | Description |
509
+ |---|---|---|---|
510
+ | `path.action_id` | `string` | yes | Skill or workflow `action_id`. |
511
+ | `path.collection_id` | `integer` | yes | Collection to unlink. |
512
+
513
+ **Returns** `ApiResponse_VoicePayload_`: the envelope `{ data: VoicePayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
514
+
515
+ Other envelope fields: `pagination` (PaginationMeta).
516
+
517
+ **Example**
518
+
519
+ ```ts
520
+ // destructive: deletes or archives data; confirm with a human before calling.
521
+ const result = await g8.api.workflows.detachSkillCollection({ path: { action_id: "id", collection_id: 123 } });
522
+ ```
523
+
524
+ ---
525
+
526
+ <a id="op-diffskillversions"></a>
527
+
528
+ ### `g8.api.workflows.diffSkillVersions(input)`
529
+
530
+ **Diff two versions of a skill**
531
+
532
+ - HTTP: `GET /api/v1/skills/{action_id}/versions/{version_id}/diff`
533
+ - operationId: `diff_skill_versions_skills__action_id__versions__version_id__diff_get` (also callable as `g8.api.call("diff_skill_versions_skills__action_id__versions__version_id__diff_get", input)`)
534
+ - Tier: `read`: reads data; safe to call and to retry
535
+ - API-key scope: `workflows:read`
536
+
537
+ Field-level diff - what actually changed, not just that something did.
538
+
539
+ The question to ask when a skill's output changed and nobody remembers
540
+ editing it.
541
+
542
+ **Input**
543
+
544
+ | Field | Type | Required | Description |
545
+ |---|---|---|---|
546
+ | `path.action_id` | `string` | yes | Skill or workflow `action_id`. |
547
+ | `path.version_id` | `string` | yes | The version to diff. |
548
+ | `query.against` | `string \| null` | no | The version to compare with. Defaults to the one immediately before. |
549
+
550
+ **Returns** `ApiResponse_VoicePayload_`: the envelope `{ data: VoicePayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
551
+
552
+ Other envelope fields: `pagination` (PaginationMeta).
553
+
554
+ **Example**
555
+
556
+ ```ts
557
+ const result = await g8.api.workflows.diffSkillVersions({ path: { action_id: "id", version_id: "id" } });
558
+ ```
559
+
560
+ ---
561
+
562
+ <a id="op-executeworkflow"></a>
563
+
564
+ ### `g8.api.workflows.executeWorkflow(input)`
565
+
566
+ **Execute a workflow**
567
+
568
+ - HTTP: `POST /api/v1/workflows/{action_id}/execute`
569
+ - operationId: `execute_workflow_workflows__action_id__execute_post` (also callable as `g8.api.call("execute_workflow_workflows__action_id__execute_post", input)`)
570
+ - 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
571
+ - API-key scope: `workflows:run`
572
+ - ★ Hand-written: [`g8.workflows.execute()`](../sdk-clients.md#g8-workflows-execute)
573
+
574
+ Trigger a workflow run. Returns ``execution_id`` for polling.
575
+
576
+ Pins ``org_id`` server-side; the caller cannot override which org's
577
+ execution row is created. ``triggered_by`` defaults to the caller's
578
+ user id when not supplied.
579
+
580
+ **Input**
581
+
582
+ | Field | Type | Required | Description |
583
+ |---|---|---|---|
584
+ | `path.action_id` | `string` | yes | Workflow action_id. |
585
+ | `body` | `Record<string, unknown>` | no | Request body; fields below. |
586
+
587
+ **Returns** `Record<string, unknown>`.
588
+
589
+ **Example**
590
+
591
+ ```ts
592
+ // external: reaches real people (sends email/SMS, places a call, launches a send); the SDK never blindly retries it; confirm with a human first.
593
+ const result = await g8.api.workflows.executeWorkflow({ path: { action_id: "id" } });
594
+ ```
595
+
596
+ ---
597
+
598
+ <a id="op-getexecution"></a>
599
+
600
+ ### `g8.api.workflows.getExecution(input)`
601
+
602
+ **Get execution status / result**
603
+
604
+ - HTTP: `GET /api/v1/workflows/executions/{execution_id}`
605
+ - operationId: `get_execution_workflows_executions__execution_id__get` (also callable as `g8.api.call("get_execution_workflows_executions__execution_id__get", input)`)
606
+ - Tier: `read`: reads data; safe to call and to retry
607
+ - API-key scope: `workflows:read`
608
+ - ★ Hand-written: [`g8.workflows.getExecution()`](../sdk-clients.md#g8-workflows-getexecution)
609
+
610
+ Return execution status + output_data + token / cost telemetry.
611
+
612
+ The MCP polling pattern: call this until ``status`` reaches a TERMINAL
613
+ value — ``completed``, ``failed`` or ``stopped``. A run can also sit in
614
+ ``paused`` or ``pending_approval`` (both non-terminal and resumable via
615
+ the lifecycle routes below), so a poller must treat those as "keep
616
+ waiting", not "done" — polling only for completed/failed hangs forever on
617
+ a paused or approval-gated run. The full set voice writes is
618
+ ``pending|running|completed|failed|paused|pending_approval|stopped``.
619
+ Voice's GET enforces tenant isolation natively so no pre-flight is needed
620
+ for the read path.
621
+
622
+ **Input**
623
+
624
+ | Field | Type | Required | Description |
625
+ |---|---|---|---|
626
+ | `path.execution_id` | `string` | yes | Execution UUID. |
627
+
628
+ **Returns** `Record<string, unknown>`.
629
+
630
+ **Example**
631
+
632
+ ```ts
633
+ const result = await g8.api.workflows.getExecution({ path: { execution_id: "id" } });
634
+ ```
635
+
636
+ ---
637
+
638
+ <a id="op-getexecutionstats"></a>
639
+
640
+ ### `g8.api.workflows.getExecutionStats(input?)`
641
+
642
+ **Run health for the organisation or one skill**
643
+
644
+ - HTTP: `GET /api/v1/workflows/stats/executions`
645
+ - operationId: `get_execution_stats_workflows_stats_executions_get` (also callable as `g8.api.call("get_execution_stats_workflows_stats_executions_get", input)`)
646
+ - Tier: `read`: reads data; safe to call and to retry
647
+ - API-key scope: `workflows:read`
648
+
649
+ SPENDS NOTHING. Status buckets that sum to the total, success rate,
650
+ duration, tokens, and `total_cost_usd` - a FLOOR on spend, since only
651
+ LLM-runtime runs record a cost (`executions_with_cost` says how many).
652
+
653
+ **Input**
654
+
655
+ | Field | Type | Required | Description |
656
+ |---|---|---|---|
657
+ | `query.action_id` | `string \| null` | no | One skill's health; omit for the organisation. |
658
+ | `query.days` | `integer \| null` | no | Window; omit for lifetime. |
659
+
660
+ **Returns** `ApiResponse_VoicePayload_`: the envelope `{ data: VoicePayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
661
+
662
+ Other envelope fields: `pagination` (PaginationMeta).
663
+
664
+ **Example**
665
+
666
+ ```ts
667
+ const result = await g8.api.workflows.getExecutionStats();
668
+ ```
669
+
670
+ ---
671
+
672
+ <a id="op-getnodetypesschema"></a>
673
+
674
+ ### `g8.api.workflows.getNodeTypesSchema(input?)`
675
+
676
+ **Catalog of all workflow node types and their config schemas**
677
+
678
+ - HTTP: `GET /api/v1/workflows/node-types/schema`
679
+ - operationId: `get_node_types_schema_workflows_node_types_schema_get` (also callable as `g8.api.call("get_node_types_schema_workflows_node_types_schema_get", input)`)
680
+ - Tier: `read`: reads data; safe to call and to retry
681
+ - API-key scope: `workflows:read`
682
+ - ★ Hand-written: [`g8.workflows.nodeTypes()`](../sdk-clients.md#g8-workflows-nodetypes)
683
+
684
+ Catalog every node type with its config schema, trigger output schemas,
685
+ resolver-tool hints, and worked examples. Cached (LRU + 1h Cache-Control)
686
+ on voice's side - context-cheap to call repeatedly from MCP clients.
687
+
688
+ **Input**
689
+
690
+ | Field | Type | Required | Description |
691
+ |---|---|---|---|
692
+ | `query.detail` | `string` | no | "slim" returns name+type per field; "full" includes Pydantic JSON schema. default `"slim"` |
693
+ | `query.node_type` | `string \| null` | no | If provided, return just one entry instead of the full catalog. |
694
+
695
+ **Returns** `Record<string, unknown>`.
696
+
697
+ **Example**
698
+
699
+ ```ts
700
+ const result = await g8.api.workflows.getNodeTypesSchema();
701
+ ```
702
+
703
+ ---
704
+
705
+ <a id="op-gettriggeractivity"></a>
706
+
707
+ ### `g8.api.workflows.getTriggerActivity(input)`
708
+
709
+ **Whether workflow triggers are being evaluated**
710
+
711
+ - HTTP: `GET /api/v1/workflows/stats/trigger-activity`
712
+ - operationId: `get_trigger_activity_workflows_stats_trigger_activity_get` (also callable as `g8.api.call("get_trigger_activity_workflows_stats_trigger_activity_get", input)`)
713
+ - Tier: `read`: reads data; safe to call and to retry
714
+ - API-key scope: `workflows:read`
715
+
716
+ SPENDS NOTHING. Per workflow: when its trigger was last evaluated and
717
+ last matched. A workflow absent from the answer is UNKNOWN (never evaluated,
718
+ or its 30-day record lapsed), not "never ran".
719
+
720
+ **Input**
721
+
722
+ | Field | Type | Required | Description |
723
+ |---|---|---|---|
724
+ | `query.action_ids` | `string` | yes | Comma-separated workflow ids (first 200 used). |
725
+
726
+ **Returns** `ApiResponse_VoicePayload_`: the envelope `{ data: VoicePayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
727
+
728
+ Other envelope fields: `pagination` (PaginationMeta).
729
+
730
+ **Example**
731
+
732
+ ```ts
733
+ const result = await g8.api.workflows.getTriggerActivity({ query: { action_ids: "id" } });
734
+ ```
735
+
736
+ ---
737
+
738
+ <a id="op-gettriggerstatus"></a>
739
+
740
+ ### `g8.api.workflows.getTriggerStatus(input)`
741
+
742
+ **Trigger status (cursor + config) for a workflow**
743
+
744
+ - HTTP: `GET /api/v1/workflows/{action_id}/trigger-status`
745
+ - operationId: `get_trigger_status_workflows__action_id__trigger_status_get` (also callable as `g8.api.call("get_trigger_status_workflows__action_id__trigger_status_get", input)`)
746
+ - Tier: `read`: reads data; safe to call and to retry
747
+ - API-key scope: `workflows:read`
748
+ - ★ Hand-written: [`g8.workflows.getTriggerStatus()`](../sdk-clients.md#g8-workflows-gettriggerstatus)
749
+
750
+ Return whether the workflow has a trigger, its type, and last cursor.
751
+
752
+ **Input**
753
+
754
+ | Field | Type | Required | Description |
755
+ |---|---|---|---|
756
+ | `path.action_id` | `string` | yes | Workflow action_id. |
757
+
758
+ **Returns** `Record<string, unknown>`.
759
+
760
+ **Example**
761
+
762
+ ```ts
763
+ const result = await g8.api.workflows.getTriggerStatus({ path: { action_id: "id" } });
764
+ ```
765
+
766
+ ---
767
+
768
+ <a id="op-getworkflow"></a>
769
+
770
+ ### `g8.api.workflows.getWorkflow(input)`
771
+
772
+ **Get a workflow's full graph**
773
+
774
+ - HTTP: `GET /api/v1/workflows/{action_id}`
775
+ - operationId: `get_workflow_workflows__action_id__get` (also callable as `g8.api.call("get_workflow_workflows__action_id__get", input)`)
776
+ - Tier: `read`: reads data; safe to call and to retry
777
+ - API-key scope: `workflows:read`
778
+ - ★ Hand-written: [`g8.workflows.get()`](../sdk-clients.md#g8-workflows-get)
779
+
780
+ Return the full workflow graph (nodes + edges + trigger config).
781
+
782
+ Translates voice's internal ``skill_config`` field to public
783
+ ``config`` on the way out (see module docstring).
784
+
785
+ **Input**
786
+
787
+ | Field | Type | Required | Description |
788
+ |---|---|---|---|
789
+ | `path.action_id` | `string` | yes | Workflow action_id. |
790
+
791
+ **Returns** `Record<string, unknown>`.
792
+
793
+ **Example**
794
+
795
+ ```ts
796
+ const result = await g8.api.workflows.getWorkflow({ path: { action_id: "id" } });
797
+ ```
798
+
799
+ ---
800
+
801
+ <a id="op-getworkflowintegration"></a>
802
+
803
+ ### `g8.api.workflows.getWorkflowIntegration(input)`
804
+
805
+ **Get one workflow integration**
806
+
807
+ - HTTP: `GET /api/v1/workflows/integrations/{provider_name}`
808
+ - operationId: `get_workflow_integration_workflows_integrations__provider_name__get` (also callable as `g8.api.call("get_workflow_integration_workflows_integrations__provider_name__get", input)`)
809
+ - Tier: `read`: reads data; safe to call and to retry
810
+ - API-key scope: `workflows:read`
811
+
812
+ Its configuration and whether a key is stored - never the key itself.
813
+
814
+ **Input**
815
+
816
+ | Field | Type | Required | Description |
817
+ |---|---|---|---|
818
+ | `path.provider_name` | `string` | yes | Provider name. |
819
+
820
+ **Returns** `ApiResponse_VoicePayload_`: the envelope `{ data: VoicePayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
821
+
822
+ Other envelope fields: `pagination` (PaginationMeta).
823
+
824
+ **Example**
825
+
826
+ ```ts
827
+ const result = await g8.api.workflows.getWorkflowIntegration({ path: { provider_name: "Example" } });
828
+ ```
829
+
830
+ ---
831
+
832
+ <a id="op-getworkflownodestats"></a>
833
+
834
+ ### `g8.api.workflows.getWorkflowNodeStats(input)`
835
+
836
+ **Per-node success and failure rates for a workflow**
837
+
838
+ - HTTP: `GET /api/v1/workflows/node-stats`
839
+ - operationId: `get_workflow_node_stats_workflows_node_stats_get` (also callable as `g8.api.call("get_workflow_node_stats_workflows_node_stats_get", input)`)
840
+ - Tier: `read`: reads data; safe to call and to retry
841
+ - API-key scope: `workflows:read`
842
+
843
+ Which STEP is failing, aggregated across runs.
844
+
845
+ The view that turns "this workflow is flaky" into "this node times out",
846
+ without reading every execution.
847
+
848
+ **Input**
849
+
850
+ | Field | Type | Required | Description |
851
+ |---|---|---|---|
852
+ | `query.action_id` | `string` | yes | The workflow to analyse. |
853
+ | `query.days` | `integer` | no | Window, in days. default `30` |
854
+
855
+ **Returns** `ApiResponse_VoicePayload_`: the envelope `{ data: VoicePayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
856
+
857
+ Other envelope fields: `pagination` (PaginationMeta).
858
+
859
+ **Example**
860
+
861
+ ```ts
862
+ const result = await g8.api.workflows.getWorkflowNodeStats({ query: { action_id: "id" } });
863
+ ```
864
+
865
+ ---
866
+
867
+ <a id="op-getworkflowrunsummary"></a>
868
+
869
+ ### `g8.api.workflows.getWorkflowRunSummary(input?)`
870
+
871
+ **Has this workflow ever run?**
872
+
873
+ - HTTP: `GET /api/v1/workflows/run-summary`
874
+ - operationId: `get_workflow_run_summary_workflows_run_summary_get` (also callable as `g8.api.call("get_workflow_run_summary_workflows_run_summary_get", input)`)
875
+ - Tier: `read`: reads data; safe to call and to retry
876
+ - API-key scope: `workflows:read`
877
+
878
+ The authoritative answer for a BATCH of workflows, in one call.
879
+
880
+ Worth using instead of listing executions per workflow: "never run" and
881
+ "ran and returned nothing" look identical in an empty execution list, and
882
+ this distinguishes them.
883
+
884
+ **Input**
885
+
886
+ | Field | Type | Required | Description |
887
+ |---|---|---|---|
888
+ | `query.action_ids` | `string \| null` | no | Comma-separated workflow ids. Omit for every workflow in the org. |
889
+
890
+ **Returns** `ApiResponse_VoicePayload_`: the envelope `{ data: VoicePayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
891
+
892
+ Other envelope fields: `pagination` (PaginationMeta).
893
+
894
+ **Example**
895
+
896
+ ```ts
897
+ const result = await g8.api.workflows.getWorkflowRunSummary();
898
+ ```
899
+
900
+ ---
901
+
902
+ <a id="op-inferskillvariable"></a>
903
+
904
+ ### `g8.api.workflows.inferSkillVariable(input)`
905
+
906
+ **Infer one skill variable from a record**
907
+
908
+ - HTTP: `POST /api/v1/skills/infer-variable`
909
+ - operationId: `infer_skill_variable_skills_infer_variable_post` (also callable as `g8.api.call("infer_skill_variable_skills_infer_variable_post", input)`)
910
+ - Tier: `write`: creates or changes records; the SDK sends an Idempotency-Key and retries transient failures
911
+ - API-key scope: `workflows:write`
912
+
913
+ Work out what one skill variable should be for a given record.
914
+
915
+ The single-variable version of what a skill does to its whole input before
916
+ it runs - useful for showing a caller what a skill WILL see without running
917
+ it. Results are cached per `(org, entity_id)`, so passing `entity_id` makes
918
+ a repeated call cheap.
919
+
920
+ **Input**
921
+
922
+ | Field | Type | Required | Description |
923
+ |---|---|---|---|
924
+ | `body` | `Body_infer_skill_variable_skills_infer_variable_post` | yes | Request body; fields below. |
925
+
926
+ Body fields (`Body_infer_skill_variable_skills_infer_variable_post`):
927
+
928
+ | Field | Type | Required | Description |
929
+ |---|---|---|---|
930
+ | `body.entity_data` | `Record<string, unknown>` | yes | The contact or company record, same shape as an execution input. |
931
+ | `body.entity_data_type` | `string` | yes | "contact" or "company". |
932
+ | `body.entity_id` | `string \| null` | no | Record id. Used for cache keying only. |
933
+
934
+ **Returns** `ApiResponse_VoicePayload_`: the envelope `{ data: VoicePayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
935
+
936
+ Other envelope fields: `pagination` (PaginationMeta).
937
+
938
+ **Example**
939
+
940
+ ```ts
941
+ const result = await g8.api.workflows.inferSkillVariable({ body: { entity_data: {}, entity_data_type: "example" } });
942
+ ```
943
+
944
+ ---
945
+
946
+ <a id="op-listdispositions"></a>
947
+
948
+ ### `g8.api.workflows.listDispositions(input?)`
949
+
950
+ **List valid call disposition values (system + this org's custom)**
951
+
952
+ - HTTP: `GET /api/v1/workflows/dispositions`
953
+ - operationId: `list_dispositions_workflows_dispositions_get` (also callable as `g8.api.call("list_dispositions_workflows_dispositions_get", input)`)
954
+ - Tier: `read`: reads data; safe to call and to retry
955
+ - API-key scope: `workflows:read`
956
+ - ★ Hand-written: [`g8.workflows.listDispositions()`](../sdk-clients.md#g8-workflows-listdispositions)
957
+
958
+ Return every disposition value accepted by ``disposition_filters`` on the
959
+ ``new_call_disposition`` trigger - system values AND the caller org's own
960
+ custom dispositions.
961
+
962
+ Each entry carries ``origin``: ``system`` for the built-in vocabulary,
963
+ ``custom`` for an org-defined one (whose ``value`` is the stored
964
+ ``custom_{id}`` key, never the display name). ``category`` keeps its
965
+ existing meaning: ``sdr_selectable`` a rep can pick it, ``system_set`` only
966
+ the dialer backend writes it.
967
+
968
+ Authority for the system half is voice's ``SDR_SELECTABLE_DISPOSITIONS``
969
+ (``voice/graph8_livekit/schemas/dispositions.py``) plus the two system-set
970
+ values the dialer also emits (``sdr_hangup``, ``failed``). That half is
971
+ inlined here and a parity test
972
+ (``developer_api/tests/test_workflow_dispositions.py``) fails the build if
973
+ voice adds a value that is not mirrored - the previous "mirror the change
974
+ here" comment was not enforced and silently went stale when ``busy`` was
975
+ added.
976
+
977
+ The custom half comes from voice's ``GET /api/dialer/dispositions/{org_id}``,
978
+ with the org pinned server-side from the authenticated caller and echoed in
979
+ the ``X-Org-Id`` header voice's tenant gate requires. Nothing about the
980
+ request body or query can influence which org is read.
981
+
982
+ Degraded mode: if voice is unreachable or errors, this returns the system
983
+ vocabulary alone with ``source='static_fallback'`` and logs a warning,
984
+ rather than failing the whole call. An agent that sees
985
+ ``source='static_fallback'`` should say it could not confirm custom
986
+ dispositions instead of asserting none exist.
987
+
988
+ Legacy aliases (``positive``/``neutral``/``negative``) are deliberately
989
+ absent: ``normalize_disposition`` rewrites them before storage, so a filter
990
+ on them could never match.
991
+
992
+ **Input**: none.
993
+
994
+ **Returns** `Record<string, unknown>`.
995
+
996
+ **Example**
997
+
998
+ ```ts
999
+ const result = await g8.api.workflows.listDispositions();
1000
+ ```
1001
+
1002
+ ---
1003
+
1004
+ <a id="op-listinboxtags"></a>
1005
+
1006
+ ### `g8.api.workflows.listInboxTags(input?)`
1007
+
1008
+ **List AI Inbox tags for the org (resolver helper)**
1009
+
1010
+ - HTTP: `GET /api/v1/workflows/inbox-tags`
1011
+ - operationId: `list_inbox_tags_workflows_inbox_tags_get` (also callable as `g8.api.call("list_inbox_tags_workflows_inbox_tags_get", input)`)
1012
+ - Tier: `read`: reads data; safe to call and to retry
1013
+ - API-key scope: `workflows:read`
1014
+
1015
+ Resolve human tag descriptions ("out of office", "interested", "referred
1016
+ me to a colleague") into the concrete tag IDs required by the
1017
+ ``new_inbox_tag_set`` trigger's ``tag_filters``.
1018
+
1019
+ This is the resolver that makes reply-intent workflows authorable. Without
1020
+ it an agent has no way to turn a tag NAME into a tag ID, so it falls back to
1021
+ a ``new_email_reply`` trigger plus a condition node grepping the body text -
1022
+ which is both fragile and duplicates work the inbox AI agent already did
1023
+ when it tagged the message on arrival.
1024
+
1025
+ ``ai_applicable_only=true`` narrows to tags whose ``ai_can_apply`` is set,
1026
+ i.e. the ones an agent applies automatically the moment an email lands.
1027
+ Those are the tags a ``new_inbox_tag_set`` trigger will actually fire on
1028
+ without a human touching anything.
1029
+
1030
+ Calls the ``ai_inbox`` tag service in-process (no voice round-trip). Org is
1031
+ pinned from the authenticated caller and used as the Postgres tenant schema;
1032
+ nothing client-supplied selects the tenant.
1033
+
1034
+ Returns ``{tags: [{id, name, description, color, ai_can_apply}], total}``.
1035
+
1036
+ **Input**
1037
+
1038
+ | Field | Type | Required | Description |
1039
+ |---|---|---|---|
1040
+ | `query.ai_applicable_only` | `boolean` | no | Return only tags an AI agent is allowed to apply automatically. default `false` |
1041
+
1042
+ **Returns** `Record<string, unknown>`.
1043
+
1044
+ **Example**
1045
+
1046
+ ```ts
1047
+ const result = await g8.api.workflows.listInboxTags();
1048
+ ```
1049
+
1050
+ ---
1051
+
1052
+ <a id="op-listlinkedinsenders"></a>
1053
+
1054
+ ### `g8.api.workflows.listLinkedinSenders(input?)`
1055
+
1056
+ **List LinkedIn sender accounts for the org (resolver helper)**
1057
+
1058
+ - HTTP: `GET /api/v1/workflows/integrations/linkedin/senders`
1059
+ - operationId: `list_linkedin_senders_workflows_integrations_linkedin_senders_get` (also callable as `g8.api.call("list_linkedin_senders_workflows_integrations_linkedin_senders_get", input)`)
1060
+ - Tier: `read`: reads data; safe to call and to retry
1061
+ - API-key scope: `workflows:read`
1062
+
1063
+ Return LinkedIn sender accounts for ``sender_account_id`` resolution.
1064
+
1065
+ Resolves the ``sender_account_id`` on the Netrion workflow nodes
1066
+ (``send_netrion_connection_request`` / ``send_netrion_message``) and on the
1067
+ ``linkedin_*`` triggers' ``linkedin_account_id``. Until this existed there was
1068
+ NO way to discover these ids programmatically: voice's ``_RESOLVER_HINTS``
1069
+ said "no MCP resolver yet — ask user", and the only listing endpoint
1070
+ (``GET /v1/linkedin/accounts``) is behind ``get_current_user`` browser auth,
1071
+ so an MCP/API caller could build the node and then not attach a sender.
1072
+
1073
+ ``sender_account_id`` is the INTEGER PK (``ArlinkLinkedInAccount.id``), which
1074
+ is the value the node config takes — deliberately NOT the arlink ``lia_...``
1075
+ string. ``account_resolution.resolve_active_account`` cannot parse the
1076
+ ``lia_`` form, and the Netrion nodes opt into ``strict_account``, so naming
1077
+ one is a hard failure rather than a silent send from an arbitrary seat. The
1078
+ field is emitted as a STRING because that is the node config's own type.
1079
+
1080
+ Mirrors ``GET /v1/linkedin/accounts`` on degradation: flag off, no accounts,
1081
+ or per-org tables not provisioned all answer an empty list, never a 500.
1082
+ A sender that is not ``status='OK'`` is still returned, with its status, so
1083
+ the caller can say "that seat is disconnected" instead of "no seats".
1084
+
1085
+ **Input**: none.
1086
+
1087
+ **Returns** `Record<string, unknown>`.
1088
+
1089
+ **Example**
1090
+
1091
+ ```ts
1092
+ const result = await g8.api.workflows.listLinkedinSenders();
1093
+ ```
1094
+
1095
+ ---
1096
+
1097
+ <a id="op-listmcpservers"></a>
1098
+
1099
+ ### `g8.api.workflows.listMcpServers(input?)`
1100
+
1101
+ **List MCP servers connected to the org (resolver helper)**
1102
+
1103
+ - HTTP: `GET /api/v1/workflows/mcp-servers`
1104
+ - operationId: `list_mcp_servers_workflows_mcp_servers_get` (also callable as `g8.api.call("list_mcp_servers_workflows_mcp_servers_get", input)`)
1105
+ - Tier: `read`: reads data; safe to call and to retry
1106
+ - API-key scope: `workflows:read`
1107
+ - ★ Hand-written: [`g8.workflows.listMcpServers()`](../sdk-clients.md#g8-workflows-listmcpservers)
1108
+
1109
+ Return MCP servers (with their tool lists) for ``tool.mcp_server_id`` resolution.
1110
+
1111
+ ``org_id`` is REQUIRED by voice (``voice/graph8_livekit/routers/mcp_servers.py``
1112
+ declares ``list_mcp_servers(org_id: str)`` with no default), so omitting it makes
1113
+ voice answer 422, not an empty list. This route previously sat below the
1114
+ ``/{action_id}`` catch-all and was unreachable, which hid the missing parameter -
1115
+ un-shadowing it turned a 404 into a 422 until this was fixed.
1116
+
1117
+ The org is pinned from the authenticated caller and is never read from the request,
1118
+ so a client cannot enumerate another tenant's MCP servers.
1119
+
1120
+ **Input**: none.
1121
+
1122
+ **Returns** `Record<string, unknown>`.
1123
+
1124
+ **Example**
1125
+
1126
+ ```ts
1127
+ const result = await g8.api.workflows.listMcpServers();
1128
+ ```
1129
+
1130
+ ---
1131
+
1132
+ <a id="op-listrecentworkflowruns"></a>
1133
+
1134
+ ### `g8.api.workflows.listRecentWorkflowRuns(input)`
1135
+
1136
+ **Recent runs of one workflow**
1137
+
1138
+ - HTTP: `GET /api/v1/workflows/{action_id}/runs/recent`
1139
+ - operationId: `list_recent_workflow_runs_workflows__action_id__runs_recent_get` (also callable as `g8.api.call("list_recent_workflow_runs_workflows__action_id__runs_recent_get", input)`)
1140
+ - Tier: `read`: reads data; safe to call and to retry
1141
+ - API-key scope: `workflows:read`
1142
+
1143
+ Ordered and limited in SQL, so a busy workflow answers cheaply.
1144
+
1145
+ `GET /workflows/executions` lists across the whole org; this is the
1146
+ per-workflow view.
1147
+
1148
+ **Input**
1149
+
1150
+ | Field | Type | Required | Description |
1151
+ |---|---|---|---|
1152
+ | `path.action_id` | `string` | yes | Skill or workflow `action_id`. |
1153
+ | `query.limit` | `integer` | no | Rows to return, newest first. default `10` |
1154
+
1155
+ **Returns** `ApiResponse_VoiceListPayload_`: the envelope `{ data: VoiceListPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1156
+
1157
+ Other envelope fields: `pagination` (PaginationMeta).
1158
+
1159
+ `VoiceListPayload` fields:
1160
+
1161
+ | Field | Type | Required | Description |
1162
+ |---|---|---|---|
1163
+ | `items` | `Array<unknown>` | no | |
1164
+
1165
+ **Example**
1166
+
1167
+ ```ts
1168
+ const result = await g8.api.workflows.listRecentWorkflowRuns({ path: { action_id: "id" } });
1169
+ ```
1170
+
1171
+ ---
1172
+
1173
+ <a id="op-listroamgroups"></a>
1174
+
1175
+ ### `g8.api.workflows.listRoamGroups(input?)`
1176
+
1177
+ **List Roam groups connected to the org (resolver helper)**
1178
+
1179
+ - HTTP: `GET /api/v1/workflows/integrations/roam/groups`
1180
+ - operationId: `list_roam_groups_workflows_integrations_roam_groups_get` (also callable as `g8.api.call("list_roam_groups_workflows_integrations_roam_groups_get", input)`)
1181
+ - Tier: `read`: reads data; safe to call and to retry
1182
+ - API-key scope: `workflows:read`
1183
+ - ★ Hand-written: [`g8.workflows.listRoamGroups()`](../sdk-clients.md#g8-workflows-listroamgroups)
1184
+
1185
+ Return Roam groups for ``send_roam_notification.recipient_id`` resolution.
1186
+
1187
+ **Input**: none.
1188
+
1189
+ **Returns** `Record<string, unknown>`.
1190
+
1191
+ **Example**
1192
+
1193
+ ```ts
1194
+ const result = await g8.api.workflows.listRoamGroups();
1195
+ ```
1196
+
1197
+ ---
1198
+
1199
+ <a id="op-listroamusers"></a>
1200
+
1201
+ ### `g8.api.workflows.listRoamUsers(input?)`
1202
+
1203
+ **List Roam users connected to the org (resolver helper)**
1204
+
1205
+ - HTTP: `GET /api/v1/workflows/integrations/roam/users`
1206
+ - operationId: `list_roam_users_workflows_integrations_roam_users_get` (also callable as `g8.api.call("list_roam_users_workflows_integrations_roam_users_get", input)`)
1207
+ - Tier: `read`: reads data; safe to call and to retry
1208
+ - API-key scope: `workflows:read`
1209
+ - ★ Hand-written: [`g8.workflows.listRoamUsers()`](../sdk-clients.md#g8-workflows-listroamusers)
1210
+
1211
+ Return Roam users for ``send_roam_notification.user_ids`` resolution.
1212
+
1213
+ **Input**: none.
1214
+
1215
+ **Returns** `Record<string, unknown>`.
1216
+
1217
+ **Example**
1218
+
1219
+ ```ts
1220
+ const result = await g8.api.workflows.listRoamUsers();
1221
+ ```
1222
+
1223
+ ---
1224
+
1225
+ <a id="op-listskillcollections"></a>
1226
+
1227
+ ### `g8.api.workflows.listSkillCollections(input)`
1228
+
1229
+ **Collections a skill retrieves from**
1230
+
1231
+ - HTTP: `GET /api/v1/skills/{action_id}/collections`
1232
+ - operationId: `list_skill_collections_skills__action_id__collections_get` (also callable as `g8.api.call("list_skill_collections_skills__action_id__collections_get", input)`)
1233
+ - Tier: `read`: reads data; safe to call and to retry
1234
+ - API-key scope: `workflows:read`
1235
+
1236
+ What this skill can look things up in while it runs.
1237
+
1238
+ The collections themselves are managed at `/voice/collections`; this is
1239
+ the link between one skill and them.
1240
+
1241
+ **Input**
1242
+
1243
+ | Field | Type | Required | Description |
1244
+ |---|---|---|---|
1245
+ | `path.action_id` | `string` | yes | Skill or workflow `action_id`. |
1246
+
1247
+ **Returns** `ApiResponse_VoiceListPayload_`: the envelope `{ data: VoiceListPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1248
+
1249
+ Other envelope fields: `pagination` (PaginationMeta).
1250
+
1251
+ `VoiceListPayload` fields:
1252
+
1253
+ | Field | Type | Required | Description |
1254
+ |---|---|---|---|
1255
+ | `items` | `Array<unknown>` | no | |
1256
+
1257
+ **Example**
1258
+
1259
+ ```ts
1260
+ const result = await g8.api.workflows.listSkillCollections({ path: { action_id: "id" } });
1261
+ ```
1262
+
1263
+ ---
1264
+
1265
+ <a id="op-listskilltestcases"></a>
1266
+
1267
+ ### `g8.api.workflows.listSkillTestCases(input)`
1268
+
1269
+ **List a skill's saved test cases**
1270
+
1271
+ - HTTP: `GET /api/v1/skills/{action_id}/test-cases`
1272
+ - operationId: `list_skill_test_cases_skills__action_id__test_cases_get` (also callable as `g8.api.call("list_skill_test_cases_skills__action_id__test_cases_get", input)`)
1273
+ - Tier: `read`: reads data; safe to call and to retry
1274
+ - API-key scope: `workflows:read`
1275
+
1276
+ Oldest first, so the suite has a stable order between runs.
1277
+
1278
+ **Input**
1279
+
1280
+ | Field | Type | Required | Description |
1281
+ |---|---|---|---|
1282
+ | `path.action_id` | `string` | yes | Skill or workflow `action_id`. |
1283
+
1284
+ **Returns** `ApiResponse_VoiceListPayload_`: the envelope `{ data: VoiceListPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1285
+
1286
+ Other envelope fields: `pagination` (PaginationMeta).
1287
+
1288
+ `VoiceListPayload` fields:
1289
+
1290
+ | Field | Type | Required | Description |
1291
+ |---|---|---|---|
1292
+ | `items` | `Array<unknown>` | no | |
1293
+
1294
+ **Example**
1295
+
1296
+ ```ts
1297
+ const result = await g8.api.workflows.listSkillTestCases({ path: { action_id: "id" } });
1298
+ ```
1299
+
1300
+ ---
1301
+
1302
+ <a id="op-listskilltestruns"></a>
1303
+
1304
+ ### `g8.api.workflows.listSkillTestRuns(input)`
1305
+
1306
+ **A skill's test-run history**
1307
+
1308
+ - HTTP: `GET /api/v1/skills/{action_id}/test-runs`
1309
+ - operationId: `list_skill_test_runs_skills__action_id__test_runs_get` (also callable as `g8.api.call("list_skill_test_runs_skills__action_id__test_runs_get", input)`)
1310
+ - Tier: `read`: reads data; safe to call and to retry
1311
+ - API-key scope: `workflows:read`
1312
+
1313
+ Newest first. Reading history costs nothing and runs nothing.
1314
+
1315
+ **Input**
1316
+
1317
+ | Field | Type | Required | Description |
1318
+ |---|---|---|---|
1319
+ | `path.action_id` | `string` | yes | Skill or workflow `action_id`. |
1320
+ | `query.test_case_id` | `string \| null` | no | Only runs of this case. |
1321
+ | `query.limit` | `integer` | no | Rows to return, newest first. default `50` |
1322
+ | `query.include_output` | `boolean` | no | True adds the stored output previews. They can be large. default `false` |
1323
+
1324
+ **Returns** `ApiResponse_VoiceListPayload_`: the envelope `{ data: VoiceListPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1325
+
1326
+ Other envelope fields: `pagination` (PaginationMeta).
1327
+
1328
+ `VoiceListPayload` fields:
1329
+
1330
+ | Field | Type | Required | Description |
1331
+ |---|---|---|---|
1332
+ | `items` | `Array<unknown>` | no | |
1333
+
1334
+ **Example**
1335
+
1336
+ ```ts
1337
+ const result = await g8.api.workflows.listSkillTestRuns({ path: { action_id: "id" } });
1338
+ ```
1339
+
1340
+ ---
1341
+
1342
+ <a id="op-listskillversions"></a>
1343
+
1344
+ ### `g8.api.workflows.listSkillVersions(input)`
1345
+
1346
+ **A skill's versions**
1347
+
1348
+ - HTTP: `GET /api/v1/skills/{action_id}/versions`
1349
+ - operationId: `list_skill_versions_skills__action_id__versions_get` (also callable as `g8.api.call("list_skill_versions_skills__action_id__versions_get", input)`)
1350
+ - Tier: `read`: reads data; safe to call and to retry
1351
+ - API-key scope: `workflows:read`
1352
+
1353
+ SPENDS NOTHING. Version history, newest first, with the published one
1354
+ marked. Compare two with `GET /skills/{action_id}/versions/{version_id}/diff`.
1355
+
1356
+ **Input**
1357
+
1358
+ | Field | Type | Required | Description |
1359
+ |---|---|---|---|
1360
+ | `path.action_id` | `string` | yes | Skill (action) id. |
1361
+ | `query.limit` | `integer` | no | Newest first. default `50` |
1362
+
1363
+ **Returns** `ApiResponse_VoicePayload_`: the envelope `{ data: VoicePayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1364
+
1365
+ Other envelope fields: `pagination` (PaginationMeta).
1366
+
1367
+ **Example**
1368
+
1369
+ ```ts
1370
+ const result = await g8.api.workflows.listSkillVersions({ path: { action_id: "id" } });
1371
+ ```
1372
+
1373
+ ---
1374
+
1375
+ <a id="op-listslackchannels"></a>
1376
+
1377
+ ### `g8.api.workflows.listSlackChannels(input?)`
1378
+
1379
+ **List Slack channels for the org (resolver helper)**
1380
+
1381
+ - HTTP: `GET /api/v1/workflows/integrations/slack/channels`
1382
+ - operationId: `list_slack_channels_workflows_integrations_slack_channels_get` (also callable as `g8.api.call("list_slack_channels_workflows_integrations_slack_channels_get", input)`)
1383
+ - Tier: `read`: reads data; safe to call and to retry
1384
+ - API-key scope: `workflows:read`
1385
+ - ★ Hand-written: [`g8.workflows.listSlackChannels()`](../sdk-clients.md#g8-workflows-listslackchannels)
1386
+
1387
+ Return Slack channels for ``send_slack_notification.channel_id`` resolution.
1388
+
1389
+ **Input**: none.
1390
+
1391
+ **Returns** `Record<string, unknown>`.
1392
+
1393
+ **Example**
1394
+
1395
+ ```ts
1396
+ const result = await g8.api.workflows.listSlackChannels();
1397
+ ```
1398
+
1399
+ ---
1400
+
1401
+ <a id="op-listslackusers"></a>
1402
+
1403
+ ### `g8.api.workflows.listSlackUsers(input?)`
1404
+
1405
+ **List Slack users for the org (resolver helper)**
1406
+
1407
+ - HTTP: `GET /api/v1/workflows/integrations/slack/users`
1408
+ - operationId: `list_slack_users_workflows_integrations_slack_users_get` (also callable as `g8.api.call("list_slack_users_workflows_integrations_slack_users_get", input)`)
1409
+ - Tier: `read`: reads data; safe to call and to retry
1410
+ - API-key scope: `workflows:read`
1411
+ - ★ Hand-written: [`g8.workflows.listSlackUsers()`](../sdk-clients.md#g8-workflows-listslackusers)
1412
+
1413
+ Return Slack workspace users for ``send_slack_notification.user_id`` resolution.
1414
+
1415
+ **Input**: none.
1416
+
1417
+ **Returns** `Record<string, unknown>`.
1418
+
1419
+ **Example**
1420
+
1421
+ ```ts
1422
+ const result = await g8.api.workflows.listSlackUsers();
1423
+ ```
1424
+
1425
+ ---
1426
+
1427
+ <a id="op-listworkbenches"></a>
1428
+
1429
+ ### `g8.api.workflows.listWorkbenches(input?)`
1430
+
1431
+ **List workbenches for the org (resolver helper)**
1432
+
1433
+ - HTTP: `GET /api/v1/workflows/workbenches`
1434
+ - operationId: `list_workbenches_workflows_workbenches_get` (also callable as `g8.api.call("list_workbenches_workflows_workbenches_get", input)`)
1435
+ - Tier: `read`: reads data; safe to call and to retry
1436
+ - API-key scope: `workflows:read`
1437
+
1438
+ Resolve a workbench NAME into the `workbench_id` the workbench nodes need.
1439
+
1440
+ Returns ``{workbenches: [{workbench_id, name, entity_type, description,
1441
+ row_count, created_at}], total, page, limit}``.
1442
+
1443
+ ``workbench_id`` is the value to paste straight into a node config. It is the
1444
+ same id the Workbench page URL shows, so an agent and a human are naming the
1445
+ same thing.
1446
+
1447
+ Org is pinned from the authenticated caller and used as the tenant scope;
1448
+ nothing client-supplied selects the tenant.
1449
+
1450
+ **Input**
1451
+
1452
+ | Field | Type | Required | Description |
1453
+ |---|---|---|---|
1454
+ | `query.limit` | `integer` | no | Page size. default `50` |
1455
+ | `query.page` | `integer` | no | 1-based page number. default `1` |
1456
+ | `query.filter_name` | `string \| null` | no | Case-insensitive name filter. |
1457
+
1458
+ **Returns** `Record<string, unknown>`.
1459
+
1460
+ **Example**
1461
+
1462
+ ```ts
1463
+ const result = await g8.api.workflows.listWorkbenches();
1464
+ ```
1465
+
1466
+ ---
1467
+
1468
+ <a id="op-listworkflowexecutions"></a>
1469
+
1470
+ ### `g8.api.workflows.listWorkflowExecutions(input?)`
1471
+
1472
+ **List workflow executions for the caller's org (recover a lost execution_id)**
1473
+
1474
+ - HTTP: `GET /api/v1/workflows/executions`
1475
+ - operationId: `list_workflow_executions_workflows_executions_get` (also callable as `g8.api.call("list_workflow_executions_workflows_executions_get", input)`)
1476
+ - Tier: `read`: reads data; safe to call and to retry
1477
+ - API-key scope: `workflows:read`
1478
+
1479
+ List this org's workflow executions, newest first, with SQL-side
1480
+ pagination - the recovery path for a lost ``execution_id`` (the single
1481
+ ``GET /workflows/executions/{execution_id}`` read below needs an id you
1482
+ no longer have).
1483
+
1484
+ Org is pinned server-side from the authenticated caller and passed to
1485
+ voice in the PATH; a client-supplied ``org_id`` query param is ignored,
1486
+ so one tenant can never list another tenant's executions (the voice
1487
+ backing route trusts its path ``org_id``, so pinning here is the tenant
1488
+ boundary - getting it wrong is a cross-org IDOR). ``runtime_type`` is
1489
+ pinned to ``workflow`` so only workflow runs surface here, matching the
1490
+ sibling ``GET /workflows`` which does not expose raw LLM/API/script
1491
+ action runs.
1492
+
1493
+ Proxies voice's ``GET /api/v1/executions/list/{org_id}`` and returns its
1494
+ ``ExecutionListResponse`` shape unchanged - ``{executions: [...],
1495
+ total_count: int}`` - consistent with this router's pass-through
1496
+ convention (voice owns the execution DTO; re-declaring its ~20 fields
1497
+ here would only drift). Voice also clamps ``limit`` to 1..200 SQL-side;
1498
+ the bounds here reject an out-of-range page with a clean 422 before the
1499
+ round-trip.
1500
+
1501
+ Read-only and additive: nothing is created, and no existing route changes.
1502
+
1503
+ **Input**
1504
+
1505
+ | Field | Type | Required | Description |
1506
+ |---|---|---|---|
1507
+ | `query.action_id` | `string \| null` | no | Filter to a single workflow's executions. |
1508
+ | `query.status_filter` | `string \| null` | no | Filter by execution status (equality match — one status per call). The backend writes seven values: pending\|running\|completed\|failed\|paused\|pending_approval\|stopped. The four terminal-or-early states are pending, running, completed, failed; paused and pending_approval are resumable, stopped is terminal. |
1509
+ | `query.triggered_by` | `string \| null` | no | Filter by the identity that started the run (user email, agent id, 'api', ...). |
1510
+ | `query.limit` | `integer` | no | Page size (1..200). default `50` |
1511
+ | `query.offset` | `integer` | no | Rows to skip for pagination. default `0` |
1512
+
1513
+ **Returns** `Record<string, unknown>`.
1514
+
1515
+ **Example**
1516
+
1517
+ ```ts
1518
+ const result = await g8.api.workflows.listWorkflowExecutions();
1519
+ ```
1520
+
1521
+ ---
1522
+
1523
+ <a id="op-listworkflowintegrations"></a>
1524
+
1525
+ ### `g8.api.workflows.listWorkflowIntegrations(input?)`
1526
+
1527
+ **List connected workflow integrations**
1528
+
1529
+ - HTTP: `GET /api/v1/workflows/integrations`
1530
+ - operationId: `list_workflow_integrations_workflows_integrations_get` (also callable as `g8.api.call("list_workflow_integrations_workflows_integrations_get", input)`)
1531
+ - Tier: `read`: reads data; safe to call and to retry
1532
+ - API-key scope: `workflows:read`
1533
+
1534
+ Which third-party accounts workflow nodes can act as.
1535
+
1536
+ Rows report `has_api_key` rather than the key: credentials on this surface
1537
+ are write-only and are never echoed back.
1538
+
1539
+ **Input**: none.
1540
+
1541
+ **Returns** `ApiResponse_VoiceListPayload_`: the envelope `{ data: VoiceListPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1542
+
1543
+ Other envelope fields: `pagination` (PaginationMeta).
1544
+
1545
+ `VoiceListPayload` fields:
1546
+
1547
+ | Field | Type | Required | Description |
1548
+ |---|---|---|---|
1549
+ | `items` | `Array<unknown>` | no | |
1550
+
1551
+ **Example**
1552
+
1553
+ ```ts
1554
+ const result = await g8.api.workflows.listWorkflowIntegrations();
1555
+ ```
1556
+
1557
+ ---
1558
+
1559
+ <a id="op-listworkflows"></a>
1560
+
1561
+ ### `g8.api.workflows.listWorkflows(input?)`
1562
+
1563
+ **List workflows for the caller's org**
1564
+
1565
+ - HTTP: `GET /api/v1/workflows`
1566
+ - operationId: `list_workflows_workflows_get` (also callable as `g8.api.call("list_workflows_workflows_get", input)`)
1567
+ - Tier: `read`: reads data; safe to call and to retry
1568
+ - API-key scope: `workflows:read`
1569
+ - ★ Hand-written: [`g8.workflows.list()`](../sdk-clients.md#g8-workflows-list)
1570
+
1571
+ List workflow actions (``runtime_type='workflow'``) owned by the org.
1572
+
1573
+ Voice's underlying ``GET /list/{org_id}`` lists all actions; we pin
1574
+ ``runtime_type=workflow`` so the public surface returns workflows
1575
+ only. Raw action listing (LLM/API/script skills) is intentionally
1576
+ not exposed here.
1577
+
1578
+ **Input**
1579
+
1580
+ | Field | Type | Required | Description |
1581
+ |---|---|---|---|
1582
+ | `query.enabled` | `boolean \| null` | no | Filter by enabled flag. |
1583
+ | `query.category` | `string \| null` | no | Filter by category. |
1584
+ | `query.is_template` | `boolean \| null` | no | Templates only when true. |
1585
+
1586
+ **Returns** `Record<string, unknown>`.
1587
+
1588
+ **Example**
1589
+
1590
+ ```ts
1591
+ const result = await g8.api.workflows.listWorkflows();
1592
+ ```
1593
+
1594
+ ---
1595
+
1596
+ <a id="op-parsescriptparameters"></a>
1597
+
1598
+ ### `g8.api.workflows.parseScriptParameters(input)`
1599
+
1600
+ **Detect a script's parameters from its code**
1601
+
1602
+ - HTTP: `POST /api/v1/skills/parse-script-parameters`
1603
+ - operationId: `parse_script_parameters_skills_parse_script_parameters_post` (also callable as `g8.api.call("parse_script_parameters_skills_parse_script_parameters_post", input)`)
1604
+ - Tier: `write`: creates or changes records; the SDK sends an Idempotency-Key and retries transient failures
1605
+ - API-key scope: `workflows:write`
1606
+
1607
+ Static analysis, not execution. The code is PARSED and never run.
1608
+
1609
+ Returns the detected parameter names with their types and defaults, which
1610
+ is how a builder offers the right inputs for a script it did not write.
1611
+
1612
+ **Input**
1613
+
1614
+ | Field | Type | Required | Description |
1615
+ |---|---|---|---|
1616
+ | `body` | `Body_parse_script_parameters_skills_parse_script_parameters_post` | yes | Request body; fields below. |
1617
+
1618
+ Body fields (`Body_parse_script_parameters_skills_parse_script_parameters_post`):
1619
+
1620
+ | Field | Type | Required | Description |
1621
+ |---|---|---|---|
1622
+ | `body.code` | `string` | yes | The script source. |
1623
+ | `body.language` | `string` | no | "python", "javascript" or "typescript". default `"python"` |
1624
+
1625
+ **Returns** `ApiResponse_VoicePayload_`: the envelope `{ data: VoicePayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1626
+
1627
+ Other envelope fields: `pagination` (PaginationMeta).
1628
+
1629
+ **Example**
1630
+
1631
+ ```ts
1632
+ const result = await g8.api.workflows.parseScriptParameters({ body: { code: "example" } });
1633
+ ```
1634
+
1635
+ ---
1636
+
1637
+ <a id="op-pauseexecution"></a>
1638
+
1639
+ ### `g8.api.workflows.pauseExecution(input)`
1640
+
1641
+ **Pause a running execution (tenant-checked)**
1642
+
1643
+ - HTTP: `POST /api/v1/workflows/executions/{execution_id}/pause`
1644
+ - operationId: `pause_execution_workflows_executions__execution_id__pause_post` (also callable as `g8.api.call("pause_execution_workflows_executions__execution_id__pause_post", input)`)
1645
+ - 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
1646
+ - API-key scope: `workflows:run`
1647
+ - ★ Hand-written: [`g8.workflows.pauseExecution()`](../sdk-clients.md#g8-workflows-pauseexecution)
1648
+
1649
+ Pause a running workflow execution. Pre-flight enforces that the
1650
+ execution belongs to the caller's org before forwarding to voice.
1651
+
1652
+ **Input**
1653
+
1654
+ | Field | Type | Required | Description |
1655
+ |---|---|---|---|
1656
+ | `path.execution_id` | `string` | yes | Execution UUID. |
1657
+ | `body` | `Record<string, unknown>` | no | Request body; fields below. |
1658
+
1659
+ **Returns** `Record<string, unknown>`.
1660
+
1661
+ **Example**
1662
+
1663
+ ```ts
1664
+ // external: reaches real people (sends email/SMS, places a call, launches a send); the SDK never blindly retries it; confirm with a human first.
1665
+ const result = await g8.api.workflows.pauseExecution({ path: { execution_id: "id" } });
1666
+ ```
1667
+
1668
+ ---
1669
+
1670
+ <a id="op-planinlineworkflow"></a>
1671
+
1672
+ ### `g8.api.workflows.planInlineWorkflow(input)`
1673
+
1674
+ **Preview a normalized execution plan for an inline workflow graph**
1675
+
1676
+ - HTTP: `POST /api/v1/workflows/plan`
1677
+ - operationId: `plan_inline_workflow_workflows_plan_post` (also callable as `g8.api.call("plan_inline_workflow_workflows_plan_post", input)`)
1678
+ - Tier: `read`: reads data; safe to call and to retry
1679
+ - API-key scope: `workflows:read`
1680
+
1681
+ Compute a normalized plan for a graph that is NOT yet saved. Accepts
1682
+ either ``{config: {...}}`` or a raw graph ``{nodes, edges, start_node_id}``
1683
+ directly. Read-only: nothing is persisted or executed.
1684
+
1685
+ **Input**
1686
+
1687
+ | Field | Type | Required | Description |
1688
+ |---|---|---|---|
1689
+ | `body` | `Record<string, unknown>` | yes | Request body; fields below. |
1690
+
1691
+ **Returns** `Record<string, unknown>`.
1692
+
1693
+ **Example**
1694
+
1695
+ ```ts
1696
+ const result = await g8.api.workflows.planInlineWorkflow({ body: {} });
1697
+ ```
1698
+
1699
+ ---
1700
+
1701
+ <a id="op-planworkflow"></a>
1702
+
1703
+ ### `g8.api.workflows.planWorkflow(input)`
1704
+
1705
+ **Preview a normalized execution plan for a saved workflow**
1706
+
1707
+ - HTTP: `POST /api/v1/workflows/{action_id}/plan`
1708
+ - operationId: `plan_workflow_workflows__action_id__plan_post` (also callable as `g8.api.call("plan_workflow_workflows__action_id__plan_post", input)`)
1709
+ - Tier: `read`: reads data; safe to call and to retry
1710
+ - API-key scope: `workflows:read`
1711
+
1712
+ Fetch a saved workflow's graph and compute its normalized plan. Org is
1713
+ pinned server-side; the caller cannot preview another tenant's workflow.
1714
+ Read-only.
1715
+
1716
+ **Input**
1717
+
1718
+ | Field | Type | Required | Description |
1719
+ |---|---|---|---|
1720
+ | `path.action_id` | `string` | yes | Workflow action_id. |
1721
+ | `body` | `Record<string, unknown>` | no | Request body; fields below. |
1722
+
1723
+ **Returns** `Record<string, unknown>`.
1724
+
1725
+ **Example**
1726
+
1727
+ ```ts
1728
+ const result = await g8.api.workflows.planWorkflow({ path: { action_id: "id" } });
1729
+ ```
1730
+
1731
+ ---
1732
+
1733
+ <a id="op-rejectexecution"></a>
1734
+
1735
+ ### `g8.api.workflows.rejectExecution(input)`
1736
+
1737
+ **Reject a run waiting on a human**
1738
+
1739
+ - HTTP: `POST /api/v1/workflows/executions/reject`
1740
+ - operationId: `reject_execution_workflows_executions_reject_post` (also callable as `g8.api.call("reject_execution_workflows_executions_reject_post", input)`)
1741
+ - Tier: `write`: creates or changes records; the SDK sends an Idempotency-Key and retries transient failures
1742
+ - API-key scope: `workflows:write`
1743
+
1744
+ SPENDS NOTHING. The held action is NOT performed and the run ends. For
1745
+ "try again with changes" use `POST /workflows/executions/request-changes`.
1746
+
1747
+ **Input**
1748
+
1749
+ | Field | Type | Required | Description |
1750
+ |---|---|---|---|
1751
+ | `body` | `ExecutionRejection` | yes | Request body; fields below. |
1752
+
1753
+ Body fields (`ExecutionRejection`):
1754
+
1755
+ | Field | Type | Required | Description |
1756
+ |---|---|---|---|
1757
+ | `body.rejected_by` | `string` | yes | Who rejected; voice checks they may. min length 1 |
1758
+ | `body.workflow_id` | `string` | yes | The paused run's workflow id. min length 1 |
1759
+ | `body.reason` | `string \| null` | no | max length 2000 |
1760
+
1761
+ **Returns** `ApiResponse_VoicePayload_`: the envelope `{ data: VoicePayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1762
+
1763
+ Other envelope fields: `pagination` (PaginationMeta).
1764
+
1765
+ **Example**
1766
+
1767
+ ```ts
1768
+ const result = await g8.api.workflows.rejectExecution({ body: { rejected_by: "example", workflow_id: "id" } });
1769
+ ```
1770
+
1771
+ ---
1772
+
1773
+ <a id="op-requestexecutionchanges"></a>
1774
+
1775
+ ### `g8.api.workflows.requestExecutionChanges(input)`
1776
+
1777
+ **Answer a human-approval step with changes requested**
1778
+
1779
+ - HTTP: `POST /api/v1/workflows/executions/request-changes`
1780
+ - operationId: `request_execution_changes_workflows_executions_request_changes_post` (also callable as `g8.api.call("request_execution_changes_workflows_executions_request_changes_post", input)`)
1781
+ - 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
1782
+ - API-key scope: `workflows:run`
1783
+
1784
+ The THIRD outcome of a human-approval step, beside approve and reject.
1785
+
1786
+ Approve and reject are terminal for the paused node. This one is not: it
1787
+ sends the run down the revise branch carrying the reviewer's words, so the
1788
+ workflow gets another attempt instead of ending.
1789
+
1790
+ **Input**
1791
+
1792
+ | Field | Type | Required | Description |
1793
+ |---|---|---|---|
1794
+ | `body` | `Body_request_execution_changes_workflows_executions_request_changes_post` | yes | Request body; fields below. |
1795
+
1796
+ Body fields (`Body_request_execution_changes_workflows_executions_request_changes_post`):
1797
+
1798
+ | Field | Type | Required | Description |
1799
+ |---|---|---|---|
1800
+ | `body.feedback` | `string` | yes | REQUIRED and non-blank. It is the value the revise branch reads as `${<human_node>.feedback}` - an empty one sends the workflow down the revise path with nothing to revise against. min length 1, max length 2000 |
1801
+ | `body.requested_by` | `string` | yes | Who is asking for changes. |
1802
+ | `body.workflow_id` | `string` | yes | The workflow the run belongs to. |
1803
+
1804
+ **Returns** `ApiResponse_VoicePayload_`: the envelope `{ data: VoicePayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1805
+
1806
+ Other envelope fields: `pagination` (PaginationMeta).
1807
+
1808
+ **Example**
1809
+
1810
+ ```ts
1811
+ // external: reaches real people (sends email/SMS, places a call, launches a send); the SDK never blindly retries it; confirm with a human first.
1812
+ const result = await g8.api.workflows.requestExecutionChanges({
1813
+ body: { feedback: "example", requested_by: "example", workflow_id: "id" },
1814
+ });
1815
+ ```
1816
+
1817
+ ---
1818
+
1819
+ <a id="op-resettriggercursor"></a>
1820
+
1821
+ ### `g8.api.workflows.resetTriggerCursor(input)`
1822
+
1823
+ **Reset the trigger cursor to now**
1824
+
1825
+ - HTTP: `POST /api/v1/workflows/{action_id}/trigger-reset`
1826
+ - operationId: `reset_trigger_cursor_workflows__action_id__trigger_reset_post` (also callable as `g8.api.call("reset_trigger_cursor_workflows__action_id__trigger_reset_post", input)`)
1827
+ - 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
1828
+ - API-key scope: `workflows:run`
1829
+ - ★ Hand-written: [`g8.workflows.resetTrigger()`](../sdk-clients.md#g8-workflows-resettrigger)
1830
+
1831
+ Stop reprocessing old events - sets the trigger cursor to now().
1832
+
1833
+ **Input**
1834
+
1835
+ | Field | Type | Required | Description |
1836
+ |---|---|---|---|
1837
+ | `path.action_id` | `string` | yes | Workflow action_id. |
1838
+
1839
+ **Returns** `Record<string, unknown>`.
1840
+
1841
+ **Example**
1842
+
1843
+ ```ts
1844
+ // external: reaches real people (sends email/SMS, places a call, launches a send); the SDK never blindly retries it; confirm with a human first.
1845
+ const result = await g8.api.workflows.resetTriggerCursor({ path: { action_id: "id" } });
1846
+ ```
1847
+
1848
+ ---
1849
+
1850
+ <a id="op-resolveskilltemplates"></a>
1851
+
1852
+ ### `g8.api.workflows.resolveSkillTemplates(input)`
1853
+
1854
+ **Resolve skill template names to ids**
1855
+
1856
+ - HTTP: `POST /api/v1/skills/resolve-templates`
1857
+ - operationId: `resolve_skill_templates_skills_resolve_templates_post` (also callable as `g8.api.call("resolve_skill_templates_skills_resolve_templates_post", input)`)
1858
+ - Tier: `write`: creates or changes records; the SDK sends an Idempotency-Key and retries transient failures
1859
+ - API-key scope: `workflows:write`
1860
+
1861
+ Turn human template names into the `action_id`s every other route wants.
1862
+
1863
+ The lookup that lets a caller write "Cold Call Opener" where the API needs
1864
+ a UUID. `org_id` is pinned from the key, so a name resolves within the
1865
+ caller's own templates.
1866
+
1867
+ **Input**
1868
+
1869
+ | Field | Type | Required | Description |
1870
+ |---|---|---|---|
1871
+ | `body` | `Record<string, unknown>` | yes | Request body; fields below. |
1872
+
1873
+ **Returns** `ApiResponse_VoicePayload_`: the envelope `{ data: VoicePayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1874
+
1875
+ Other envelope fields: `pagination` (PaginationMeta).
1876
+
1877
+ **Example**
1878
+
1879
+ ```ts
1880
+ const result = await g8.api.workflows.resolveSkillTemplates({ body: {} });
1881
+ ```
1882
+
1883
+ ---
1884
+
1885
+ <a id="op-restartexecution"></a>
1886
+
1887
+ ### `g8.api.workflows.restartExecution(input)`
1888
+
1889
+ **Restart one workflow execution**
1890
+
1891
+ - HTTP: `POST /api/v1/workflows/executions/{execution_id}/restart`
1892
+ - operationId: `restart_execution_workflows_executions__execution_id__restart_post` (also callable as `g8.api.call("restart_execution_workflows_executions__execution_id__restart_post", input)`)
1893
+ - 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
1894
+ - API-key scope: `workflows:run`
1895
+
1896
+ Runs the workflow again FROM THE BEGINNING. Not a resume.
1897
+
1898
+ Nodes that already succeeded run a second time. If any of them sent an
1899
+ email, posted to Slack or called a paid API, they do it again. To continue
1900
+ a paused run instead, use `POST /workflows/executions/{id}/resume`.
1901
+
1902
+ The org is forwarded and voice scopes the lookup by it, so one tenant
1903
+ cannot restart another's run.
1904
+
1905
+ **Input**
1906
+
1907
+ | Field | Type | Required | Description |
1908
+ |---|---|---|---|
1909
+ | `path.execution_id` | `string` | yes | Execution id. |
1910
+ | `body` | `Record<string, unknown>` | no | Request body; fields below. |
1911
+
1912
+ **Returns** `ApiResponse_VoicePayload_`: the envelope `{ data: VoicePayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1913
+
1914
+ Other envelope fields: `pagination` (PaginationMeta).
1915
+
1916
+ **Example**
1917
+
1918
+ ```ts
1919
+ // external: reaches real people (sends email/SMS, places a call, launches a send); the SDK never blindly retries it; confirm with a human first.
1920
+ const result = await g8.api.workflows.restartExecution({ path: { execution_id: "id" } });
1921
+ ```
1922
+
1923
+ ---
1924
+
1925
+ <a id="op-restoreskillversion"></a>
1926
+
1927
+ ### `g8.api.workflows.restoreSkillVersion(input)`
1928
+
1929
+ **Restore an earlier version of a skill**
1930
+
1931
+ - HTTP: `POST /api/v1/skills/{action_id}/versions/{version_id}/restore`
1932
+ - operationId: `restore_skill_version_skills__action_id__versions__version_id__restore_post` (also callable as `g8.api.call("restore_skill_version_skills__action_id__versions__version_id__restore_post", input)`)
1933
+ - Tier: `write`: creates or changes records; the SDK sends an Idempotency-Key and retries transient failures
1934
+ - API-key scope: `workflows:write`
1935
+
1936
+ SPENDS NOTHING. Publishes the old snapshot as a NEW version, live for the
1937
+ next run - agents and workflows using the skill pick it up. Append-only, so
1938
+ the restore can itself be rolled back. Routine-managed skills refuse (403).
1939
+
1940
+ **Input**
1941
+
1942
+ | Field | Type | Required | Description |
1943
+ |---|---|---|---|
1944
+ | `path.action_id` | `string` | yes | Skill (action) id. |
1945
+ | `path.version_id` | `string` | yes | The version to bring back. |
1946
+
1947
+ **Returns** `ApiResponse_VoicePayload_`: the envelope `{ data: VoicePayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
1948
+
1949
+ Other envelope fields: `pagination` (PaginationMeta).
1950
+
1951
+ **Example**
1952
+
1953
+ ```ts
1954
+ const result = await g8.api.workflows.restoreSkillVersion({ path: { action_id: "id", version_id: "id" } });
1955
+ ```
1956
+
1957
+ ---
1958
+
1959
+ <a id="op-resumeexecution"></a>
1960
+
1961
+ ### `g8.api.workflows.resumeExecution(input)`
1962
+
1963
+ **Resume a paused execution (tenant-checked)**
1964
+
1965
+ - HTTP: `POST /api/v1/workflows/executions/{execution_id}/resume`
1966
+ - operationId: `resume_execution_workflows_executions__execution_id__resume_post` (also callable as `g8.api.call("resume_execution_workflows_executions__execution_id__resume_post", input)`)
1967
+ - 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
1968
+ - API-key scope: `workflows:run`
1969
+ - ★ Hand-written: [`g8.workflows.resumeExecution()`](../sdk-clients.md#g8-workflows-resumeexecution)
1970
+
1971
+ Resume a paused execution. Pre-flight enforces tenant ownership.
1972
+
1973
+ **Input**
1974
+
1975
+ | Field | Type | Required | Description |
1976
+ |---|---|---|---|
1977
+ | `path.execution_id` | `string` | yes | Execution UUID. |
1978
+ | `body` | `Record<string, unknown>` | no | Request body; fields below. |
1979
+
1980
+ **Returns** `Record<string, unknown>`.
1981
+
1982
+ **Example**
1983
+
1984
+ ```ts
1985
+ // external: reaches real people (sends email/SMS, places a call, launches a send); the SDK never blindly retries it; confirm with a human first.
1986
+ const result = await g8.api.workflows.resumeExecution({ path: { execution_id: "id" } });
1987
+ ```
1988
+
1989
+ ---
1990
+
1991
+ <a id="op-runskilltestsuite"></a>
1992
+
1993
+ ### `g8.api.workflows.runSkillTestSuite(input)`
1994
+
1995
+ **Run every saved test case against a skill**
1996
+
1997
+ - HTTP: `POST /api/v1/skills/{action_id}/test-runs`
1998
+ - operationId: `run_skill_test_suite_skills__action_id__test_runs_post` (also callable as `g8.api.call("run_skill_test_suite_skills__action_id__test_runs_post", input)`)
1999
+ - 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
2000
+ - API-key scope: `workflows:run`
2001
+
2002
+ RUNS THE SKILL, ONCE PER SAVED CASE. This has real side effects.
2003
+
2004
+ For an `llm` skill that is a model call per case. For an `api` skill it is
2005
+ an outbound HTTP request per case, to the endpoint the skill is configured
2006
+ with, made AS THE PLATFORM - so a skill that writes somewhere will write
2007
+ there again, with the fixture's data.
2008
+
2009
+ Every case is pinned to ONE version of the skill, so the result is a
2010
+ regression answer rather than a mix of versions.
2011
+
2012
+ Tiered `external` by an explicit rule, for the same reason
2013
+ `POST /skills/{action_id}/execute` is: it reaches outside graph8 on the
2014
+ customer's behalf, and nothing in the path name says so.
2015
+
2016
+ **Input**
2017
+
2018
+ | Field | Type | Required | Description |
2019
+ |---|---|---|---|
2020
+ | `path.action_id` | `string` | yes | Skill or workflow `action_id`. |
2021
+
2022
+ **Returns** `ApiResponse_VoicePayload_`: the envelope `{ data: VoicePayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
2023
+
2024
+ Other envelope fields: `pagination` (PaginationMeta).
2025
+
2026
+ **Example**
2027
+
2028
+ ```ts
2029
+ // external: reaches real people (sends email/SMS, places a call, launches a send); the SDK never blindly retries it; confirm with a human first.
2030
+ const result = await g8.api.workflows.runSkillTestSuite({ path: { action_id: "id" } });
2031
+ ```
2032
+
2033
+ ---
2034
+
2035
+ <a id="op-saveworkflowintegration"></a>
2036
+
2037
+ ### `g8.api.workflows.saveWorkflowIntegration(input)`
2038
+
2039
+ **Connect or update a workflow integration**
2040
+
2041
+ - HTTP: `POST /api/v1/workflows/integrations/{provider_name}`
2042
+ - operationId: `save_workflow_integration_workflows_integrations__provider_name__post` (also callable as `g8.api.call("save_workflow_integration_workflows_integrations__provider_name__post", input)`)
2043
+ - Tier: `write`: creates or changes records; the SDK sends an Idempotency-Key and retries transient failures
2044
+ - API-key scope: `workflows:write`
2045
+
2046
+ UPSERT: creates the integration or replaces its configuration.
2047
+
2048
+ POST rather than PUT because that is the verb voice exposes, and one
2049
+ spelling is better than two.
2050
+
2051
+ Whatever is stored here is used BY WORKFLOW NODES ACTING AS THE PLATFORM,
2052
+ so a key placed here is a standing grant, not a one-off.
2053
+
2054
+ **Input**
2055
+
2056
+ | Field | Type | Required | Description |
2057
+ |---|---|---|---|
2058
+ | `path.provider_name` | `string` | yes | Provider name. |
2059
+ | `body` | `Body_save_workflow_integration_workflows_integrations__provider_name__post` | no | Request body; fields below. |
2060
+
2061
+ Body fields (`Body_save_workflow_integration_workflows_integrations__provider_name__post`):
2062
+
2063
+ | Field | Type | Required | Description |
2064
+ |---|---|---|---|
2065
+ | `body.api_key` | `string \| null` | no | The provider credential. WRITE-ONLY: no route on this API returns it. Omitting it on an update leaves the stored key in place. |
2066
+ | `body.configuration` | `Record<string, unknown> \| null` | no | Provider-specific settings. |
2067
+
2068
+ **Returns** `ApiResponse_VoicePayload_`: the envelope `{ data: VoicePayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
2069
+
2070
+ Other envelope fields: `pagination` (PaginationMeta).
2071
+
2072
+ **Example**
2073
+
2074
+ ```ts
2075
+ const result = await g8.api.workflows.saveWorkflowIntegration({ path: { provider_name: "Example" } });
2076
+ ```
2077
+
2078
+ ---
2079
+
2080
+ <a id="op-stopexecution"></a>
2081
+
2082
+ ### `g8.api.workflows.stopExecution(input)`
2083
+
2084
+ **Permanently stop an execution (tenant-checked)**
2085
+
2086
+ - HTTP: `POST /api/v1/workflows/executions/{execution_id}/stop`
2087
+ - operationId: `stop_execution_workflows_executions__execution_id__stop_post` (also callable as `g8.api.call("stop_execution_workflows_executions__execution_id__stop_post", input)`)
2088
+ - 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
2089
+ - API-key scope: `workflows:run`
2090
+ - ★ Hand-written: [`g8.workflows.stopExecution()`](../sdk-clients.md#g8-workflows-stopexecution)
2091
+
2092
+ Stop an execution permanently. Pre-flight enforces tenant ownership.
2093
+
2094
+ **Input**
2095
+
2096
+ | Field | Type | Required | Description |
2097
+ |---|---|---|---|
2098
+ | `path.execution_id` | `string` | yes | Execution UUID. |
2099
+ | `body` | `Record<string, unknown>` | no | Request body; fields below. |
2100
+
2101
+ **Returns** `Record<string, unknown>`.
2102
+
2103
+ **Example**
2104
+
2105
+ ```ts
2106
+ // external: reaches real people (sends email/SMS, places a call, launches a send); the SDK never blindly retries it; confirm with a human first.
2107
+ const result = await g8.api.workflows.stopExecution({ path: { execution_id: "id" } });
2108
+ ```
2109
+
2110
+ ---
2111
+
2112
+ <a id="op-testintegrationcredential"></a>
2113
+
2114
+ ### `g8.api.workflows.testIntegrationCredential(input)`
2115
+
2116
+ **Try a Roam or Slack token**
2117
+
2118
+ - HTTP: `POST /api/v1/workflows/integrations/{provider_name}/test`
2119
+ - operationId: `test_integration_credential_workflows_integrations__provider_name__test_post` (also callable as `g8.api.call("test_integration_credential_workflows_integrations__provider_name__test_post", input)`)
2120
+ - 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
2121
+ - API-key scope: `workflows:run`
2122
+
2123
+ REACHES OUTSIDE GRAPH8. Calls the provider with the token and reports
2124
+ whether it works (`success`, `error`). The token is not stored; save it with
2125
+ `PUT /workflows/integrations/{provider_name}`.
2126
+
2127
+ **Input**
2128
+
2129
+ | Field | Type | Required | Description |
2130
+ |---|---|---|---|
2131
+ | `path.provider_name` | `"roam" \| "slack"` | yes | roam or slack. |
2132
+ | `body` | `IntegrationCredentialTest` | yes | Request body; fields below. |
2133
+
2134
+ Body fields (`IntegrationCredentialTest`):
2135
+
2136
+ | Field | Type | Required | Description |
2137
+ |---|---|---|---|
2138
+ | `body.api_key` | `string` | yes | The token to try. Not stored. min length 1 |
2139
+
2140
+ **Returns** `ApiResponse_VoicePayload_`: the envelope `{ data: VoicePayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
2141
+
2142
+ Other envelope fields: `pagination` (PaginationMeta).
2143
+
2144
+ **Example**
2145
+
2146
+ ```ts
2147
+ // external: reaches real people (sends email/SMS, places a call, launches a send); the SDK never blindly retries it; confirm with a human first.
2148
+ const result = await g8.api.workflows.testIntegrationCredential({ path: { provider_name: "roam" }, body: { api_key: "example" } });
2149
+ ```
2150
+
2151
+ ---
2152
+
2153
+ <a id="op-testskillonce"></a>
2154
+
2155
+ ### `g8.api.workflows.testSkillOnce(input)`
2156
+
2157
+ **Dry-run a skill once**
2158
+
2159
+ - HTTP: `POST /api/v1/skills/{action_id}/test`
2160
+ - operationId: `test_skill_once_skills__action_id__test_post` (also callable as `g8.api.call("test_skill_once_skills__action_id__test_post", input)`)
2161
+ - Tier: `write`: creates or changes records; the SDK sends an Idempotency-Key and retries transient failures
2162
+ - API-key scope: `workflows:write`
2163
+
2164
+ SPENDS NOTHING. One DRY run from a saved case or ad-hoc inputs: returns
2165
+ the resolved prompt (llm skills) or the unsent request with secrets masked
2166
+ (api skills). Never calls a model, never sends, never writes an execution.
2167
+
2168
+ **Input**
2169
+
2170
+ | Field | Type | Required | Description |
2171
+ |---|---|---|---|
2172
+ | `path.action_id` | `string` | yes | Skill (action) id. |
2173
+ | `body` | `SkillTestRun` | yes | Request body; fields below. |
2174
+
2175
+ Body fields (`SkillTestRun`):
2176
+
2177
+ | Field | Type | Required | Description |
2178
+ |---|---|---|---|
2179
+ | `body.assertion_config` | `Record<string, unknown> \| null` | no | Ad-hoc only. |
2180
+ | `body.assertion_type` | `"exact" \| "contains" \| "llm_judge" \| null` | no | Ad-hoc only. |
2181
+ | `body.expected_output` | `unknown \| null` | no | Ad-hoc only: value to assert against. |
2182
+ | `body.input_data` | `Record<string, unknown> \| null` | no | Ad-hoc inputs (no saved case). |
2183
+ | `body.test_case_id` | `string \| null` | no | Run this saved case. |
2184
+ | `body.triggered_by` | `string \| null` | no | Attribution for the run history. |
2185
+
2186
+ **Returns** `ApiResponse_VoicePayload_`: the envelope `{ data: VoicePayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
2187
+
2188
+ Other envelope fields: `pagination` (PaginationMeta).
2189
+
2190
+ **Example**
2191
+
2192
+ ```ts
2193
+ const result = await g8.api.workflows.testSkillOnce({ path: { action_id: "id" }, body: {} });
2194
+ ```
2195
+
2196
+ ---
2197
+
2198
+ <a id="op-updateskilltestcase"></a>
2199
+
2200
+ ### `g8.api.workflows.updateSkillTestCase(input)`
2201
+
2202
+ **Update a test case**
2203
+
2204
+ - HTTP: `PUT /api/v1/skills/{action_id}/test-cases/{test_case_id}`
2205
+ - operationId: `update_skill_test_case_skills__action_id__test_cases__test_case_id__put` (also callable as `g8.api.call("update_skill_test_case_skills__action_id__test_cases__test_case_id__put", input)`)
2206
+ - Tier: `write`: creates or changes records; the SDK sends an Idempotency-Key and retries transient failures
2207
+ - API-key scope: `workflows:write`
2208
+
2209
+ PARTIAL update despite the verb - voice exposes it as a PUT.
2210
+
2211
+ Omitted fields are untouched; an explicit `null` CLEARS the field. Those
2212
+ are different instructions and only the second one is destructive.
2213
+
2214
+ **Input**
2215
+
2216
+ | Field | Type | Required | Description |
2217
+ |---|---|---|---|
2218
+ | `path.action_id` | `string` | yes | Skill or workflow `action_id`. |
2219
+ | `path.test_case_id` | `string` | yes | Test case id. |
2220
+ | `body` | `Record<string, unknown>` | yes | Request body; fields below. |
2221
+
2222
+ **Returns** `ApiResponse_VoicePayload_`: the envelope `{ data: VoicePayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
2223
+
2224
+ Other envelope fields: `pagination` (PaginationMeta).
2225
+
2226
+ **Example**
2227
+
2228
+ ```ts
2229
+ const result = await g8.api.workflows.updateSkillTestCase({ path: { action_id: "id", test_case_id: "id" }, body: {} });
2230
+ ```
2231
+
2232
+ ---
2233
+
2234
+ <a id="op-updateworkflow"></a>
2235
+
2236
+ ### `g8.api.workflows.updateWorkflow(input)`
2237
+
2238
+ **Update a workflow's graph**
2239
+
2240
+ - HTTP: `PUT /api/v1/workflows/{action_id}`
2241
+ - operationId: `update_workflow_workflows__action_id__put` (also callable as `g8.api.call("update_workflow_workflows__action_id__put", input)`)
2242
+ - 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
2243
+ - API-key scope: `workflows:run`
2244
+ - ★ Hand-written: [`g8.workflows.update()`](../sdk-clients.md#g8-workflows-update)
2245
+
2246
+ Update a workflow. The voice update endpoint takes ``org_id`` as a
2247
+ query param and the partial body in JSON, so we forward both.
2248
+
2249
+ Translates the public ``config`` field to voice's internal
2250
+ ``skill_config`` before forwarding (see module docstring).
2251
+
2252
+ **Input**
2253
+
2254
+ | Field | Type | Required | Description |
2255
+ |---|---|---|---|
2256
+ | `path.action_id` | `string` | yes | Workflow action_id. |
2257
+ | `body` | `Record<string, unknown>` | yes | Request body; fields below. |
2258
+
2259
+ **Returns** `Record<string, unknown>`.
2260
+
2261
+ **Example**
2262
+
2263
+ ```ts
2264
+ // external: reaches real people (sends email/SMS, places a call, launches a send); the SDK never blindly retries it; confirm with a human first.
2265
+ const result = await g8.api.workflows.updateWorkflow({ path: { action_id: "id" }, body: {} });
2266
+ ```
2267
+
2268
+ ---
2269
+
2270
+ <a id="op-validateworkflow"></a>
2271
+
2272
+ ### `g8.api.workflows.validateWorkflow(input)`
2273
+
2274
+ **Validate a workflow graph (structural + reference resolution)**
2275
+
2276
+ - HTTP: `POST /api/v1/workflows/validate`
2277
+ - operationId: `validate_workflow_workflows_validate_post` (also callable as `g8.api.call("validate_workflow_workflows_validate_post", input)`)
2278
+ - 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
2279
+ - API-key scope: `workflows:run`
2280
+ - ★ Hand-written: [`g8.workflows.validate()`](../sdk-clients.md#g8-workflows-validate)
2281
+
2282
+ Validate a workflow without saving. Returns errors + warnings +
2283
+ missing_references so an MCP client can repair before retrying create.
2284
+
2285
+ The inner ``config`` is normalized the same way create/update do so
2286
+ a caller can validate hybrid/ReactFlow shapes and get a clean answer
2287
+ instead of a structural error from a key the validator didn't expect.
2288
+
2289
+ **Input**
2290
+
2291
+ | Field | Type | Required | Description |
2292
+ |---|---|---|---|
2293
+ | `body` | `Record<string, unknown>` | yes | Request body; fields below. |
2294
+
2295
+ **Returns** `Record<string, unknown>`.
2296
+
2297
+ **Example**
2298
+
2299
+ ```ts
2300
+ // external: reaches real people (sends email/SMS, places a call, launches a send); the SDK never blindly retries it; confirm with a human first.
2301
+ const result = await g8.api.workflows.validateWorkflow({ body: {} });
2302
+ ```