apinow-sdk 0.16.0 → 0.18.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/dist/cli.js +370 -1
- package/dist/index.d.ts +103 -0
- package/dist/index.js +173 -0
- package/package.json +3 -2
package/dist/cli.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command } from 'commander';
|
|
3
3
|
import { createClient } from './index.js';
|
|
4
|
+
import { privateKeyToAccount } from 'viem/accounts';
|
|
4
5
|
const API_BASE = 'https://apinow.fun';
|
|
5
6
|
const program = new Command();
|
|
6
7
|
program
|
|
7
8
|
.name('apinow')
|
|
8
9
|
.description('CLI for APINow.fun — search, inspect, and call pay-per-request APIs')
|
|
9
|
-
.version('0.
|
|
10
|
+
.version('0.17.0');
|
|
10
11
|
// ─── Helpers ───
|
|
11
12
|
function getPrivateKey(opts) {
|
|
12
13
|
const raw = opts.key || process.env.APINOW_WALLET_PKEY || process.env.PRIVATE_KEY;
|
|
@@ -42,6 +43,14 @@ function printTable(rows) {
|
|
|
42
43
|
function truncate(s, max) {
|
|
43
44
|
return s.length > max ? s.slice(0, max - 1) + '…' : s;
|
|
44
45
|
}
|
|
46
|
+
function getWallet(opts) {
|
|
47
|
+
const privateKey = getPrivateKey(opts);
|
|
48
|
+
const account = privateKeyToAccount(privateKey);
|
|
49
|
+
return { privateKey, address: account.address };
|
|
50
|
+
}
|
|
51
|
+
function walletHeaders(address) {
|
|
52
|
+
return { 'Content-Type': 'application/json', 'x-wallet-address': address };
|
|
53
|
+
}
|
|
45
54
|
// ─── search ───
|
|
46
55
|
program
|
|
47
56
|
.command('search <query>')
|
|
@@ -185,6 +194,92 @@ program
|
|
|
185
194
|
process.exit(1);
|
|
186
195
|
}
|
|
187
196
|
});
|
|
197
|
+
// ─── endpoint-create ───
|
|
198
|
+
program
|
|
199
|
+
.command('endpoint-create')
|
|
200
|
+
.description('Create an endpoint (raw CRUD)')
|
|
201
|
+
.requiredOption('--namespace <ns>', 'Namespace')
|
|
202
|
+
.requiredOption('--name <name>', 'Endpoint name')
|
|
203
|
+
.requiredOption('--url <url>', 'Upstream URL')
|
|
204
|
+
.requiredOption('--description <desc>', 'Description')
|
|
205
|
+
.option('--method <method>', 'HTTP method', 'POST')
|
|
206
|
+
.option('--price <usdc>', 'USDC price per call', '0.01')
|
|
207
|
+
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
208
|
+
.action(async (opts) => {
|
|
209
|
+
try {
|
|
210
|
+
const { address } = getWallet(opts);
|
|
211
|
+
const body = {
|
|
212
|
+
namespace: opts.namespace,
|
|
213
|
+
endpointName: opts.name,
|
|
214
|
+
url: opts.url,
|
|
215
|
+
description: opts.description,
|
|
216
|
+
httpMethod: opts.method.toUpperCase(),
|
|
217
|
+
paymentOptions: [{ usdAmount: opts.price, amount: opts.price }],
|
|
218
|
+
};
|
|
219
|
+
const data = await fetchJson(`${API_BASE}/api/endpoints`, {
|
|
220
|
+
method: 'POST',
|
|
221
|
+
headers: walletHeaders(address),
|
|
222
|
+
body: JSON.stringify(body),
|
|
223
|
+
});
|
|
224
|
+
console.log(JSON.stringify(data, null, 2));
|
|
225
|
+
}
|
|
226
|
+
catch (err) {
|
|
227
|
+
console.error(`Error: ${err.message}`);
|
|
228
|
+
process.exit(1);
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
// ─── endpoint-update ───
|
|
232
|
+
program
|
|
233
|
+
.command('endpoint-update <id>')
|
|
234
|
+
.description('Update an endpoint by ID')
|
|
235
|
+
.option('--description <desc>', 'New description')
|
|
236
|
+
.option('--url <url>', 'New URL')
|
|
237
|
+
.option('--price <usdc>', 'New USDC price')
|
|
238
|
+
.option('--status <status>', 'New status')
|
|
239
|
+
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
240
|
+
.action(async (id, opts) => {
|
|
241
|
+
try {
|
|
242
|
+
const { address } = getWallet(opts);
|
|
243
|
+
const body = {};
|
|
244
|
+
if (opts.description)
|
|
245
|
+
body.description = opts.description;
|
|
246
|
+
if (opts.url)
|
|
247
|
+
body.url = opts.url;
|
|
248
|
+
if (opts.status)
|
|
249
|
+
body.status = opts.status;
|
|
250
|
+
if (opts.price)
|
|
251
|
+
body.paymentOptions = [{ usdAmount: opts.price, amount: opts.price }];
|
|
252
|
+
const data = await fetchJson(`${API_BASE}/api/endpoints/${id}`, {
|
|
253
|
+
method: 'PUT',
|
|
254
|
+
headers: walletHeaders(address),
|
|
255
|
+
body: JSON.stringify(body),
|
|
256
|
+
});
|
|
257
|
+
console.log(JSON.stringify(data, null, 2));
|
|
258
|
+
}
|
|
259
|
+
catch (err) {
|
|
260
|
+
console.error(`Error: ${err.message}`);
|
|
261
|
+
process.exit(1);
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
// ─── endpoint-delete ───
|
|
265
|
+
program
|
|
266
|
+
.command('endpoint-delete <id>')
|
|
267
|
+
.description('Delete an endpoint by ID')
|
|
268
|
+
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
269
|
+
.action(async (id, opts) => {
|
|
270
|
+
try {
|
|
271
|
+
const { address } = getWallet(opts);
|
|
272
|
+
const data = await fetchJson(`${API_BASE}/api/endpoints/${id}`, {
|
|
273
|
+
method: 'DELETE',
|
|
274
|
+
headers: walletHeaders(address),
|
|
275
|
+
});
|
|
276
|
+
console.log(JSON.stringify(data, null, 2));
|
|
277
|
+
}
|
|
278
|
+
catch (err) {
|
|
279
|
+
console.error(`Error: ${err.message}`);
|
|
280
|
+
process.exit(1);
|
|
281
|
+
}
|
|
282
|
+
});
|
|
188
283
|
// ─── call ───
|
|
189
284
|
program
|
|
190
285
|
.command('call <endpoint>')
|
|
@@ -312,4 +407,278 @@ program
|
|
|
312
407
|
process.exit(1);
|
|
313
408
|
}
|
|
314
409
|
});
|
|
410
|
+
// ─── workflow-create ───
|
|
411
|
+
program
|
|
412
|
+
.command('workflow-create')
|
|
413
|
+
.description('Create a workflow (raw CRUD)')
|
|
414
|
+
.requiredOption('--name <name>', 'Workflow name')
|
|
415
|
+
.option('--description <desc>', 'Description')
|
|
416
|
+
.option('--graph <json>', 'Graph JSON (nodes + outputNode)')
|
|
417
|
+
.option('--prompt <prompt>', 'AI prompt to generate workflow')
|
|
418
|
+
.option('--price <usdc>', 'Total price', '0.10')
|
|
419
|
+
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
420
|
+
.action(async (opts) => {
|
|
421
|
+
try {
|
|
422
|
+
const { address } = getWallet(opts);
|
|
423
|
+
const body = { name: opts.name, totalPrice: opts.price };
|
|
424
|
+
if (opts.description)
|
|
425
|
+
body.description = opts.description;
|
|
426
|
+
if (opts.graph)
|
|
427
|
+
body.graph = JSON.parse(opts.graph);
|
|
428
|
+
if (opts.prompt)
|
|
429
|
+
body.prompt = opts.prompt;
|
|
430
|
+
const data = await fetchJson(`${API_BASE}/api/workflows`, {
|
|
431
|
+
method: 'POST',
|
|
432
|
+
headers: walletHeaders(address),
|
|
433
|
+
body: JSON.stringify(body),
|
|
434
|
+
});
|
|
435
|
+
console.log(JSON.stringify(data, null, 2));
|
|
436
|
+
}
|
|
437
|
+
catch (err) {
|
|
438
|
+
console.error(`Error: ${err.message}`);
|
|
439
|
+
process.exit(1);
|
|
440
|
+
}
|
|
441
|
+
});
|
|
442
|
+
// ─── workflow-update ───
|
|
443
|
+
program
|
|
444
|
+
.command('workflow-update <id>')
|
|
445
|
+
.description('Update a workflow by ID')
|
|
446
|
+
.option('--name <name>', 'New name')
|
|
447
|
+
.option('--description <desc>', 'New description')
|
|
448
|
+
.option('--status <status>', 'New status')
|
|
449
|
+
.option('--price <usdc>', 'New total price')
|
|
450
|
+
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
451
|
+
.action(async (id, opts) => {
|
|
452
|
+
try {
|
|
453
|
+
const { address } = getWallet(opts);
|
|
454
|
+
const body = {};
|
|
455
|
+
if (opts.name)
|
|
456
|
+
body.name = opts.name;
|
|
457
|
+
if (opts.description)
|
|
458
|
+
body.description = opts.description;
|
|
459
|
+
if (opts.status)
|
|
460
|
+
body.status = opts.status;
|
|
461
|
+
if (opts.price)
|
|
462
|
+
body.totalPrice = opts.price;
|
|
463
|
+
const data = await fetchJson(`${API_BASE}/api/workflows/${id}`, {
|
|
464
|
+
method: 'PUT',
|
|
465
|
+
headers: walletHeaders(address),
|
|
466
|
+
body: JSON.stringify(body),
|
|
467
|
+
});
|
|
468
|
+
console.log(JSON.stringify(data, null, 2));
|
|
469
|
+
}
|
|
470
|
+
catch (err) {
|
|
471
|
+
console.error(`Error: ${err.message}`);
|
|
472
|
+
process.exit(1);
|
|
473
|
+
}
|
|
474
|
+
});
|
|
475
|
+
// ─── workflow-delete ───
|
|
476
|
+
program
|
|
477
|
+
.command('workflow-delete <id>')
|
|
478
|
+
.description('Delete a workflow by ID')
|
|
479
|
+
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
480
|
+
.action(async (id, opts) => {
|
|
481
|
+
try {
|
|
482
|
+
const { address } = getWallet(opts);
|
|
483
|
+
const data = await fetchJson(`${API_BASE}/api/workflows/${id}`, {
|
|
484
|
+
method: 'DELETE',
|
|
485
|
+
headers: walletHeaders(address),
|
|
486
|
+
});
|
|
487
|
+
console.log(JSON.stringify(data, null, 2));
|
|
488
|
+
}
|
|
489
|
+
catch (err) {
|
|
490
|
+
console.error(`Error: ${err.message}`);
|
|
491
|
+
process.exit(1);
|
|
492
|
+
}
|
|
493
|
+
});
|
|
494
|
+
// ─── factory-balance ───
|
|
495
|
+
program
|
|
496
|
+
.command('factory-balance')
|
|
497
|
+
.description('Check $APINOW token balance and factory access')
|
|
498
|
+
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
499
|
+
.action(async (opts) => {
|
|
500
|
+
try {
|
|
501
|
+
const { address } = getWallet(opts);
|
|
502
|
+
const data = await fetchJson(`${API_BASE}/api/user-factory/check-balance`, {
|
|
503
|
+
headers: walletHeaders(address),
|
|
504
|
+
});
|
|
505
|
+
console.log(`\n Wallet: ${address}`);
|
|
506
|
+
console.log(` Balance: ${data.balance} $APINOW`);
|
|
507
|
+
console.log(` Required: ${data.required}`);
|
|
508
|
+
console.log(` Access: ${data.hasAccess ? 'YES' : 'NO'}\n`);
|
|
509
|
+
}
|
|
510
|
+
catch (err) {
|
|
511
|
+
console.error(`Error: ${err.message}`);
|
|
512
|
+
process.exit(1);
|
|
513
|
+
}
|
|
514
|
+
});
|
|
515
|
+
// ─── factory-list ───
|
|
516
|
+
program
|
|
517
|
+
.command('factory-list')
|
|
518
|
+
.description('List your user-factory endpoints')
|
|
519
|
+
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
520
|
+
.action(async (opts) => {
|
|
521
|
+
try {
|
|
522
|
+
const { address } = getWallet(opts);
|
|
523
|
+
const data = await fetchJson(`${API_BASE}/api/user-factory`, {
|
|
524
|
+
headers: walletHeaders(address),
|
|
525
|
+
});
|
|
526
|
+
const endpoints = data.endpoints || [];
|
|
527
|
+
if (!endpoints.length) {
|
|
528
|
+
console.log('No factory endpoints found.');
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
const rows = [['ENDPOINT', 'MODEL', 'COST', 'STATUS']];
|
|
532
|
+
for (const ep of endpoints) {
|
|
533
|
+
rows.push([
|
|
534
|
+
`${ep.namespace}/${ep.endpointName}`,
|
|
535
|
+
ep.model || '—',
|
|
536
|
+
formatUsd(ep.paymentOptions),
|
|
537
|
+
ep.status || '—',
|
|
538
|
+
]);
|
|
539
|
+
}
|
|
540
|
+
printTable(rows);
|
|
541
|
+
}
|
|
542
|
+
catch (err) {
|
|
543
|
+
console.error(`Error: ${err.message}`);
|
|
544
|
+
process.exit(1);
|
|
545
|
+
}
|
|
546
|
+
});
|
|
547
|
+
// ─── factory-generate ───
|
|
548
|
+
program
|
|
549
|
+
.command('factory-generate <idea>')
|
|
550
|
+
.description('Generate endpoint config from a natural-language idea')
|
|
551
|
+
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
552
|
+
.action(async (idea, opts) => {
|
|
553
|
+
try {
|
|
554
|
+
const { address } = getWallet(opts);
|
|
555
|
+
console.error('Generating endpoint config…');
|
|
556
|
+
const data = await fetchJson(`${API_BASE}/api/user-factory/generate`, {
|
|
557
|
+
method: 'POST',
|
|
558
|
+
headers: walletHeaders(address),
|
|
559
|
+
body: JSON.stringify({ idea }),
|
|
560
|
+
});
|
|
561
|
+
console.log(JSON.stringify(data, null, 2));
|
|
562
|
+
}
|
|
563
|
+
catch (err) {
|
|
564
|
+
console.error(`Error: ${err.message}`);
|
|
565
|
+
process.exit(1);
|
|
566
|
+
}
|
|
567
|
+
});
|
|
568
|
+
// ─── factory-create ───
|
|
569
|
+
program
|
|
570
|
+
.command('factory-create')
|
|
571
|
+
.description('Create an LLM endpoint via user-factory')
|
|
572
|
+
.requiredOption('--name <name>', 'Endpoint name')
|
|
573
|
+
.requiredOption('--prompt <prompt>', 'System prompt for the LLM')
|
|
574
|
+
.option('--namespace <ns>', 'Namespace (defaults to u-<wallet>)')
|
|
575
|
+
.option('--description <desc>', 'Endpoint description')
|
|
576
|
+
.option('--model <model>', 'LLM model', 'google/gemini-2.0-flash-001')
|
|
577
|
+
.option('--price <usdc>', 'USDC price per call', '0.01')
|
|
578
|
+
.option('--recipient <wallet>', 'Payment recipient wallet')
|
|
579
|
+
.option('--input-params <json>', 'Input params JSON array')
|
|
580
|
+
.option('--output-params <json>', 'Output params JSON array')
|
|
581
|
+
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
582
|
+
.action(async (opts) => {
|
|
583
|
+
try {
|
|
584
|
+
const { address } = getWallet(opts);
|
|
585
|
+
const body = {
|
|
586
|
+
name: opts.name,
|
|
587
|
+
prompt: opts.prompt,
|
|
588
|
+
model: opts.model,
|
|
589
|
+
usdcPrice: opts.price,
|
|
590
|
+
};
|
|
591
|
+
if (opts.namespace)
|
|
592
|
+
body.namespace = opts.namespace;
|
|
593
|
+
if (opts.description)
|
|
594
|
+
body.description = opts.description;
|
|
595
|
+
if (opts.recipient)
|
|
596
|
+
body.recipientWallet = opts.recipient;
|
|
597
|
+
if (opts.inputParams)
|
|
598
|
+
body.inputParams = JSON.parse(opts.inputParams);
|
|
599
|
+
if (opts.outputParams)
|
|
600
|
+
body.outputParams = JSON.parse(opts.outputParams);
|
|
601
|
+
console.error(`Creating endpoint "${opts.name}"…`);
|
|
602
|
+
const data = await fetchJson(`${API_BASE}/api/user-factory`, {
|
|
603
|
+
method: 'POST',
|
|
604
|
+
headers: walletHeaders(address),
|
|
605
|
+
body: JSON.stringify(body),
|
|
606
|
+
});
|
|
607
|
+
const ep = data.endpoint;
|
|
608
|
+
console.log(`\n Created: ${ep.namespace}/${ep.endpointName}`);
|
|
609
|
+
console.log(` Model: ${ep.model}`);
|
|
610
|
+
console.log(` Price: $${ep.price} USDC`);
|
|
611
|
+
console.log(` Try: https://apinow.fun${ep.tryUrl}`);
|
|
612
|
+
console.log(` API: https://apinow.fun${ep.apiUrl}\n`);
|
|
613
|
+
}
|
|
614
|
+
catch (err) {
|
|
615
|
+
console.error(`Error: ${err.message}`);
|
|
616
|
+
process.exit(1);
|
|
617
|
+
}
|
|
618
|
+
});
|
|
619
|
+
// ─── factory-markup ───
|
|
620
|
+
program
|
|
621
|
+
.command('factory-markup <endpointId>')
|
|
622
|
+
.description('Create a markup workflow that wraps an existing endpoint')
|
|
623
|
+
.option('--markup <percent>', 'Markup percentage', '20')
|
|
624
|
+
.option('--name <name>', 'Workflow name')
|
|
625
|
+
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
626
|
+
.action(async (endpointId, opts) => {
|
|
627
|
+
try {
|
|
628
|
+
const { address } = getWallet(opts);
|
|
629
|
+
const body = { endpointId, markupPercent: Number(opts.markup) };
|
|
630
|
+
if (opts.name)
|
|
631
|
+
body.workflowName = opts.name;
|
|
632
|
+
console.error(`Creating markup workflow (${opts.markup}%)…`);
|
|
633
|
+
const data = await fetchJson(`${API_BASE}/api/user-factory/markup`, {
|
|
634
|
+
method: 'POST',
|
|
635
|
+
headers: walletHeaders(address),
|
|
636
|
+
body: JSON.stringify(body),
|
|
637
|
+
});
|
|
638
|
+
const w = data.workflow;
|
|
639
|
+
console.log(`\n Created: ${w.name}`);
|
|
640
|
+
console.log(` ID: ${w.workflowId}`);
|
|
641
|
+
console.log(` Base: $${w.basePrice} USDC`);
|
|
642
|
+
console.log(` Markup: ${w.markupPercent}%`);
|
|
643
|
+
console.log(` Total: $${w.totalPrice} USDC`);
|
|
644
|
+
console.log(` View: https://apinow.fun${w.viewUrl}\n`);
|
|
645
|
+
}
|
|
646
|
+
catch (err) {
|
|
647
|
+
console.error(`Error: ${err.message}`);
|
|
648
|
+
process.exit(1);
|
|
649
|
+
}
|
|
650
|
+
});
|
|
651
|
+
// ─── factory-test ───
|
|
652
|
+
program
|
|
653
|
+
.command('factory-test <endpoint>')
|
|
654
|
+
.description('Test-call an endpoint without payment')
|
|
655
|
+
.option('-d, --data <json>', 'JSON input')
|
|
656
|
+
.option('--save', 'Save as example')
|
|
657
|
+
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
658
|
+
.action(async (endpoint, opts) => {
|
|
659
|
+
try {
|
|
660
|
+
if (!endpoint.includes('/'))
|
|
661
|
+
throw new Error('Format: namespace/endpoint-name');
|
|
662
|
+
const { address } = getWallet(opts);
|
|
663
|
+
const [namespace, endpointName] = endpoint.split('/');
|
|
664
|
+
const body = { namespace, endpointName };
|
|
665
|
+
if (opts.data)
|
|
666
|
+
body.input = JSON.parse(opts.data);
|
|
667
|
+
if (opts.save)
|
|
668
|
+
body.saveExample = true;
|
|
669
|
+
console.error(`Testing ${endpoint}…`);
|
|
670
|
+
const data = await fetchJson(`${API_BASE}/api/user-factory/test-call`, {
|
|
671
|
+
method: 'POST',
|
|
672
|
+
headers: walletHeaders(address),
|
|
673
|
+
body: JSON.stringify(body),
|
|
674
|
+
});
|
|
675
|
+
console.log(JSON.stringify(data.output, null, 2));
|
|
676
|
+
if (data.saved)
|
|
677
|
+
console.error('(saved as example)');
|
|
678
|
+
}
|
|
679
|
+
catch (err) {
|
|
680
|
+
console.error(`Error: ${err.message}`);
|
|
681
|
+
process.exit(1);
|
|
682
|
+
}
|
|
683
|
+
});
|
|
315
684
|
program.parse();
|
package/dist/index.d.ts
CHANGED
|
@@ -27,6 +27,34 @@ 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
|
+
createEndpoint(config: {
|
|
31
|
+
namespace: string;
|
|
32
|
+
endpointName: string;
|
|
33
|
+
url: string;
|
|
34
|
+
description: string;
|
|
35
|
+
httpMethod: "GET" | "POST";
|
|
36
|
+
paymentOptions: Array<{
|
|
37
|
+
amount?: string;
|
|
38
|
+
usdAmount?: string;
|
|
39
|
+
tokenAddress?: string;
|
|
40
|
+
tokenSymbol?: string;
|
|
41
|
+
}>;
|
|
42
|
+
chain?: string;
|
|
43
|
+
querySchema?: any;
|
|
44
|
+
responseSchema?: any;
|
|
45
|
+
exampleQuery?: any;
|
|
46
|
+
exampleOutput?: any;
|
|
47
|
+
docsUrl?: string;
|
|
48
|
+
}): Promise<any>;
|
|
49
|
+
getEndpoint(id: string): Promise<any>;
|
|
50
|
+
updateEndpoint(id: string, updates: Record<string, any>): Promise<any>;
|
|
51
|
+
deleteEndpoint(id: string): Promise<any>;
|
|
52
|
+
listEndpoints(opts?: {
|
|
53
|
+
limit?: number;
|
|
54
|
+
sortBy?: string;
|
|
55
|
+
namespace?: string;
|
|
56
|
+
search?: string;
|
|
57
|
+
}): Promise<any>;
|
|
30
58
|
/**
|
|
31
59
|
* List workflows. Optionally filter by creator or status.
|
|
32
60
|
*/
|
|
@@ -39,6 +67,30 @@ export declare function createClient(config: ApinowConfig): {
|
|
|
39
67
|
* Get workflow details by ID.
|
|
40
68
|
*/
|
|
41
69
|
getWorkflow(workflowId: string): Promise<any>;
|
|
70
|
+
createWorkflow(config: {
|
|
71
|
+
name?: string;
|
|
72
|
+
description?: string;
|
|
73
|
+
graph?: {
|
|
74
|
+
nodes: Array<{
|
|
75
|
+
id: string;
|
|
76
|
+
endpoint: string;
|
|
77
|
+
inputMapping: any;
|
|
78
|
+
dependsOn: string[];
|
|
79
|
+
}>;
|
|
80
|
+
outputNode: string;
|
|
81
|
+
outputMapping?: any;
|
|
82
|
+
};
|
|
83
|
+
prompt?: string;
|
|
84
|
+
totalPrice?: string;
|
|
85
|
+
splits?: Array<{
|
|
86
|
+
address: string;
|
|
87
|
+
basisPoints: number;
|
|
88
|
+
label?: string;
|
|
89
|
+
}>;
|
|
90
|
+
chain?: string;
|
|
91
|
+
}): Promise<any>;
|
|
92
|
+
updateWorkflow(workflowId: string, updates: Record<string, any>): Promise<any>;
|
|
93
|
+
deleteWorkflow(workflowId: string): Promise<any>;
|
|
42
94
|
/**
|
|
43
95
|
* Run a workflow. Handles x402 payment automatically.
|
|
44
96
|
*
|
|
@@ -46,6 +98,57 @@ export declare function createClient(config: ApinowConfig): {
|
|
|
46
98
|
* const result = await apinow.runWorkflow('90931d9c8fb94df9', { query: 'hello world' });
|
|
47
99
|
*/
|
|
48
100
|
runWorkflow(workflowId: string, input: Record<string, any>): Promise<any>;
|
|
101
|
+
/**
|
|
102
|
+
* Check $APINOW token balance and factory access.
|
|
103
|
+
*/
|
|
104
|
+
factoryBalance(): Promise<any>;
|
|
105
|
+
/**
|
|
106
|
+
* List your user-factory endpoints.
|
|
107
|
+
*/
|
|
108
|
+
factoryList(): Promise<any>;
|
|
109
|
+
/**
|
|
110
|
+
* Generate endpoint config from a natural-language idea.
|
|
111
|
+
*/
|
|
112
|
+
factoryGenerate(idea: string): Promise<any>;
|
|
113
|
+
/**
|
|
114
|
+
* Create an LLM endpoint via user-factory.
|
|
115
|
+
*/
|
|
116
|
+
factoryCreate(config: {
|
|
117
|
+
name: string;
|
|
118
|
+
prompt: string;
|
|
119
|
+
namespace?: string;
|
|
120
|
+
description?: string;
|
|
121
|
+
model?: string;
|
|
122
|
+
usdcPrice?: string;
|
|
123
|
+
recipientWallet?: string;
|
|
124
|
+
inputParams?: Array<{
|
|
125
|
+
name: string;
|
|
126
|
+
type: string;
|
|
127
|
+
description?: string;
|
|
128
|
+
}>;
|
|
129
|
+
outputParams?: Array<{
|
|
130
|
+
name: string;
|
|
131
|
+
type: string;
|
|
132
|
+
description?: string;
|
|
133
|
+
}>;
|
|
134
|
+
}): Promise<any>;
|
|
135
|
+
/**
|
|
136
|
+
* Create a markup workflow wrapping an existing endpoint.
|
|
137
|
+
*/
|
|
138
|
+
factoryMarkup(opts: {
|
|
139
|
+
endpointId: string;
|
|
140
|
+
markupPercent?: number;
|
|
141
|
+
workflowName?: string;
|
|
142
|
+
}): Promise<any>;
|
|
143
|
+
/**
|
|
144
|
+
* Test-call an endpoint without payment (free, server-side LLM call).
|
|
145
|
+
*/
|
|
146
|
+
factoryTestCall(opts: {
|
|
147
|
+
namespace: string;
|
|
148
|
+
endpointName: string;
|
|
149
|
+
input?: any;
|
|
150
|
+
saveExample?: boolean;
|
|
151
|
+
}): Promise<any>;
|
|
49
152
|
/**
|
|
50
153
|
* The underlying x402-wrapped fetch, for advanced use.
|
|
51
154
|
*/
|
package/dist/index.js
CHANGED
|
@@ -58,6 +58,63 @@ export function createClient(config) {
|
|
|
58
58
|
throw new Error(`Failed to fetch info: ${res.status}`);
|
|
59
59
|
return res.json();
|
|
60
60
|
},
|
|
61
|
+
// ─── Endpoint CRUD ───
|
|
62
|
+
async createEndpoint(config) {
|
|
63
|
+
const res = await fetch(`${baseUrl}/api/endpoints`, {
|
|
64
|
+
method: 'POST',
|
|
65
|
+
headers: { 'Content-Type': 'application/json', 'x-wallet-address': account.address },
|
|
66
|
+
body: JSON.stringify(config),
|
|
67
|
+
});
|
|
68
|
+
if (!res.ok) {
|
|
69
|
+
const text = await res.text();
|
|
70
|
+
throw new Error(`Failed to create endpoint: ${res.status} ${text}`);
|
|
71
|
+
}
|
|
72
|
+
return res.json();
|
|
73
|
+
},
|
|
74
|
+
async getEndpoint(id) {
|
|
75
|
+
const res = await fetch(`${baseUrl}/api/endpoints/${id}`);
|
|
76
|
+
if (!res.ok)
|
|
77
|
+
throw new Error(`Failed to get endpoint: ${res.status}`);
|
|
78
|
+
return res.json();
|
|
79
|
+
},
|
|
80
|
+
async updateEndpoint(id, updates) {
|
|
81
|
+
const res = await fetch(`${baseUrl}/api/endpoints/${id}`, {
|
|
82
|
+
method: 'PUT',
|
|
83
|
+
headers: { 'Content-Type': 'application/json', 'x-wallet-address': account.address },
|
|
84
|
+
body: JSON.stringify(updates),
|
|
85
|
+
});
|
|
86
|
+
if (!res.ok) {
|
|
87
|
+
const text = await res.text();
|
|
88
|
+
throw new Error(`Failed to update endpoint: ${res.status} ${text}`);
|
|
89
|
+
}
|
|
90
|
+
return res.json();
|
|
91
|
+
},
|
|
92
|
+
async deleteEndpoint(id) {
|
|
93
|
+
const res = await fetch(`${baseUrl}/api/endpoints/${id}`, {
|
|
94
|
+
method: 'DELETE',
|
|
95
|
+
headers: { 'x-wallet-address': account.address },
|
|
96
|
+
});
|
|
97
|
+
if (!res.ok) {
|
|
98
|
+
const text = await res.text();
|
|
99
|
+
throw new Error(`Failed to delete endpoint: ${res.status} ${text}`);
|
|
100
|
+
}
|
|
101
|
+
return res.json();
|
|
102
|
+
},
|
|
103
|
+
async listEndpoints(opts = {}) {
|
|
104
|
+
const params = new URLSearchParams();
|
|
105
|
+
if (opts.limit)
|
|
106
|
+
params.set('limit', String(opts.limit));
|
|
107
|
+
if (opts.sortBy)
|
|
108
|
+
params.set('sortBy', opts.sortBy);
|
|
109
|
+
if (opts.namespace)
|
|
110
|
+
params.set('namespace', opts.namespace);
|
|
111
|
+
if (opts.search)
|
|
112
|
+
params.set('search', opts.search);
|
|
113
|
+
const res = await fetch(`${baseUrl}/api/endpoints?${params}`);
|
|
114
|
+
if (!res.ok)
|
|
115
|
+
throw new Error(`Failed to list endpoints: ${res.status}`);
|
|
116
|
+
return res.json();
|
|
117
|
+
},
|
|
61
118
|
// ─── Workflows ───
|
|
62
119
|
/**
|
|
63
120
|
* List workflows. Optionally filter by creator or status.
|
|
@@ -84,6 +141,41 @@ export function createClient(config) {
|
|
|
84
141
|
throw new Error(`Failed to get workflow: ${res.status}`);
|
|
85
142
|
return res.json();
|
|
86
143
|
},
|
|
144
|
+
async createWorkflow(config) {
|
|
145
|
+
const res = await fetch(`${baseUrl}/api/workflows`, {
|
|
146
|
+
method: 'POST',
|
|
147
|
+
headers: { 'Content-Type': 'application/json', 'x-wallet-address': account.address },
|
|
148
|
+
body: JSON.stringify(config),
|
|
149
|
+
});
|
|
150
|
+
if (!res.ok) {
|
|
151
|
+
const text = await res.text();
|
|
152
|
+
throw new Error(`Failed to create workflow: ${res.status} ${text}`);
|
|
153
|
+
}
|
|
154
|
+
return res.json();
|
|
155
|
+
},
|
|
156
|
+
async updateWorkflow(workflowId, updates) {
|
|
157
|
+
const res = await fetch(`${baseUrl}/api/workflows/${workflowId}`, {
|
|
158
|
+
method: 'PUT',
|
|
159
|
+
headers: { 'Content-Type': 'application/json', 'x-wallet-address': account.address },
|
|
160
|
+
body: JSON.stringify(updates),
|
|
161
|
+
});
|
|
162
|
+
if (!res.ok) {
|
|
163
|
+
const text = await res.text();
|
|
164
|
+
throw new Error(`Failed to update workflow: ${res.status} ${text}`);
|
|
165
|
+
}
|
|
166
|
+
return res.json();
|
|
167
|
+
},
|
|
168
|
+
async deleteWorkflow(workflowId) {
|
|
169
|
+
const res = await fetch(`${baseUrl}/api/workflows/${workflowId}`, {
|
|
170
|
+
method: 'DELETE',
|
|
171
|
+
headers: { 'x-wallet-address': account.address },
|
|
172
|
+
});
|
|
173
|
+
if (!res.ok) {
|
|
174
|
+
const text = await res.text();
|
|
175
|
+
throw new Error(`Failed to delete workflow: ${res.status} ${text}`);
|
|
176
|
+
}
|
|
177
|
+
return res.json();
|
|
178
|
+
},
|
|
87
179
|
/**
|
|
88
180
|
* Run a workflow. Handles x402 payment automatically.
|
|
89
181
|
*
|
|
@@ -96,6 +188,87 @@ export function createClient(config) {
|
|
|
96
188
|
body: input,
|
|
97
189
|
});
|
|
98
190
|
},
|
|
191
|
+
// ─── User Factory ───
|
|
192
|
+
/**
|
|
193
|
+
* Check $APINOW token balance and factory access.
|
|
194
|
+
*/
|
|
195
|
+
async factoryBalance() {
|
|
196
|
+
const res = await fetch(`${baseUrl}/api/user-factory/check-balance`, {
|
|
197
|
+
headers: { 'x-wallet-address': account.address },
|
|
198
|
+
});
|
|
199
|
+
if (!res.ok)
|
|
200
|
+
throw new Error(`Failed to check balance: ${res.status}`);
|
|
201
|
+
return res.json();
|
|
202
|
+
},
|
|
203
|
+
/**
|
|
204
|
+
* List your user-factory endpoints.
|
|
205
|
+
*/
|
|
206
|
+
async factoryList() {
|
|
207
|
+
const res = await fetch(`${baseUrl}/api/user-factory`, {
|
|
208
|
+
headers: { 'x-wallet-address': account.address },
|
|
209
|
+
});
|
|
210
|
+
if (!res.ok)
|
|
211
|
+
throw new Error(`Failed to list factory endpoints: ${res.status}`);
|
|
212
|
+
return res.json();
|
|
213
|
+
},
|
|
214
|
+
/**
|
|
215
|
+
* Generate endpoint config from a natural-language idea.
|
|
216
|
+
*/
|
|
217
|
+
async factoryGenerate(idea) {
|
|
218
|
+
const res = await fetch(`${baseUrl}/api/user-factory/generate`, {
|
|
219
|
+
method: 'POST',
|
|
220
|
+
headers: { 'Content-Type': 'application/json', 'x-wallet-address': account.address },
|
|
221
|
+
body: JSON.stringify({ idea }),
|
|
222
|
+
});
|
|
223
|
+
if (!res.ok)
|
|
224
|
+
throw new Error(`Failed to generate: ${res.status}`);
|
|
225
|
+
return res.json();
|
|
226
|
+
},
|
|
227
|
+
/**
|
|
228
|
+
* Create an LLM endpoint via user-factory.
|
|
229
|
+
*/
|
|
230
|
+
async factoryCreate(config) {
|
|
231
|
+
const res = await fetch(`${baseUrl}/api/user-factory`, {
|
|
232
|
+
method: 'POST',
|
|
233
|
+
headers: { 'Content-Type': 'application/json', 'x-wallet-address': account.address },
|
|
234
|
+
body: JSON.stringify(config),
|
|
235
|
+
});
|
|
236
|
+
if (!res.ok) {
|
|
237
|
+
const text = await res.text();
|
|
238
|
+
throw new Error(`Failed to create endpoint: ${res.status} ${text}`);
|
|
239
|
+
}
|
|
240
|
+
return res.json();
|
|
241
|
+
},
|
|
242
|
+
/**
|
|
243
|
+
* Create a markup workflow wrapping an existing endpoint.
|
|
244
|
+
*/
|
|
245
|
+
async factoryMarkup(opts) {
|
|
246
|
+
const res = await fetch(`${baseUrl}/api/user-factory/markup`, {
|
|
247
|
+
method: 'POST',
|
|
248
|
+
headers: { 'Content-Type': 'application/json', 'x-wallet-address': account.address },
|
|
249
|
+
body: JSON.stringify(opts),
|
|
250
|
+
});
|
|
251
|
+
if (!res.ok) {
|
|
252
|
+
const text = await res.text();
|
|
253
|
+
throw new Error(`Failed to create markup: ${res.status} ${text}`);
|
|
254
|
+
}
|
|
255
|
+
return res.json();
|
|
256
|
+
},
|
|
257
|
+
/**
|
|
258
|
+
* Test-call an endpoint without payment (free, server-side LLM call).
|
|
259
|
+
*/
|
|
260
|
+
async factoryTestCall(opts) {
|
|
261
|
+
const res = await fetch(`${baseUrl}/api/user-factory/test-call`, {
|
|
262
|
+
method: 'POST',
|
|
263
|
+
headers: { 'Content-Type': 'application/json', 'x-wallet-address': account.address },
|
|
264
|
+
body: JSON.stringify(opts),
|
|
265
|
+
});
|
|
266
|
+
if (!res.ok) {
|
|
267
|
+
const text = await res.text();
|
|
268
|
+
throw new Error(`Failed to test call: ${res.status} ${text}`);
|
|
269
|
+
}
|
|
270
|
+
return res.json();
|
|
271
|
+
},
|
|
99
272
|
/**
|
|
100
273
|
* The underlying x402-wrapped fetch, for advanced use.
|
|
101
274
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "apinow-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
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",
|
|
@@ -26,7 +26,8 @@
|
|
|
26
26
|
"llm",
|
|
27
27
|
"cli",
|
|
28
28
|
"workflow",
|
|
29
|
-
"dag"
|
|
29
|
+
"dag",
|
|
30
|
+
"user-factory"
|
|
30
31
|
],
|
|
31
32
|
"author": "ApiNow.fun",
|
|
32
33
|
"license": "MIT",
|