apinow-sdk 0.15.1 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -42,9 +42,30 @@ Returns:
42
42
  | `call(endpoint, opts?)` | Call any endpoint with automatic x402 payment |
43
43
  | `search(query, limit?)` | Semantic search across all endpoints |
44
44
  | `info(ns, name)` | Get endpoint details (free) |
45
+ | `listWorkflows(opts?)` | List workflows (free) |
46
+ | `getWorkflow(id)` | Get workflow details (free) |
47
+ | `runWorkflow(id, input)` | Run a workflow with automatic x402 payment |
45
48
  | `wallet` | Your wallet address |
46
49
  | `fetch` | Raw x402-wrapped `fetch` for advanced use |
47
50
 
51
+ ### Workflows
52
+
53
+ Workflows chain multiple x402 endpoints into a single paid DAG pipeline with automatic payment splitting.
54
+
55
+ ```typescript
56
+ // list workflows
57
+ const { workflows } = await apinow.listWorkflows({ status: 'active', limit: 10 });
58
+
59
+ // get workflow details (nodes, splits, pricing)
60
+ const workflow = await apinow.getWorkflow('90931d9c8fb94df9');
61
+ console.log(workflow.name, workflow.totalPrice, workflow.graph.nodes);
62
+
63
+ // run a workflow — x402 payment covers all nodes + creator split
64
+ const result = await apinow.runWorkflow('90931d9c8fb94df9', {
65
+ query: 'birthday gift ideas for a friend who loves cooking',
66
+ });
67
+ ```
68
+
48
69
  ## CLI
49
70
 
