@myapihq/cli 1.0.61 → 1.0.65
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/commands/auth.js +13 -5
- package/dist/commands/config.d.ts +4 -4
- package/dist/commands/config.js +13 -13
- package/dist/commands/domain.d.ts +0 -1
- package/dist/commands/domain.js +10 -24
- package/dist/commands/funnel.js +7 -3
- package/dist/commands/keys.js +2 -2
- package/dist/commands/org.js +8 -4
- package/dist/commands/update.js +1 -1
- package/dist/index.js +6 -6
- package/dist/skills/my-api-hq/README.md +37 -0
- package/dist/skills/my-api-hq/SKILL.md +116 -0
- package/dist/skills/my-api-hq/claude/.claude-plugin/plugin.json +6 -0
- package/dist/skills/my-api-hq/make/.gitkeep +0 -0
- package/dist/skills/my-api-hq/n8n/.gitkeep +0 -0
- package/dist/skills/my-api-hq/openapi/.gitkeep +0 -0
- package/dist/skills/my-domain-api/README.md +37 -0
- package/dist/skills/my-domain-api/SKILL.md +83 -0
- package/dist/skills/my-domain-api/claude/.claude-plugin/plugin.json +6 -0
- package/dist/skills/my-domain-api/make/.gitkeep +0 -0
- package/dist/skills/my-domain-api/n8n/.gitkeep +0 -0
- package/dist/skills/my-domain-api/openapi/.gitkeep +0 -0
- package/dist/skills/my-funnel-api/README.md +39 -0
- package/dist/skills/my-funnel-api/SKILL.md +35 -0
- package/dist/skills/my-funnel-api/claude/.claude-plugin/plugin.json +6 -0
- package/dist/skills/my-funnel-api/make/.gitkeep +0 -0
- package/dist/skills/my-funnel-api/n8n/.gitkeep +0 -0
- package/dist/skills/my-funnel-api/openapi/.gitkeep +0 -0
- package/package.json +4 -1
- package/scripts/copy-skills.js +0 -13
- package/src/commands/auth.ts +0 -190
- package/src/commands/billing.ts +0 -92
- package/src/commands/config.ts +0 -71
- package/src/commands/domain.ts +0 -146
- package/src/commands/email.ts +0 -185
- package/src/commands/funnel.ts +0 -122
- package/src/commands/image.ts +0 -85
- package/src/commands/keys.ts +0 -68
- package/src/commands/org.ts +0 -134
- package/src/commands/pixel.ts +0 -62
- package/src/commands/setup.ts +0 -335
- package/src/commands/storage.ts +0 -56
- package/src/commands/update.ts +0 -89
- package/src/commands/url.ts +0 -28
- package/src/commands/webhook.ts +0 -66
- package/src/commands/workflow.ts +0 -102
- package/src/config.ts +0 -123
- package/src/index.ts +0 -200
- package/src/output.ts +0 -49
- package/src/utils.ts +0 -45
- package/thank-you.html +0 -56
- package/tsconfig.json +0 -15
package/dist/commands/auth.js
CHANGED
|
@@ -41,7 +41,7 @@ async function patch(path, body, apiKey) {
|
|
|
41
41
|
// myapi auth link — upgrade anonymous session to registered account.
|
|
42
42
|
export async function link(flags = {}, emailArg) {
|
|
43
43
|
if (flags.help) {
|
|
44
|
-
info('Usage: myapi auth link [email]\n\
|
|
44
|
+
info('Usage: myapi auth link [email]\n\nUpgrades your anonymous account by attaching a verified email address.\nA one-time code will be sent to your inbox — paste it at the prompt to confirm.\nThis is an interactive command; it will ask for the code before completing.\n\nIf that email already belongs to an existing MyAPI account, your anonymous\naccount is NOT merged. Instead, the existing account is added as a second\nactive session and you can switch between them with: myapi auth switch\n\nTo create a completely new account from scratch, use: myapi auth setup');
|
|
45
45
|
return;
|
|
46
46
|
}
|
|
47
47
|
const config = loadConfig();
|
|
@@ -144,7 +144,7 @@ export async function whoami(flags = {}) {
|
|
|
144
144
|
// myapi auth switch [index] — switch between saved accounts.
|
|
145
145
|
export async function switchCmd(flags = {}, indexArg) {
|
|
146
146
|
if (flags.help) {
|
|
147
|
-
info('Usage: myapi auth switch [index]\n\nSwitches the active account.
|
|
147
|
+
info('Usage: myapi auth switch [index|email]\n\nSwitches the active account. Run without arguments to see a numbered list\nof accounts and choose interactively.\n\nPass an index number or email address to switch non-interactively:\n myapi auth switch 2\n myapi auth switch you@example.com\n\nNote: index numbers can shift as accounts are added or removed.\nUse email as a stable identifier in scripts.');
|
|
148
148
|
return;
|
|
149
149
|
}
|
|
150
150
|
const accounts = listAccounts();
|
|
@@ -171,9 +171,17 @@ export async function switchCmd(flags = {}, indexArg) {
|
|
|
171
171
|
rl.close();
|
|
172
172
|
}
|
|
173
173
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
174
|
+
// Support email as a stable identifier
|
|
175
|
+
let idx;
|
|
176
|
+
const byEmail = accounts.find(a => a.email && a.email.toLowerCase() === idxStr.toLowerCase());
|
|
177
|
+
if (byEmail) {
|
|
178
|
+
idx = byEmail.index;
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
idx = parseInt(idxStr, 10) - 1;
|
|
182
|
+
if (isNaN(idx) || idx < 0 || idx >= accounts.length) {
|
|
183
|
+
error('Invalid selection. Use an index number or email address.');
|
|
184
|
+
}
|
|
177
185
|
}
|
|
178
186
|
if (switchAccount(idx)) {
|
|
179
187
|
const a = accounts[idx];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export declare function setOrg(id: string, flags: Record<string, string | boolean
|
|
2
|
-
export declare function setFunnel(id: string, flags: Record<string, string | boolean
|
|
3
|
-
export declare function setDomain(domain: string, flags: Record<string, string | boolean
|
|
4
|
-
export declare function view(flags: Record<string, string | boolean
|
|
1
|
+
export declare function setOrg(id: string, flags: Record<string, string | boolean>, via?: string): Promise<void>;
|
|
2
|
+
export declare function setFunnel(id: string, flags: Record<string, string | boolean>, via?: string): Promise<void>;
|
|
3
|
+
export declare function setDomain(domain: string, flags: Record<string, string | boolean>, via?: string): Promise<void>;
|
|
4
|
+
export declare function view(flags: Record<string, string | boolean>, via?: string): Promise<void>;
|
|
5
5
|
export declare function run(subcommand: string | undefined, args: string[], flags: Record<string, string | boolean>): Promise<void>;
|
package/dist/commands/config.js
CHANGED
|
@@ -2,9 +2,9 @@ import { hq, funnel as sdkFunnel } from '@myapihq/sdk';
|
|
|
2
2
|
import { requireConfig, saveConfig } from '../config.js';
|
|
3
3
|
import { success, error, info } from '../output.js';
|
|
4
4
|
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
5
|
-
export async function setOrg(id, flags) {
|
|
5
|
+
export async function setOrg(id, flags, via = 'auth config') {
|
|
6
6
|
if (!id || flags.help) {
|
|
7
|
-
info(
|
|
7
|
+
info(`Usage: myapi ${via} set-org <id>\n\nSets the default organization for all commands that require --org.\nThe ID is validated against the API before saving.\n\nExample:\n myapi ${via} set-org xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`);
|
|
8
8
|
return;
|
|
9
9
|
}
|
|
10
10
|
if (!UUID_RE.test(id))
|
|
@@ -16,9 +16,9 @@ export async function setOrg(id, flags) {
|
|
|
16
16
|
saveConfig(config);
|
|
17
17
|
success(`Default organization set to: ${org.name || org.id}`);
|
|
18
18
|
}
|
|
19
|
-
export async function setFunnel(id, flags) {
|
|
19
|
+
export async function setFunnel(id, flags, via = 'auth config') {
|
|
20
20
|
if (!id || flags.help) {
|
|
21
|
-
info(
|
|
21
|
+
info(`Usage: myapi ${via} set-funnel <id>\n\nSets the default funnel. The funnel must belong to your current default org.\nThe ID is validated against the API before saving.\n\nExample:\n myapi ${via} set-funnel xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`);
|
|
22
22
|
return;
|
|
23
23
|
}
|
|
24
24
|
if (!UUID_RE.test(id))
|
|
@@ -33,9 +33,9 @@ export async function setFunnel(id, flags) {
|
|
|
33
33
|
saveConfig(config);
|
|
34
34
|
success(`Default funnel set to: ${funnel.id}`);
|
|
35
35
|
}
|
|
36
|
-
export async function setDomain(domain, flags) {
|
|
36
|
+
export async function setDomain(domain, flags, via = 'auth config') {
|
|
37
37
|
if (!domain || flags.help) {
|
|
38
|
-
info(
|
|
38
|
+
info(`Usage: myapi ${via} set-domain <domain>\n\nSets the default domain used by domain commands when --domain is omitted.\n\nExample:\n myapi ${via} set-domain example.com`);
|
|
39
39
|
return;
|
|
40
40
|
}
|
|
41
41
|
const config = requireConfig();
|
|
@@ -43,9 +43,9 @@ export async function setDomain(domain, flags) {
|
|
|
43
43
|
saveConfig(config);
|
|
44
44
|
success(`Default domain set to: ${domain}`);
|
|
45
45
|
}
|
|
46
|
-
export async function view(flags) {
|
|
46
|
+
export async function view(flags, via = 'auth config') {
|
|
47
47
|
if (flags.help) {
|
|
48
|
-
info(
|
|
48
|
+
info(`Usage: myapi ${via} view\n\nShows the currently configured defaults: default org, funnel, and domain.`);
|
|
49
49
|
return;
|
|
50
50
|
}
|
|
51
51
|
const config = requireConfig();
|
|
@@ -56,17 +56,17 @@ export async function view(flags) {
|
|
|
56
56
|
export async function run(subcommand, args, flags) {
|
|
57
57
|
const via = flags._via || 'auth config';
|
|
58
58
|
if (!subcommand || (flags.help && !subcommand)) {
|
|
59
|
-
info(`Usage: myapi ${via} <subcommand>\n\nSubcommands:\n view
|
|
59
|
+
info(`Usage: myapi ${via} <subcommand>\n\nManages CLI defaults (org, funnel, domain) so you don't have to pass --org / --domain on every command.\n\nSubcommands:\n view Show current defaults\n set-org Set default organization (validates access)\n set-funnel Set default funnel (must be owned by default org)\n set-domain Set default domain\n\nExamples:\n myapi auth config set-org <id>\n myapi auth config set-funnel <id>\n myapi auth config view`);
|
|
60
60
|
return;
|
|
61
61
|
}
|
|
62
62
|
if (subcommand === 'view')
|
|
63
|
-
await view(flags);
|
|
63
|
+
await view(flags, via);
|
|
64
64
|
else if (subcommand === 'set-org')
|
|
65
|
-
await setOrg(args[0], flags);
|
|
65
|
+
await setOrg(args[0], flags, via);
|
|
66
66
|
else if (subcommand === 'set-funnel')
|
|
67
|
-
await setFunnel(args[0], flags);
|
|
67
|
+
await setFunnel(args[0], flags, via);
|
|
68
68
|
else if (subcommand === 'set-domain')
|
|
69
|
-
await setDomain(args[0], flags);
|
|
69
|
+
await setDomain(args[0], flags, via);
|
|
70
70
|
else
|
|
71
71
|
error(`Unknown subcommand: ${subcommand}. Run "myapi config --help" for a list of valid subcommands.`);
|
|
72
72
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export declare function check(domainArg: string, flags: Record<string, string | boolean>): Promise<void>;
|
|
2
2
|
export declare function register(domainArg: string, flags: Record<string, string | boolean>): Promise<void>;
|
|
3
|
-
export declare function importDomain(domainArg: string, flags: Record<string, string | boolean>): Promise<void>;
|
|
4
3
|
export declare function list(flags: Record<string, string | boolean>): Promise<void>;
|
|
5
4
|
export declare function assign(domainArg: string, flags: Record<string, string | boolean>): Promise<void>;
|
|
6
5
|
export declare function unassign(domainArg: string, flags: Record<string, string | boolean>): Promise<void>;
|
package/dist/commands/domain.js
CHANGED
|
@@ -35,20 +35,6 @@ export async function register(domainArg, flags) {
|
|
|
35
35
|
info(`DNS propagation can take a few minutes — track it with: myapi domain status ${domain}`);
|
|
36
36
|
info(`Your funnel will be live on https://${domain} once propagation completes.`);
|
|
37
37
|
}
|
|
38
|
-
export async function importDomain(domainArg, flags) {
|
|
39
|
-
const config = requireConfig();
|
|
40
|
-
const orgId = flags.org || config.default_org;
|
|
41
|
-
const domain = domainArg || config.default_domain;
|
|
42
|
-
if (!orgId || !domain)
|
|
43
|
-
error("Missing required arguments.\nUsage: myapi domain import <domain> --org <id> [--namecheap-user <user> --namecheap-key <key>]\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
|
|
44
|
-
const payload = { domain };
|
|
45
|
-
if (flags['namecheap-user'])
|
|
46
|
-
payload.namecheap_api_user = flags['namecheap-user'];
|
|
47
|
-
if (flags['namecheap-key'])
|
|
48
|
-
payload.namecheap_api_key = flags['namecheap-key'];
|
|
49
|
-
await sdkDomain.importDomain(config.api_key, orgId, payload);
|
|
50
|
-
success(`Imported ${domain}`);
|
|
51
|
-
}
|
|
52
38
|
export async function list(flags) {
|
|
53
39
|
const config = requireConfig();
|
|
54
40
|
const orgId = flags.org || config.default_org;
|
|
@@ -56,6 +42,10 @@ export async function list(flags) {
|
|
|
56
42
|
error("Missing required arguments.\nUsage: myapi domain list --org <id> [--filter=all|unassigned|org]\n(Set default: myapi auth config set-org <id>)");
|
|
57
43
|
const filter = flags.filter;
|
|
58
44
|
const domains = await sdkDomain.listDomains(config.api_key, orgId, filter);
|
|
45
|
+
if (flags.json) {
|
|
46
|
+
printJson(domains);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
59
49
|
if (domains.length === 0) {
|
|
60
50
|
info('No domains found in this organization. Register one with: myapi domain register <name>');
|
|
61
51
|
return;
|
|
@@ -125,28 +115,26 @@ export async function updateSettings(domainArg, flags) {
|
|
|
125
115
|
}
|
|
126
116
|
export async function run(subcommand, args, flags) {
|
|
127
117
|
if (!subcommand || (flags.help && !subcommand)) {
|
|
128
|
-
info('Usage: myapi domain <subcommand>\n\nSubcommands:\n list List domains\n check Check domain availability\n register Register a domain\n
|
|
118
|
+
info('Usage: myapi domain <subcommand>\n\nSubcommands:\n list List domains\n check Check domain availability\n register Register a domain\n assign Assign domain to an org\n unassign Unassign domain from its current org\n status Get domain status\n settings Get domain settings\n update-settings Update edge/CDN settings\n\nTip: Set defaults with "myapi auth config set-org <id>" to skip --org on every command.');
|
|
129
119
|
return;
|
|
130
120
|
}
|
|
131
121
|
if (flags.help) {
|
|
132
122
|
if (subcommand === 'list')
|
|
133
|
-
info('Usage: myapi domain list --org <id> [--filter=all|unassigned|org]\n\nLists all registered domains in your account.\n --filter=all Lists all domains owned by the account.\n --filter=unassigned Lists domains not assigned to an org.\n --filter=org (Default) Lists domains assigned to the current org
|
|
123
|
+
info('Usage: myapi domain list --org <id> [--filter=all|unassigned|org] [--json]\n\nLists all registered domains in your account.\n --filter=all Lists all domains owned by the account.\n --filter=unassigned Lists domains not assigned to an org.\n --filter=org (Default) Lists domains assigned to the current org.\n --json Output raw JSON');
|
|
134
124
|
else if (subcommand === 'check')
|
|
135
125
|
info('Usage: myapi domain check <domain> --org <id> [--json]\n\nChecks if a domain name is available for registration.\n\nFlags:\n --json Output raw JSON');
|
|
136
126
|
else if (subcommand === 'register')
|
|
137
|
-
info('Usage: myapi domain register <domain> --org <id> [--years <num>]\n\nRegisters a new domain name.');
|
|
138
|
-
else if (subcommand === 'import')
|
|
139
|
-
info('Usage: myapi domain import <domain> --org <id> --namecheap-user <user> --namecheap-key <key>\n\nImports an existing domain from Namecheap.');
|
|
127
|
+
info('Usage: myapi domain register <domain> --org <id> [--years <num>]\n\nRegisters a new domain name under your account.\n\nFlags:\n --years <num> Number of years to register for (default: 1)\n\nPrerequisites:\n - You must have sufficient balance (myapi billing balance)\n - The domain must be available (myapi domain check <domain>)\n\nAfter registering, assign the domain to your org:\n myapi domain assign <domain> --org <id>\n\nDNS propagation takes a few minutes. Track it with:\n myapi domain status <domain>');
|
|
140
128
|
else if (subcommand === 'assign')
|
|
141
|
-
info('Usage: myapi domain assign <domain> --org <id>\n\nAssigns a domain to the
|
|
129
|
+
info('Usage: myapi domain assign <domain> --org <id>\n\nAssigns a registered domain to an organization. The domain must already be\nregistered under your account. Once assigned, your funnel will be served at\nhttps://<domain> after DNS propagation completes.\n\nTo transfer a domain to a different org: unassign it first, then assign to the new org.');
|
|
142
130
|
else if (subcommand === 'unassign')
|
|
143
|
-
info('Usage: myapi domain unassign <domain> --org <id>\n\nUnassigns a domain from its current organization.');
|
|
131
|
+
info('Usage: myapi domain unassign <domain> --org <id>\n\nUnassigns a domain from its current organization. The domain remains registered\nunder your account and can be reassigned to a different org at any time.');
|
|
144
132
|
else if (subcommand === 'status')
|
|
145
133
|
info('Usage: myapi domain status <domain> --org <id> [--json]\n\nGets the registration status of a domain.\n\nFlags:\n --json Output raw JSON');
|
|
146
134
|
else if (subcommand === 'settings')
|
|
147
135
|
info('Usage: myapi domain settings <domain> --org <id>\n\nGets the DNS settings and configuration for a domain.');
|
|
148
136
|
else if (subcommand === 'update-settings')
|
|
149
|
-
info('Usage: myapi domain update-settings <domain> --org <id> [--security
|
|
137
|
+
info('Usage: myapi domain update-settings <domain> --org <id> [flags]\n\nUpdates edge/CDN settings for a domain.\n\nFlags:\n --security=<level> CDN security level. Controls bot/threat filtering.\n Values: essentially_off | low | medium | high | under_attack\n Default (if unset): medium\n --browser-check=<on|off> Enable or disable browser integrity challenge for suspicious traffic.\n Default: on\n --purge-cache Immediately clears the CDN cache for this domain.\n Use after deploying changes that are not yet visible.\n\nExample:\n myapi domain update-settings example.com --org <id> --security=high --purge-cache');
|
|
150
138
|
return;
|
|
151
139
|
}
|
|
152
140
|
if (subcommand === 'list')
|
|
@@ -155,8 +143,6 @@ export async function run(subcommand, args, flags) {
|
|
|
155
143
|
await check(args[0], flags);
|
|
156
144
|
else if (subcommand === 'register')
|
|
157
145
|
await register(args[0], flags);
|
|
158
|
-
else if (subcommand === 'import')
|
|
159
|
-
await importDomain(args[0], flags);
|
|
160
146
|
else if (subcommand === 'assign')
|
|
161
147
|
await assign(args[0], flags);
|
|
162
148
|
else if (subcommand === 'unassign')
|
package/dist/commands/funnel.js
CHANGED
|
@@ -8,6 +8,10 @@ export async function list(flags) {
|
|
|
8
8
|
if (!orgId)
|
|
9
9
|
error("Missing required arguments.\nUsage: myapi funnel list --org <id>\n(Or set defaults via: myapi config set-org <id>)");
|
|
10
10
|
const funnels = await sdkFunnel.listFunnels(config.api_key, orgId);
|
|
11
|
+
if (flags.json) {
|
|
12
|
+
printJson(funnels);
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
11
15
|
const rows = funnels.map(f => ({ id: f.id, created_at: formatDate(f.created_at), updated_at: formatDate(f.updated_at) }));
|
|
12
16
|
if (rows.length === 0) {
|
|
13
17
|
info('No funnels found. Create one with: myapi funnel create');
|
|
@@ -102,15 +106,15 @@ export async function run(subcommand, args, flags) {
|
|
|
102
106
|
}
|
|
103
107
|
if (flags.help) {
|
|
104
108
|
if (subcommand === 'list')
|
|
105
|
-
info('Usage: myapi funnel list --org <id
|
|
109
|
+
info('Usage: myapi funnel list --org <id> [--json]\n\nLists all funnels (websites) in the organization.\n\nFlags:\n --org <id> Organization ID (or set default via myapi auth config set-org)\n --json Output raw JSON');
|
|
106
110
|
else if (subcommand === 'create')
|
|
107
111
|
info('Usage: myapi funnel create --org <id>\n\nCreates a new funnel in the organization.\n\nFlags:\n --org <id> Organization ID (or set default via myapi auth config set-org)');
|
|
108
112
|
else if (subcommand === 'get')
|
|
109
|
-
info('Usage: myapi funnel get <id> --org <id>\n\nFetches details of a specific funnel.\n\nFlags:\n --org <id> Organization ID (or set default via myapi auth config set-org)');
|
|
113
|
+
info('Usage: myapi funnel get <id> --org <id>\n\nFetches details of a specific funnel including its pages and settings.\n\nFlags:\n --org <id> Organization ID (or set default via myapi auth config set-org)');
|
|
110
114
|
else if (subcommand === 'delete')
|
|
111
115
|
info('Usage: myapi funnel delete <id> --org <id>\n\nDeletes a funnel permanently.\n\nFlags:\n --org <id> Organization ID (or set default via myapi auth config set-org)');
|
|
112
116
|
else if (subcommand === 'push')
|
|
113
|
-
info('Usage: myapi funnel push [funnel_id] [slug] <
|
|
117
|
+
info('Usage: myapi funnel push [funnel_id] [slug] < page.html\n\nPublishes an HTML page from stdin to a path within your funnel (website).\n\nArgument resolution:\n - If the first positional argument starts with "/", it is treated as the slug\n (funnel_id is omitted and your default funnel is used).\n - If the first positional argument looks like a UUID, it is treated as funnel_id;\n the second argument (if any) is the slug.\n - Omit both to use your configured default funnel and slug "/".\n\nFlags:\n --org <id> Organization ID (or set default via myapi auth config set-org)\n --slug <path> Alternative way to specify the slug\n\nExamples:\n echo \'<h1>Hello</h1>\' | myapi funnel push / # push to / on default funnel\n cat about.html | myapi funnel push /about # push to /about\n myapi funnel push < index.html # push to / on default funnel\n cat p.html | myapi funnel push <uuid> /pricing # explicit funnel + slug');
|
|
114
118
|
else if (subcommand === 'pull')
|
|
115
119
|
info('Usage: myapi funnel pull [funnel_id] [slug]\n\nFetches the HTML content of a funnel page.');
|
|
116
120
|
return;
|
package/dist/commands/keys.js
CHANGED
|
@@ -24,7 +24,7 @@ export async function createNew(flags) {
|
|
|
24
24
|
}
|
|
25
25
|
export async function list(flags) {
|
|
26
26
|
if (flags.help) {
|
|
27
|
-
info('Usage: myapi keys list [--json]\n\nLists all API keys associated with your account
|
|
27
|
+
info('Usage: myapi auth api-keys list [--json]\n\nLists all API keys associated with your account.\n\nAlias: myapi keys list\n\nFlags:\n --json Output raw JSON');
|
|
28
28
|
return;
|
|
29
29
|
}
|
|
30
30
|
const config = requireConfig();
|
|
@@ -48,7 +48,7 @@ export async function list(flags) {
|
|
|
48
48
|
}
|
|
49
49
|
export async function revoke(id, flags) {
|
|
50
50
|
if (flags.help) {
|
|
51
|
-
info('Usage: myapi keys revoke <id>\n\
|
|
51
|
+
info('Usage: myapi auth api-keys revoke <id>\n\nPermanently revokes an API key by ID. This action cannot be undone.\nThe key stops working immediately.\n\nAlias: myapi keys revoke <id>');
|
|
52
52
|
return;
|
|
53
53
|
}
|
|
54
54
|
if (!id) {
|
package/dist/commands/org.js
CHANGED
|
@@ -5,7 +5,7 @@ import { success, error, printTable, printJson, info } from '../output.js';
|
|
|
5
5
|
import { sleep, formatDate } from '../utils.js';
|
|
6
6
|
export async function create(flags) {
|
|
7
7
|
if (flags.help) {
|
|
8
|
-
info('Usage: myapi org create --name
|
|
8
|
+
info('Usage: myapi org create --name <name> [options]\n\nCreates a new organization. A funnel (website) is automatically created alongside it.\n\nOptions:\n --name Organization name (required). Use quotes for names with spaces.\n --tagline Short tagline\n --description Detailed description\n --business-sector Sector (e.g. Technology)\n --logo-url URL to logo image\n --yes Skip the "set as default?" prompt (useful in CI / agent workflows)\n\nExamples:\n myapi org create --name "Acme Inc"\n myapi org create --name "Acme Inc" --yes');
|
|
9
9
|
return;
|
|
10
10
|
}
|
|
11
11
|
if (!flags.name) {
|
|
@@ -45,11 +45,15 @@ export async function create(flags) {
|
|
|
45
45
|
}
|
|
46
46
|
export async function list(flags) {
|
|
47
47
|
if (flags.help) {
|
|
48
|
-
info('Usage: myapi org list\n\nLists all organizations in your account
|
|
48
|
+
info('Usage: myapi org list [--json]\n\nLists all organizations in your account.\n\nFlags:\n --json Output raw JSON');
|
|
49
49
|
return;
|
|
50
50
|
}
|
|
51
51
|
const config = requireConfig();
|
|
52
52
|
const orgs = await hq.listOrgs(config.api_key);
|
|
53
|
+
if (flags.json) {
|
|
54
|
+
printJson(orgs);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
53
57
|
const rows = orgs.map((o) => ({
|
|
54
58
|
id: o.id,
|
|
55
59
|
name: o.name,
|
|
@@ -83,7 +87,7 @@ export async function get(id, flags) {
|
|
|
83
87
|
}
|
|
84
88
|
export async function del(id, flags) {
|
|
85
89
|
if (flags.help) {
|
|
86
|
-
info('Usage: myapi org delete <id>\n\
|
|
90
|
+
info('Usage: myapi org delete <id>\n\nPermanently deletes an organization and its associated funnels.\nNote: any registered domains assigned to this org must be unassigned first.\n\nNo confirmation prompt is shown — this action is immediate.');
|
|
87
91
|
return;
|
|
88
92
|
}
|
|
89
93
|
if (!id) {
|
|
@@ -96,7 +100,7 @@ export async function del(id, flags) {
|
|
|
96
100
|
}
|
|
97
101
|
export async function importOrg(args, flags) {
|
|
98
102
|
if (flags.help) {
|
|
99
|
-
info('Usage: myapi org import <domain> --org <id>\n\
|
|
103
|
+
info('Usage: myapi org import <domain> --org <id>\n\nSyncs brand information from an existing website into an organization profile.\nMyAPI fetches the site and extracts name, logo, description, and other brand\nsignals, then updates the org automatically.\n\nThis does NOT register or assign the domain — it only reads from the site\nto enrich the org profile. Think of it as "brand sync", not domain setup.\n\nPrerequisite: an org must already exist. Create one first:\n myapi org create --name "My Brand" --yes');
|
|
100
104
|
return;
|
|
101
105
|
}
|
|
102
106
|
const config = requireConfig();
|
package/dist/commands/update.js
CHANGED
|
@@ -41,7 +41,7 @@ export async function checkForUpdate(currentVersion) {
|
|
|
41
41
|
// myapi update — explicit update, same logic as auto-update.
|
|
42
42
|
export async function update(flags = {}) {
|
|
43
43
|
if (flags.help) {
|
|
44
|
-
info('Usage: myapi update\n\nUpdates the MyAPI CLI to the latest published version.\nEquivalent to: npm install -g @myapihq/cli@latest');
|
|
44
|
+
info('Usage: myapi update\n\nUpdates the MyAPI CLI and installed skills to the latest published version.\nEquivalent to: npm install -g @myapihq/cli@latest\n\nNotes:\n - Version pinning and rollback are not supported — always installs the latest.\n - The CLI also auto-updates silently on each command when a newer version is\n detected. If you need a stable version in CI, pin with:\n npm install -g @myapihq/cli@<version>\n and set NO_COLOR=1 to suppress ANSI output in non-TTY environments.');
|
|
45
45
|
return;
|
|
46
46
|
}
|
|
47
47
|
info('› Checking for updates…');
|
package/dist/index.js
CHANGED
|
@@ -61,7 +61,7 @@ async function main() {
|
|
|
61
61
|
switch (command) {
|
|
62
62
|
case 'auth':
|
|
63
63
|
if (!subcommand || (flags.help && !subcommand)) {
|
|
64
|
-
info('Usage: myapi auth <subcommand>\n\nSubcommands:\n setup Configure your account\n import-key Import an existing API key non-interactively\n whoami Show current account\n link [email]
|
|
64
|
+
info('Usage: myapi auth <subcommand>\n\nSubcommands:\n setup Configure your account\n import-key Import an existing API key non-interactively\n whoami Show current account · supports --json\n link [email] Upgrade anonymous account to registered (or add a second session)\n Use myapi auth setup to create a completely new account\n switch [index] Switch active account by index or email\n config Manage CLI defaults (org, funnel, domain) · supports set-org / set-funnel / set-domain\n install-skills Install or update the MyAPI skills pack for AI agents\n api-keys Manage API keys · list / create / revoke\n keys Alias for api-keys');
|
|
65
65
|
break;
|
|
66
66
|
}
|
|
67
67
|
if (subcommand === 'setup')
|
|
@@ -76,7 +76,7 @@ async function main() {
|
|
|
76
76
|
await authCmd.switchCmd(flags, restArgs[0]);
|
|
77
77
|
else if (subcommand === 'install-skills') {
|
|
78
78
|
if (flags.help) {
|
|
79
|
-
info('Usage: myapi auth install-skills\n\nInstalls the MyAPI skills pack for Claude, Gemini,
|
|
79
|
+
info('Usage: myapi auth install-skills\n\nInstalls the MyAPI skills pack for AI coding agents (Claude, Gemini, Cursor).\n\nThis command writes skill definition files to:\n ~/.agents/skills/myapi/\n\nAnd creates symlinks in the appropriate agent config directories:\n ~/.claude/ (Claude)\n ~/.gemini/ (Gemini)\n ~/.cursor/ (Cursor, if detected)\n\nThese files teach agents how to use the MyAPI CLI and API directly.\nRun this command again to update existing skills to the latest version.');
|
|
80
80
|
break;
|
|
81
81
|
}
|
|
82
82
|
await setupCmd.installSkills();
|
|
@@ -86,11 +86,11 @@ async function main() {
|
|
|
86
86
|
await configCmd.run(restArgs[0], restArgs.slice(1), flags);
|
|
87
87
|
else if (subcommand === 'api-keys') {
|
|
88
88
|
if (flags.help && !restArgs[0]) {
|
|
89
|
-
info('Usage: myapi auth api-keys <subcommand>\n\nSubcommands:\n list List all API keys\n create Create a new API key\n revoke <id>
|
|
89
|
+
info('Usage: myapi auth api-keys <subcommand>\n\nManage programmatic API keys for your account. API keys are used to authenticate\nrequests to the MyAPI SDK and REST API.\n\nSubcommands:\n list List all API keys with their IDs and creation dates\n create Create a new API key (the key value is shown once)\n revoke <id> Permanently revoke an API key by ID\n\nExamples:\n myapi auth api-keys list\n myapi auth api-keys create\n myapi auth api-keys revoke xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx');
|
|
90
90
|
break;
|
|
91
91
|
}
|
|
92
92
|
if (!restArgs[0]) {
|
|
93
|
-
info('
|
|
93
|
+
info('Run: myapi auth api-keys --help');
|
|
94
94
|
break;
|
|
95
95
|
}
|
|
96
96
|
if (restArgs[0] === 'create')
|
|
@@ -154,8 +154,8 @@ async function main() {
|
|
|
154
154
|
await authCmd.whoami(flags);
|
|
155
155
|
break;
|
|
156
156
|
case 'keys':
|
|
157
|
-
if (!subcommand) {
|
|
158
|
-
info('Usage: myapi keys <list
|
|
157
|
+
if (!subcommand || flags.help) {
|
|
158
|
+
info('Usage: myapi keys <subcommand>\n\nManage programmatic API keys for your account. API keys are used to authenticate\nrequests to the MyAPI SDK and REST API.\n\nSubcommands:\n list List all API keys with their IDs and creation dates\n create Create a new API key (the key value is shown once)\n revoke <id> Permanently revoke an API key by ID\n\nExamples:\n myapi keys list\n myapi keys create\n myapi keys revoke xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n\nAlias for: myapi auth api-keys');
|
|
159
159
|
break;
|
|
160
160
|
}
|
|
161
161
|
if (subcommand === 'create')
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# my-api-hq
|
|
2
|
+
|
|
3
|
+
Core identity and billing hub for the MyAPI ecosystem. **Start here** — every other service requires an API key and often an `org_id` from this one.
|
|
4
|
+
|
|
5
|
+
## What it does
|
|
6
|
+
|
|
7
|
+
- Account management (register an account on myapihq.com)
|
|
8
|
+
- API key creation and management
|
|
9
|
+
- Organization management (`org_id` used by all other services)
|
|
10
|
+
- Balance top-up and billing history
|
|
11
|
+
|
|
12
|
+
## Quickstart
|
|
13
|
+
|
|
14
|
+
1. Register an account on myapihq.com
|
|
15
|
+
2. Generate an API key from the dashboard
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# 3. Use the generated api_key for all subsequent requests
|
|
19
|
+
export MYAPI_KEY=hq_live_...
|
|
20
|
+
|
|
21
|
+
# 4. Create an org (required by most services)
|
|
22
|
+
curl -sS -X POST https://api.myapihq.com/hq/orgs \
|
|
23
|
+
-H "Authorization: Bearer $MYAPI_KEY" \
|
|
24
|
+
-H "Content-Type: application/json" \
|
|
25
|
+
-d '{"name": "My Org"}'
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Authentication
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
Authorization: Bearer <api_key>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Links
|
|
35
|
+
|
|
36
|
+
- [Full skill documentation (SKILL.md)](./SKILL.md)
|
|
37
|
+
- [MyAPI HQ](https://myapihq.com)
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: my-api-hq
|
|
3
|
+
description: >
|
|
4
|
+
Core Identity and Billing hub. Manage auth, organizations (get org_id), and billing (checkout/topup).
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# MyApiHQ Skill
|
|
8
|
+
Root entry point for the ecosystem. All other skills require an `api_key` and often an `org_id` from here.
|
|
9
|
+
|
|
10
|
+
## Platform Conventions
|
|
11
|
+
|
|
12
|
+
### Response Envelope
|
|
13
|
+
Every response across all services is wrapped in:
|
|
14
|
+
```json
|
|
15
|
+
{
|
|
16
|
+
"success": true,
|
|
17
|
+
"data": { ... },
|
|
18
|
+
"error": null,
|
|
19
|
+
"meta": { "request_id": "...", "latency_ms": 12, "service": "...", "version": "v1" }
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
On error, `success` is `false`, `data` is `null`, and `error` contains a string error code or object. Always check `success` before reading `data`.
|
|
23
|
+
|
|
24
|
+
### Pagination
|
|
25
|
+
List endpoints accept `?limit=` and `?offset=` and return `total`, `limit`, `offset` in the body.
|
|
26
|
+
|
|
27
|
+
## Authentication & Key Management
|
|
28
|
+
|
|
29
|
+
You need to go to myapihq.com and register an account. Generate an api key and export it to pass it to the agent (as env).
|
|
30
|
+
|
|
31
|
+
### Account Login
|
|
32
|
+
```
|
|
33
|
+
POST /hq/account/login
|
|
34
|
+
{ "email": "...", "password": "..." }
|
|
35
|
+
→ { "data": { "token": "<JWT>" } }
|
|
36
|
+
```
|
|
37
|
+
Errors: `401` wrong password.
|
|
38
|
+
|
|
39
|
+
**Refresh Token:**
|
|
40
|
+
```
|
|
41
|
+
POST /hq/account/refresh
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Google OAuth:**
|
|
45
|
+
- `GET /hq/auth/google/redirect` — Initiates Google OAuth flow.
|
|
46
|
+
- `GET /hq/auth/google/callback` — OAuth callback.
|
|
47
|
+
|
|
48
|
+
### API Key Management
|
|
49
|
+
**Generate Persistent Key:**
|
|
50
|
+
```
|
|
51
|
+
POST /hq/account/create/key
|
|
52
|
+
Authorization: Bearer <JWT from login>
|
|
53
|
+
{ "name": "MyKey" }
|
|
54
|
+
→ { "data": { "api_key": "hq_live_...", "id": "...", "prefix": "..." } }
|
|
55
|
+
```
|
|
56
|
+
Errors: `401` no auth.
|
|
57
|
+
|
|
58
|
+
Use `Authorization: Bearer <api_key>` for all subsequent requests across the entire ecosystem.
|
|
59
|
+
|
|
60
|
+
**List Keys:** `GET /hq/account/keys`
|
|
61
|
+
|
|
62
|
+
**Revoke Key:** `DELETE /hq/account/delete/key/{id}`
|
|
63
|
+
|
|
64
|
+
### Cross-Session Storage
|
|
65
|
+
**Always persist credentials immediately.** Write a `.env` file:
|
|
66
|
+
```
|
|
67
|
+
MYAPI_API_KEY=hq_live_...
|
|
68
|
+
MYAPI_ACCOUNT_ID=...
|
|
69
|
+
```
|
|
70
|
+
Also save to agent memory if your runtime supports it (e.g., Claude Code memory). On every new session, check for credentials before creating a new account.
|
|
71
|
+
|
|
72
|
+
## Organization Management
|
|
73
|
+
**You MUST create an org to get an `org_id` for other APIs.**
|
|
74
|
+
|
|
75
|
+
### Create Org (sync)
|
|
76
|
+
```
|
|
77
|
+
POST /hq/orgs
|
|
78
|
+
{ "name": "Acme Inc" (required), "tagline", "description", "business_sector",
|
|
79
|
+
"logo_url", "favicon_url", "og_image_url",
|
|
80
|
+
"color_palette": { "primary": "#hex", ... },
|
|
81
|
+
"font_family", "imagery_style", "headline", "subheadline", "cta_text",
|
|
82
|
+
"value_propositions": ["..."],
|
|
83
|
+
"social_links": { "twitter": "url", ... },
|
|
84
|
+
"canonical_url", "privacy_policy_url", "cookie_policy_url", "terms_url",
|
|
85
|
+
"gdpr_enabled": false, "default_language": "en", "tracking": {} }
|
|
86
|
+
→ { "data": { "id": "<org_id>", ... } }
|
|
87
|
+
```
|
|
88
|
+
Errors: `400` invalid_json · `422` name_required, invalid_field:color_palette, invalid_field:value_propositions, invalid_field:social_links, invalid_field:tracking · `402` insufficient balance (org creation has a cost on paid plan).
|
|
89
|
+
|
|
90
|
+
### Async Brand Import
|
|
91
|
+
```
|
|
92
|
+
POST /hq/org-imports
|
|
93
|
+
{ "org_id": "<id>" (required), "domain": "example.com" (required), "auto_accept": false }
|
|
94
|
+
→ { "data": { "job_id": "...", "status": "pending" } }
|
|
95
|
+
|
|
96
|
+
GET /hq/org-imports/{job_id}
|
|
97
|
+
→ Poll until status = "awaiting_confirm". Returns brand_preview.
|
|
98
|
+
|
|
99
|
+
POST /hq/org-imports/{job_id}/confirm
|
|
100
|
+
{ ...optional overrides matching POST /hq/orgs payload... }
|
|
101
|
+
→ { "data": { "id": "<org_id>", ... } }
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Manage Orgs
|
|
105
|
+
- `GET /hq/orgs` — list all orgs.
|
|
106
|
+
- `GET /hq/orgs/{id}` — get org details. Errors: `404` org_not_found.
|
|
107
|
+
- `PATCH /hq/orgs/{id}` — partial update, same fields as create. Errors: `400` invalid_json · `404` org_not_found · `422` invalid_field:*.
|
|
108
|
+
- `DELETE /hq/orgs/{id}` — delete org and cascade. Errors: `404` org_not_found.
|
|
109
|
+
|
|
110
|
+
## Billing
|
|
111
|
+
- **Setup Payment Method:** You need to do this from the myapihq dashboard directly.
|
|
112
|
+
- **Check Balance:** `GET /hq/billing/balance` → `{ "data": { "balance_cents": 1000, "balance_display": "$10.00", "credits_cents": 500, "credits_display": "$5.00", "has_payment_method": true } }`.
|
|
113
|
+
- **Billing History:** `GET /hq/billing/history`
|
|
114
|
+
- **Top Up:** `POST /hq/billing/topup` — `{ "amount_cents": 1000 }` → `{ "data": { "new_balance_cents": 2000, "new_balance_display": "$20.00" } }`.
|
|
115
|
+
|
|
116
|
+
**On 402 from any service:** check balance and top up here before retrying.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# my-domain-api
|
|
2
|
+
|
|
3
|
+
Register domains, check availability and pricing, import existing domains, and manage edge settings. Required before creating mailboxes (`my-email-api`) or funnels (`my-funnel-api`) — both need an owned domain.
|
|
4
|
+
|
|
5
|
+
## What it does
|
|
6
|
+
|
|
7
|
+
- Check domain availability and pricing
|
|
8
|
+
- Register new domains (auto-configures DNS + email infrastructure)
|
|
9
|
+
- Import existing domains
|
|
10
|
+
- Manage edge/DNS settings
|
|
11
|
+
|
|
12
|
+
## Quickstart
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
# Check availability
|
|
16
|
+
curl -sS https://mydomainapi.com/domain/check/example.com \
|
|
17
|
+
-H "Authorization: Bearer $MYAPI_KEY"
|
|
18
|
+
|
|
19
|
+
# Register a domain
|
|
20
|
+
curl -sS -X POST https://mydomainapi.com/domain/register \
|
|
21
|
+
-H "Authorization: Bearer $MYAPI_KEY" \
|
|
22
|
+
-H "Content-Type: application/json" \
|
|
23
|
+
-d '{"domain": "example.com", "org_id": "<org_id>"}'
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Authentication
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
Authorization: Bearer <api_key>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Requires `org_id` from `my-api-hq`.
|
|
33
|
+
|
|
34
|
+
## Links
|
|
35
|
+
|
|
36
|
+
- [Full skill documentation (SKILL.md)](./SKILL.md)
|
|
37
|
+
- [MyDomainAPI](https://mydomainapi.com)
|