50
71
  ```bash
@@ -87,6 +108,31 @@ npx apinow call ns/endpoint -m GET -k 0xYOUR_KEY
87
108
  | `-m, --method <method>` | HTTP method (default: from endpoint) |
88
109
  | `-k, --key <privateKey>` | Wallet key (or set `APINOW_WALLET_PKEY`) |
89
110
 
111
+ ### `workflows` — list workflows
112
+
113
+ ```bash
114
+ npx apinow workflows
115
+ npx apinow workflows --status active --limit 10
116
+ npx apinow workflows --creator 0x32e8...E934
117
+ ```
118
+
119
+ ### `workflow` — workflow details
120
+
121
+ ```bash
122
+ npx apinow workflow 90931d9c8fb94df9
123
+ ```
124
+
125
+ ### `run-workflow` — run a workflow (paid)
126
+
127
+ ```bash
128
+ APINOW_WALLET_PKEY=0x... npx apinow run-workflow 90931d9c8fb94df9 -d '{"query":"birthday gift ideas"}'
129
+ ```
130
+
131
+ | Flag | Description |
132
+ |------|-------------|
133
+ | `-d, --data <json>` | JSON input (default: `{"query":"hello world"}`) |
134
+ | `-k, --key <privateKey>` | Wallet key (or set `APINOW_WALLET_PKEY`) |
135
+
90
136
  ## Requirements
91
137
 
92
138
  - Node.js v18+
package/dist/cli.js CHANGED
@@ -6,7 +6,7 @@ const program = new Command();
6
6
  program
7
7
  .name('apinow')
8
8
  .description('CLI for APINow.fun — search, inspect, and call pay-per-request APIs')
9
- .version('0.15.0');
9
+ .version('0.16.0');
10
10
  // ─── Helpers ───
11
11
  function getPrivateKey(opts) {
12
12
  const raw = opts.key || process.env.APINOW_WALLET_PKEY || process.env.PRIVATE_KEY;
@@ -216,4 +216,100 @@ program
216
216
  process.exit(1);
217
217
  }
218
218
  });
219
+ // ─── workflows ───
220
+ program
221
+ .command('workflows')
222
+ .description('List workflows')
223
+ .option('-l, --limit <n>', 'Max results', '20')
224
+ .option('-c, --creator <address>', 'Filter by creator wallet')
225
+ .option('-s, --status <status>', 'Filter by status: active | draft | all', 'all')
226
+ .action(async (opts) => {
227
+ try {
228
+ const params = new URLSearchParams({ limit: opts.limit, status: opts.status });
229
+ if (opts.creator)
230
+ params.set('creator', opts.creator);
231
+ const data = await fetchJson(`${API_BASE}/api/workflows?${params}`);
232
+ const workflows = data.workflows || [];
233
+ if (!workflows.length) {
234
+ console.log('No workflows found.');
235
+ return;
236
+ }
237
+ const rows = [['ID', 'NAME', 'STATUS', 'NODES', 'COST', 'DESCRIPTION']];
238
+ for (const w of workflows) {
239
+ rows.push([
240
+ w.workflowId,
241
+ truncate(w.name || '', 24),
242
+ w.status,
243
+ String(w.graph?.nodes?.length || 0),
244
+ `$${w.totalPrice}`,
245
+ truncate(w.description || '', 40),
246
+ ]);
247
+ }
248
+ printTable(rows);
249
+ }
250
+ catch (err) {
251
+ console.error(`Error: ${err.message}`);
252
+ process.exit(1);
253
+ }
254
+ });
255
+ // ─── workflow info ───
256
+ program
257
+ .command('workflow <id>')
258
+ .description('Get workflow details')
259
+ .action(async (id) => {
260
+ try {
261
+ const data = await fetchJson(`${API_BASE}/api/workflows/${id}`);
262
+ console.log(`\n ${data.name}`);
263
+ console.log(` ${'─'.repeat(40)}`);
264
+ console.log(` ${data.description || '(no description)'}\n`);
265
+ console.log(` ID: ${data.workflowId}`);
266
+ console.log(` Status: ${data.status}`);
267
+ console.log(` Cost: $${data.totalPrice} USDC`);
268
+ console.log(` Chain: ${data.chain || 'base'}`);
269
+ console.log(` Creator: ${data.creatorWallet}`);
270
+ console.log(` Nodes: ${data.graph?.nodes?.length || 0}`);
271
+ if (data.graph?.nodes?.length) {
272
+ console.log(`\n Pipeline:`);
273
+ for (const node of data.graph.nodes) {
274
+ const deps = node.dependsOn?.length ? ` (depends on: ${node.dependsOn.join(', ')})` : '';
275
+ const isOutput = node.id === data.graph.outputNode ? ' [output]' : '';
276
+ console.log(` → ${node.id}: ${node.endpoint}${deps}${isOutput}`);
277
+ }
278
+ }
279
+ if (data.splits?.length) {
280
+ console.log(`\n Payment Split:`);
281
+ for (const s of data.splits) {
282
+ const pct = (s.basisPoints / 100).toFixed(1);
283
+ const usd = (parseFloat(data.totalPrice) * s.basisPoints / 10000).toFixed(4);
284
+ console.log(` ${s.label}: ${pct}% ($${usd})`);
285
+ }
286
+ }
287
+ console.log('');
288
+ }
289
+ catch (err) {
290
+ console.error(`Error: ${err.message}`);
291
+ process.exit(1);
292
+ }
293
+ });
294
+ // ─── run workflow ───
295
+ program
296
+ .command('run-workflow <id>')
297
+ .description('Run a workflow (x402 paid)')
298
+ .option('-d, --data <json>', 'JSON input', '{"query":"hello world"}')
299
+ .option('-k, --key <privateKey>', 'Wallet private key')
300
+ .action(async (id, opts) => {
301
+ try {
302
+ const privateKey = getPrivateKey(opts);
303
+ const body = JSON.parse(opts.data);
304
+ const details = await fetchJson(`${API_BASE}/api/workflows/${id}`);
305
+ console.error(`Running workflow "${details.name}" — cost: $${details.totalPrice} USDC`);
306
+ const apinow = createClient({ privateKey });
307
+ const result = await apinow.runWorkflow(id, body);
308
+ console.log(JSON.stringify(result, null, 2));
309
+ }
310
+ catch (err) {
311
+ console.error(`Error: ${err.message}`);
312
+ process.exit(1);
313
+ }
314
+ });
219
315
  program.parse();
package/dist/index.d.ts CHANGED
@@ -27,6 +27,25 @@ export declare function createClient(config: ApinowConfig): {
27
27
  * Get public endpoint info (free, no payment).
28
28
  */
29
29
  info(namespace: string, endpointName: string): Promise<any>;
30
+ /**
31
+ * List workflows. Optionally filter by creator or status.
32
+ */
33
+ listWorkflows(opts?: {
34
+ creator?: string;
35
+ status?: string;
36
+ limit?: number;
37
+ }): Promise<any>;
38
+ /**
39
+ * Get workflow details by ID.
40
+ */
41
+ getWorkflow(workflowId: string): Promise<any>;
42
+ /**
43
+ * Run a workflow. Handles x402 payment automatically.
44
+ *
45
+ * @example
46
+ * const result = await apinow.runWorkflow('90931d9c8fb94df9', { query: 'hello world' });
47
+ */
48
+ runWorkflow(workflowId: string, input: Record<string, any>): Promise<any>;
30
49
  /**
31
50
  * The underlying x402-wrapped fetch, for advanced use.
32
51
  */
package/dist/index.js CHANGED
@@ -58,6 +58,44 @@ export function createClient(config) {
58
58
  throw new Error(`Failed to fetch info: ${res.status}`);
59
59
  return res.json();
60
60
  },
61
+ // ─── Workflows ───
62
+ /**
63
+ * List workflows. Optionally filter by creator or status.
64
+ */
65
+ async listWorkflows(opts = {}) {
66
+ const params = new URLSearchParams();
67
+ if (opts.limit)
68
+ params.set('limit', String(opts.limit));
69
+ if (opts.creator)
70
+ params.set('creator', opts.creator);
71
+ if (opts.status)
72
+ params.set('status', opts.status);
73
+ const res = await fetch(`${baseUrl}/api/workflows?${params}`);
74
+ if (!res.ok)
75
+ throw new Error(`Failed to list workflows: ${res.status}`);
76
+ return res.json();
77
+ },
78
+ /**
79
+ * Get workflow details by ID.
80
+ */
81
+ async getWorkflow(workflowId) {
82
+ const res = await fetch(`${baseUrl}/api/workflows/${workflowId}`);
83
+ if (!res.ok)
84
+ throw new Error(`Failed to get workflow: ${res.status}`);
85
+ return res.json();
86
+ },
87
+ /**
88
+ * Run a workflow. Handles x402 payment automatically.
89
+ *
90
+ * @example
91
+ * const result = await apinow.runWorkflow('90931d9c8fb94df9', { query: 'hello world' });
92
+ */
93
+ async runWorkflow(workflowId, input) {
94
+ return this.call(`/api/workflows/${workflowId}/run`, {
95
+ method: 'POST',
96
+ body: input,
97
+ });
98
+ },
61
99
  /**
62
100
  * The underlying x402-wrapped fetch, for advanced use.
63
101
  */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "apinow-sdk",
3
- "version": "0.15.1",
4
- "description": "Pay-per-call API SDK & CLI for APINow.fun — wraps x402 so you don't have to",
3
+ "version": "0.16.0",
4
+ "description": "Pay-per-call API SDK & CLI for APINow.fun — endpoints + workflows, wraps x402 so you don't have to",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "type": "module",
@@ -24,7 +24,9 @@
24
24
  "web3",
25
25
  "ai",
26
26
  "llm",
27
- "cli"
27
+ "cli",
28
+ "workflow",
29
+ "dag"
28
30
  ],
29
31
  "author": "ApiNow.fun",
30
32
  "license": "MIT",