@myapihq/cli 1.1.0-wip.5 → 1.2.1

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 (125) hide show
  1. package/dist/commands/{email.d.ts → audience.d.ts} +2 -0
  2. package/dist/commands/audience.js +245 -0
  3. package/dist/commands/auth.d.ts +5 -2
  4. package/dist/commands/auth.js +133 -5
  5. package/dist/commands/billing.d.ts +2 -0
  6. package/dist/commands/billing.js +18 -1
  7. package/dist/commands/company.d.ts +6 -0
  8. package/dist/commands/company.js +149 -0
  9. package/dist/commands/config.d.ts +2 -0
  10. package/dist/commands/config.js +20 -0
  11. package/dist/commands/crm/companies.d.ts +6 -0
  12. package/dist/commands/crm/companies.js +193 -0
  13. package/dist/commands/crm/contacts.d.ts +6 -0
  14. package/dist/commands/crm/contacts.js +241 -0
  15. package/dist/commands/crm/index.d.ts +6 -0
  16. package/dist/commands/crm/index.js +74 -0
  17. package/dist/commands/database.d.ts +6 -0
  18. package/dist/commands/database.js +259 -0
  19. package/dist/commands/domain.d.ts +4 -0
  20. package/dist/commands/domain.js +166 -8
  21. package/dist/commands/email/campaign.d.ts +2 -0
  22. package/dist/commands/email/campaign.js +34 -1
  23. package/dist/commands/email/index.d.ts +2 -0
  24. package/dist/commands/email/index.js +9 -0
  25. package/dist/commands/email/mailbox.d.ts +2 -0
  26. package/dist/commands/email/mailbox.js +5 -0
  27. package/dist/commands/email/message.d.ts +2 -0
  28. package/dist/commands/email/message.js +8 -0
  29. package/dist/commands/email/template.d.ts +2 -0
  30. package/dist/commands/email/template.js +54 -0
  31. package/dist/commands/email/verify.d.ts +7 -0
  32. package/dist/commands/email/verify.js +52 -0
  33. package/dist/commands/email/warmup.d.ts +2 -0
  34. package/dist/commands/email/warmup.js +7 -0
  35. package/dist/commands/funnel.d.ts +3 -0
  36. package/dist/commands/funnel.js +31 -0
  37. package/dist/commands/image.d.ts +2 -0
  38. package/dist/commands/image.js +43 -9
  39. package/dist/commands/keys.d.ts +2 -0
  40. package/dist/commands/keys.js +5 -0
  41. package/dist/commands/llm.d.ts +6 -0
  42. package/dist/commands/llm.js +156 -0
  43. package/dist/commands/org.d.ts +3 -0
  44. package/dist/commands/org.js +55 -0
  45. package/dist/commands/people.d.ts +6 -0
  46. package/dist/commands/people.js +136 -0
  47. package/dist/commands/pixel.d.ts +11 -3
  48. package/dist/commands/pixel.js +93 -0
  49. package/dist/commands/setup.d.ts +2 -0
  50. package/dist/commands/setup.js +57 -5
  51. package/dist/commands/status.d.ts +7 -0
  52. package/dist/commands/status.js +154 -0
  53. package/dist/commands/storage.d.ts +2 -0
  54. package/dist/commands/storage.js +9 -1
  55. package/dist/commands/update.d.ts +2 -0
  56. package/dist/commands/update.js +3 -0
  57. package/dist/commands/url.d.ts +7 -2
  58. package/dist/commands/url.js +6 -0
  59. package/dist/commands/webhook.d.ts +2 -0
  60. package/dist/commands/webhook.js +31 -6
  61. package/dist/commands/workflow.d.ts +2 -0
  62. package/dist/commands/workflow.js +19 -1
  63. package/dist/completion.d.ts +3 -0
  64. package/dist/completion.js +78 -0
  65. package/dist/config.d.ts +2 -0
  66. package/dist/exposes.d.ts +2 -0
  67. package/dist/exposes.js +13 -0
  68. package/dist/exposes.test.js +99 -0
  69. package/dist/flags.test.js +84 -0
  70. package/dist/index.js +106 -14
  71. package/dist/prompt.d.ts +15 -0
  72. package/dist/prompt.js +27 -0
  73. package/dist/registrant.d.ts +6 -0
  74. package/dist/registrant.js +155 -0
  75. package/dist/services-sync.test.d.ts +1 -0
  76. package/dist/services-sync.test.js +32 -0
  77. package/dist/skills/my-api-hq/SKILL.md +51 -45
  78. package/dist/skills/my-crm-api/README.md +42 -0
  79. package/dist/skills/my-crm-api/SKILL.md +165 -0
  80. package/dist/skills/my-crm-api/claude/.claude-plugin/plugin.json +6 -0
  81. package/dist/skills/my-database-api/README.md +41 -0
  82. package/dist/skills/my-database-api/SKILL.md +107 -0
  83. package/dist/skills/my-database-api/claude/.claude-plugin/plugin.json +6 -0
  84. package/dist/skills/my-domain-api/SKILL.md +53 -26
  85. package/dist/skills/my-email-verify-api/README.md +33 -0
  86. package/dist/skills/my-email-verify-api/SKILL.md +91 -0
  87. package/dist/skills/my-email-verify-api/claude/.claude-plugin/plugin.json +6 -0
  88. package/dist/skills/my-funnel-api/SKILL.md +41 -37
  89. package/dist/skills/my-image-api/SKILL.md +48 -44
  90. package/dist/skills/my-llm-api/README.md +35 -0
  91. package/dist/skills/my-llm-api/SKILL.md +125 -0
  92. package/dist/skills/my-llm-api/claude/.claude-plugin/plugin.json +6 -0
  93. package/dist/skills/my-storage-api/README.md +1 -1
  94. package/dist/skills/my-storage-api/SKILL.md +44 -54
  95. package/dist/skills/my-webhook-api/README.md +1 -1
  96. package/dist/skills/my-webhook-api/SKILL.md +48 -92
  97. package/dist/skills/my-workflow-api/SKILL.md +46 -115
  98. package/dist/telemetry.d.ts +12 -0
  99. package/dist/telemetry.js +80 -0
  100. package/dist/telemetry.test.d.ts +1 -0
  101. package/dist/telemetry.test.js +101 -0
  102. package/package.json +13 -8
  103. package/dist/commands/email.js +0 -586
  104. package/dist/skills/my-email-api/README.md +0 -45
  105. package/dist/skills/my-email-api/SKILL.md +0 -104
  106. package/dist/skills/my-email-api/claude/.claude-plugin/plugin.json +0 -6
  107. package/dist/skills/my-email-api/make/.gitkeep +0 -0
  108. package/dist/skills/my-email-api/n8n/.gitkeep +0 -0
  109. package/dist/skills/my-email-api/openapi/.gitkeep +0 -0
  110. package/dist/skills/my-funnel-api/make/.gitkeep +0 -0
  111. package/dist/skills/my-funnel-api/n8n/.gitkeep +0 -0
  112. package/dist/skills/my-image-api/make/.gitkeep +0 -0
  113. package/dist/skills/my-image-api/n8n/.gitkeep +0 -0
  114. package/dist/skills/my-storage-api/make/.gitkeep +0 -0
  115. package/dist/skills/my-storage-api/n8n/.gitkeep +0 -0
  116. package/dist/skills/my-webhook-api/make/.gitkeep +0 -0
  117. package/dist/skills/my-webhook-api/n8n/.gitkeep +0 -0
  118. package/dist/skills/my-workflow-api/make/.gitkeep +0 -0
  119. package/dist/skills/my-workflow-api/n8n/.gitkeep +0 -0
  120. package/dist/utils.test.js +0 -48
  121. /package/dist/{utils.test.d.ts → exposes.test.d.ts} +0 -0
  122. /package/dist/skills/{my-api-hq/make → my-crm-api/openapi}/.gitkeep +0 -0
  123. /package/dist/skills/{my-api-hq/n8n → my-database-api/openapi}/.gitkeep +0 -0
  124. /package/dist/skills/{my-domain-api/make → my-email-verify-api/openapi}/.gitkeep +0 -0
  125. /package/dist/skills/{my-domain-api/n8n → my-llm-api/openapi}/.gitkeep +0 -0
@@ -2,6 +2,19 @@ import { email as sdkEmail } from '@myapihq/sdk';
2
2
  import { requireConfig } from '../../config.js';
3
3
  import { success, error, printTable, printJson, info } from '../../output.js';
4
4
  import { requireOrg } from '../../helpers.js';
5
+ export const EXPOSES = [
6
+ 'POST /email/orgs/{org_id}/campaigns',
7
+ 'GET /email/orgs/{org_id}/campaigns',
8
+ 'GET /email/orgs/{org_id}/campaigns/{campaign_id}',
9
+ 'PATCH /email/orgs/{org_id}/campaigns/{campaign_id}',
10
+ 'POST /email/orgs/{org_id}/campaigns/{campaign_id}/contacts/upload-list',
11
+ 'POST /email/orgs/{org_id}/campaigns/{campaign_id}/contacts/upload-file',
12
+ 'GET /email/orgs/{org_id}/campaigns/{campaign_id}/contacts/status',
13
+ 'POST /email/orgs/{org_id}/campaigns/{campaign_id}/start',
14
+ 'POST /email/orgs/{org_id}/campaigns/{campaign_id}/pause',
15
+ 'POST /email/orgs/{org_id}/campaigns/{campaign_id}/resume',
16
+ 'GET /email/orgs/{org_id}/campaigns/{campaign_id}/stats',
17
+ ];
5
18
  async function create(nameArg, flags) {
6
19
  const config = requireConfig();
7
20
  const orgId = requireOrg(flags, config, 'myapi email campaign create <name> --template-id <id> --from <email> [--per-day <n>] [--org <id>]');
@@ -61,6 +74,23 @@ async function uploadContacts(id, flags) {
61
74
  const res = await sdkEmail.uploadContactList(config.api_key, orgId, id, emails);
62
75
  success(`Uploaded ${res.total} contacts (status: ${res.status})`);
63
76
  }
77
+ async function uploadContactsFile(id, flags) {
78
+ const config = requireConfig();
79
+ const orgId = requireOrg(flags, config, 'myapi email campaign upload-contacts-file <campaign_id> --file <path> [--org <id>]');
80
+ if (!id || !flags.file) {
81
+ error('Missing required arguments.\nUsage: myapi email campaign upload-contacts-file <campaign_id> --file <path> [--org <id>]');
82
+ }
83
+ // Defer fs require to keep the unimported-cost low for users who never
84
+ // touch this command. Plain JS readFile fits — the SDK accepts a Buffer.
85
+ const fs = await import('node:fs');
86
+ const path = await import('node:path');
87
+ const filePath = flags.file;
88
+ if (!fs.existsSync(filePath))
89
+ error(`File not found: ${filePath}`);
90
+ const buf = fs.readFileSync(filePath);
91
+ const res = await sdkEmail.uploadContactsFile(config.api_key, orgId, id, buf, path.basename(filePath));
92
+ success(`Uploaded ${res.total} contacts from ${filePath} (status: ${res.status})`);
93
+ }
64
94
  async function start(id, flags) {
65
95
  const config = requireConfig();
66
96
  const orgId = requireOrg(flags, config, 'myapi email campaign start <id> [--org <id>]');
@@ -106,6 +136,7 @@ Either form works; the positional name is the recommended shape.`,
106
136
  'get': 'myapi email campaign get <id> [--org <id>]',
107
137
  'update': 'myapi email campaign update <id> [--name <str>] [--per-day <n>] [--org <id>]',
108
138
  'upload-contacts': 'myapi email campaign upload-contacts <campaign_id> --emails <a@x,b@y> [--org <id>]',
139
+ 'upload-contacts-file': 'myapi email campaign upload-contacts-file <campaign_id> --file <path> [--org <id>]',
109
140
  'start': 'myapi email campaign start <id> [--org <id>]',
110
141
  'pause': 'myapi email campaign pause <id> [--org <id>]',
111
142
  'resume': 'myapi email campaign resume <id> [--org <id>]',
@@ -120,7 +151,8 @@ Subcommands:
120
151
  list List campaigns
121
152
  get <id> Get a single campaign
122
153
  update <id> Patch name / per-day-limit
123
- upload-contacts <id> Upload contact list (--emails a@x,b@y)
154
+ upload-contacts <id> Upload contact list (--emails a@x,b@y)
155
+ upload-contacts-file <id> Upload contacts from a CSV file (--file path/to/contacts.csv)
124
156
  start <id> Start a campaign
125
157
  pause <id> Pause a campaign
126
158
  resume <id> Resume a campaign
@@ -143,6 +175,7 @@ All commands accept --org <id> (or set default: myapi config set-org <id>).`);
143
175
  case 'get': return get(args[0], flags);
144
176
  case 'update': return update(args[0], flags);
145
177
  case 'upload-contacts': return uploadContacts(args[0], flags);
178
+ case 'upload-contacts-file': return uploadContactsFile(args[0], flags);
146
179
  case 'start': return start(args[0], flags);
147
180
  case 'pause': return pause(args[0], flags);
148
181
  case 'resume': return resume(args[0], flags);
@@ -1,4 +1,6 @@
1
1
  import type { FlagSchema } from '../../flags.js';
2
2
  import type { Flags } from '../../helpers.js';
3
+ import type { Exposes } from '../../exposes.js';
4
+ export declare const EXPOSES: Exposes;
3
5
  export declare const SCHEMA: FlagSchema;
4
6
  export declare function run(subcommand: string | undefined, args: string[], flags: Flags): Promise<void>;
@@ -2,11 +2,16 @@
2
2
  // namespace lives in its own file in this directory; this index just
3
3
  // routes to the right one and handles the deprecated flat aliases.
4
4
  import { error, info } from '../../output.js';
5
+ // The email index is a dispatcher only; each subcommand file declares
6
+ // its own EXPOSES. Empty here so the coverage tool can still introspect
7
+ // every file uniformly.
8
+ export const EXPOSES = [];
5
9
  import * as mailbox from './mailbox.js';
6
10
  import * as message from './message.js';
7
11
  import * as warmup from './warmup.js';
8
12
  import * as template from './template.js';
9
13
  import * as campaign from './campaign.js';
14
+ import * as verify from './verify.js';
10
15
  export const SCHEMA = {
11
16
  org: 'string',
12
17
  domain: 'string',
@@ -27,6 +32,7 @@ export const SCHEMA = {
27
32
  name: 'string',
28
33
  emails: 'string',
29
34
  'per-day': 'number',
35
+ file: 'string',
30
36
  };
31
37
  // Old flat subcommand → [namespace, sub]. Kept so existing scripts/skills
32
38
  // don't break. Emits a one-line stderr deprecation note then runs the new
@@ -63,6 +69,7 @@ async function dispatchNamespace(ns, sub, restArgs, flags) {
63
69
  case 'warmup': return warmup.run(sub, restArgs, flags);
64
70
  case 'template': return template.run(sub, restArgs, flags);
65
71
  case 'campaign': return campaign.run(sub, restArgs, flags);
72
+ case 'verify': return verify.run(sub, restArgs, flags);
66
73
  default: error(`Unknown namespace: ${ns}. Run "myapi email --help" for the list.`);
67
74
  }
68
75
  }
@@ -76,12 +83,14 @@ Namespaces:
76
83
  warmup Warmup controls (account-scoped) — start, pause, resume, stop, stats
77
84
  template Email templates (org-scoped) — generate, list, edit, send-test, delete
78
85
  campaign Email campaigns (org-scoped) — create, list, get, update, upload-contacts, start, pause, resume, stats
86
+ verify Sync single-address email verification (org-scoped) — syntax + DNS + Microsoft probe
79
87
 
80
88
  Examples:
81
89
  myapi email mailbox create hello@example.com
82
90
  myapi email message send --from a@x --to b@y --subject hi --body "hello"
83
91
  myapi email template generate welcome --prompt "Welcome email"
84
92
  myapi email campaign create "Q2 Launch" --template-id <id> --from a@x
93
+ myapi email verify alice@example.com
85
94
 
86
95
  Org-scoped commands accept --org <id> (or set default: myapi config set-org <id>).
87
96
  Run "myapi email <namespace> --help" for namespace-specific commands.`);
@@ -1,2 +1,4 @@
1
1
  import type { Flags } from '../../helpers.js';
2
+ import type { Exposes } from '../../exposes.js';
3
+ export declare const EXPOSES: Exposes;
2
4
  export declare function run(sub: string | undefined, args: string[], flags: Flags): Promise<void>;
@@ -1,6 +1,11 @@
1
1
  import { email as sdkEmail } from '@myapihq/sdk';
2
2
  import { requireConfig } from '../../config.js';
3
3
  import { success, error, printTable, info } from '../../output.js';
4
+ export const EXPOSES = [
5
+ 'POST /email/mailboxes/create',
6
+ 'GET /email/mailboxes',
7
+ 'POST /email/sending/activate',
8
+ ];
4
9
  async function create(addressArg, flags) {
5
10
  const config = requireConfig();
6
11
  // Convention: first required arg is positional. For mailboxes that's the
@@ -1,2 +1,4 @@
1
1
  import type { Flags } from '../../helpers.js';
2
+ import type { Exposes } from '../../exposes.js';
3
+ export declare const EXPOSES: Exposes;
2
4
  export declare function run(sub: string | undefined, args: string[], flags: Flags): Promise<void>;
@@ -1,6 +1,14 @@
1
1
  import { email as sdkEmail } from '@myapihq/sdk';
2
2
  import { requireConfig } from '../../config.js';
3
3
  import { success, error, printTable, printJson, info } from '../../output.js';
4
+ export const EXPOSES = [
5
+ 'POST /email/send',
6
+ 'GET /email/status/{message_id}',
7
+ 'GET /email/sent',
8
+ 'GET /email/inbox/{address}',
9
+ 'GET /email/outbox/{address}',
10
+ 'GET /email/message/{message_id}',
11
+ ];
4
12
  async function send(flags) {
5
13
  const config = requireConfig();
6
14
  if (!flags.from || !flags.to || !flags.subject) {
@@ -1,2 +1,4 @@
1
1
  import { type Flags } from '../../helpers.js';
2
+ import type { Exposes } from '../../exposes.js';
3
+ export declare const EXPOSES: Exposes;
2
4
  export declare function run(sub: string | undefined, args: string[], flags: Flags): Promise<void>;
@@ -3,6 +3,16 @@ import { requireConfig } from '../../config.js';
3
3
  import { success, error, printTable, printJson, info } from '../../output.js';
4
4
  import { pollJob } from '../../utils.js';
5
5
  import { requireOrg } from '../../helpers.js';
6
+ export const EXPOSES = [
7
+ 'POST /email/orgs/{org_id}/templates/generate',
8
+ 'GET /email/orgs/{org_id}/template-jobs/{job_id}',
9
+ 'GET /email/orgs/{org_id}/templates',
10
+ 'GET /email/orgs/{org_id}/templates/{template_id}',
11
+ 'POST /email/orgs/{org_id}/templates/{template_id}/edit',
12
+ 'POST /email/orgs/{org_id}/templates/{template_id}/send-test',
13
+ 'DELETE /email/orgs/{org_id}/templates/{template_id}',
14
+ 'GET /email/templates/{template_id}/preview',
15
+ ];
6
16
  async function generate(nameArg, flags) {
7
17
  const config = requireConfig();
8
18
  const orgId = requireOrg(flags, config, 'myapi email template generate <name> --prompt <str> [--org <id>]');
@@ -39,6 +49,44 @@ async function list(flags) {
39
49
  empty: 'No templates yet. Generate one with: myapi email template generate --prompt <p> --name <n>',
40
50
  });
41
51
  }
52
+ async function get(id, flags) {
53
+ const config = requireConfig();
54
+ const orgId = requireOrg(flags, config, 'myapi email template get <id> [--org <id>]');
55
+ if (!id)
56
+ error('Missing required arguments.\nUsage: myapi email template get <id> [--org <id>]');
57
+ const tmpl = await sdkEmail.getTemplate(config.api_key, orgId, id);
58
+ if (flags.json) {
59
+ printJson(tmpl);
60
+ return;
61
+ }
62
+ info(`ID: ${tmpl.id}`);
63
+ info(`Name: ${tmpl.name}`);
64
+ info(`Subject: ${tmpl.subject}`);
65
+ info(`Preview: ${tmpl.preview_url}`);
66
+ info(`Created: ${tmpl.created_at}`);
67
+ info(`Updated: ${tmpl.updated_at}`);
68
+ }
69
+ async function preview(id, flags) {
70
+ if (!id)
71
+ error('Missing required arguments.\nUsage: myapi email template preview <id> [--json]');
72
+ // Endpoint is unauthenticated by design — access is gated by the unguessable
73
+ // template_id, so anyone with the id can render the preview (this matches
74
+ // the "share-this-link-with-your-marketer" pattern).
75
+ const res = await sdkEmail.getTemplatePreview(id);
76
+ if (flags.json) {
77
+ printJson(res);
78
+ return;
79
+ }
80
+ if (res.preview_url)
81
+ info(`Preview URL: ${res.preview_url}`);
82
+ if (res.subject)
83
+ info(`Subject: ${res.subject}`);
84
+ if (res.html)
85
+ info(`\n--- HTML ---\n${res.html}`);
86
+ // Fall back to dumping the whole response if we got something unfamiliar.
87
+ if (!res.preview_url && !res.subject && !res.html)
88
+ printJson(res);
89
+ }
42
90
  async function edit(id, flags) {
43
91
  const config = requireConfig();
44
92
  const orgId = requireOrg(flags, config, 'myapi email template edit <id> --prompt <str> [--org <id>]');
@@ -69,6 +117,8 @@ const USAGE = {
69
117
 
70
118
  Either form works; the positional name is the recommended shape.`,
71
119
  'list': 'myapi email template list [--org <id>] [--json]',
120
+ 'get': 'myapi email template get <id> [--org <id>] [--json]',
121
+ 'preview': 'myapi email template preview <id> [--json]',
72
122
  'edit': 'myapi email template edit <id> --prompt <str> [--org <id>]',
73
123
  'send-test': 'myapi email template send-test <template_id> --to <email> [--org <id>]',
74
124
  'delete': 'myapi email template delete <id> [--org <id>]',
@@ -80,6 +130,8 @@ export async function run(sub, args, flags) {
80
130
  Subcommands:
81
131
  generate <name> Generate AI template (--prompt)
82
132
  list List templates
133
+ get <id> Get a template's metadata (subject, preview URL, ...)
134
+ preview <id> Get a template's rendered preview (no auth required)
83
135
  edit <id> Edit a template via prompt
84
136
  send-test <id> Send a test email for a template (--to)
85
137
  delete <id> Delete a template
@@ -98,6 +150,8 @@ All commands accept --org <id> (or set default: myapi config set-org <id>).`);
98
150
  switch (sub) {
99
151
  case 'generate': return generate(args[0], flags);
100
152
  case 'list': return list(flags);
153
+ case 'get': return get(args[0], flags);
154
+ case 'preview': return preview(args[0], flags);
101
155
  case 'edit': return edit(args[0], flags);
102
156
  case 'send-test': return sendTest(args[0], flags);
103
157
  case 'delete': return del(args[0], flags);
@@ -0,0 +1,7 @@
1
+ import type { FlagSchema } from '../../flags.js';
2
+ import { type Flags } from '../../helpers.js';
3
+ import type { Exposes } from '../../exposes.js';
4
+ export declare const EXPOSES: Exposes;
5
+ export declare const SCHEMA: FlagSchema;
6
+ export declare const VERIFY_HELP = "Usage: myapi email verify <email> [--org <id>] [--json]\n\nSync single-address email verification. Cheap layer only: syntax + DNS +\nMicrosoft GetCredentialType. Returns a verdict in <1s for ~50% of inputs;\nthe rest get verdict='unknown' with smtp_recommended=true.\n\nVerdicts:\n deliverable high-confidence \u2014 the address accepts mail\n undeliverable high-confidence \u2014 syntax bad, DNS missing, or Microsoft rejects\n unknown not enough signal; consider an SMTP probe (not in this API)\n\nUse --json for the full check breakdown (syntax / DNS / Microsoft probes).\n";
7
+ export declare function run(emailArg: string | undefined, _rest: string[], flags?: Flags): Promise<void>;
@@ -0,0 +1,52 @@
1
+ import { email as sdkEmail } from '@myapihq/sdk';
2
+ import { requireConfig } from '../../config.js';
3
+ import { error, info, printJson } from '../../output.js';
4
+ import { requireOrg } from '../../helpers.js';
5
+ export const EXPOSES = [
6
+ 'POST /email/orgs/{org_id}/verify',
7
+ ];
8
+ export const SCHEMA = {};
9
+ export const VERIFY_HELP = `Usage: myapi email verify <email> [--org <id>] [--json]
10
+
11
+ Sync single-address email verification. Cheap layer only: syntax + DNS +
12
+ Microsoft GetCredentialType. Returns a verdict in <1s for ~50% of inputs;
13
+ the rest get verdict='unknown' with smtp_recommended=true.
14
+
15
+ Verdicts:
16
+ deliverable high-confidence — the address accepts mail
17
+ undeliverable high-confidence — syntax bad, DNS missing, or Microsoft rejects
18
+ unknown not enough signal; consider an SMTP probe (not in this API)
19
+
20
+ Use --json for the full check breakdown (syntax / DNS / Microsoft probes).
21
+ `;
22
+ export async function run(emailArg, _rest, flags = {}) {
23
+ if (flags.help) {
24
+ info(VERIFY_HELP);
25
+ return;
26
+ }
27
+ if (!emailArg)
28
+ error('Missing required argument <email>.\nUsage: myapi email verify <email> [--org <id>] [--json]');
29
+ const config = requireConfig();
30
+ const orgId = requireOrg(flags, config, 'myapi email verify <email> [--org <id>]');
31
+ const res = await sdkEmail.verifyEmail(config.api_key, orgId, emailArg);
32
+ if (flags.json) {
33
+ printJson(res);
34
+ return;
35
+ }
36
+ const verdictLabel = res.verdict === 'deliverable' ? '✓ deliverable'
37
+ : res.verdict === 'undeliverable' ? '✗ undeliverable'
38
+ : '? unknown';
39
+ info(`Email: ${res.email}`);
40
+ info(`Verdict: ${verdictLabel} (confidence ${res.confidence.toFixed(2)})`);
41
+ info(`SMTP next: ${res.smtp_recommended ? 'yes — consider an SMTP probe' : 'no — verdict is definitive'}`);
42
+ info(`Took: ${res.elapsed_ms}ms`);
43
+ if (res.checks.syntax.detail)
44
+ info(`Syntax: ${res.checks.syntax.detail}`);
45
+ if (res.checks.dns && res.checks.dns.mx_records && res.checks.dns.mx_records.length > 0) {
46
+ const mx = res.checks.dns.mx_records.filter(Boolean);
47
+ if (mx.length > 0)
48
+ info(`MX: ${mx.slice(0, 3).join(', ')}${mx.length > 3 ? ` (+${mx.length - 3} more)` : ''}`);
49
+ }
50
+ if (res.checks.microsoft)
51
+ info(`Microsoft: ${res.checks.microsoft.verdict}`);
52
+ }
@@ -1,2 +1,4 @@
1
1
  import type { Flags } from '../../helpers.js';
2
+ import type { Exposes } from '../../exposes.js';
3
+ export declare const EXPOSES: Exposes;
2
4
  export declare function run(sub: string | undefined, args: string[], flags: Flags): Promise<void>;
@@ -1,6 +1,13 @@
1
1
  import { email as sdkEmail } from '@myapihq/sdk';
2
2
  import { requireConfig } from '../../config.js';
3
3
  import { success, error, printJson, info } from '../../output.js';
4
+ export const EXPOSES = [
5
+ 'POST /email/warmup/start',
6
+ 'POST /email/warmup/pause',
7
+ 'POST /email/warmup/resume',
8
+ 'POST /email/warmup/stop',
9
+ 'GET /email/warmup/stats/{address}',
10
+ ];
4
11
  export async function run(sub, args, flags) {
5
12
  if (!sub || (flags.help && !sub)) {
6
13
  info('Usage: myapi email warmup <start|pause|resume|stop|stats> --address <email>');
@@ -1,10 +1,13 @@
1
1
  import type { FlagSchema } from '../flags.js';
2
2
  import { type Flags } from '../helpers.js';
3
+ import type { Exposes } from '../exposes.js';
4
+ export declare const EXPOSES: Exposes;
3
5
  export declare const SCHEMA: FlagSchema;
4
6
  export declare function list(flags: Flags): Promise<void>;
5
7
  export declare function create(flags: Flags): Promise<void>;
6
8
  export declare function get(id: string, flags: Flags): Promise<void>;
7
9
  export declare function del(id: string, flags: Flags): Promise<void>;
10
+ export declare function pages(funnelArg: string, flags: Flags): Promise<void>;
8
11
  export declare function push(slug: string, flags: Flags): Promise<void>;
9
12
  export declare function verify(slug: string, flags: Flags): Promise<void>;
10
13
  export declare function run(subcommand: string | undefined, args: string[], flags: Flags): Promise<void>;
@@ -3,6 +3,16 @@ import { requireConfig } from '../config.js';
3
3
  import { success, error, printTable, info, printJson } from '../output.js';
4
4
  import { formatDate } from '../utils.js';
5
5
  import { requireOrg } from '../helpers.js';
6
+ export const EXPOSES = [
7
+ 'POST /funnel/orgs/{org_id}/funnels',
8
+ 'GET /funnel/orgs/{org_id}/funnels',
9
+ 'GET /funnel/orgs/{org_id}/funnels/{funnel_id}',
10
+ 'DELETE /funnel/orgs/{org_id}/funnels/{funnel_id}',
11
+ 'POST /funnel/orgs/{org_id}/funnels/{funnel_id}/push-page',
12
+ 'POST /funnel/orgs/{org_id}/funnels/{funnel_id}/verify',
13
+ 'GET /funnel/orgs/{org_id}/funnels/{funnel_id}/pages',
14
+ 'GET /hq/orgs/{org_id}',
15
+ ];
6
16
  export const SCHEMA = {
7
17
  org: 'string',
8
18
  funnel: 'string',
@@ -74,6 +84,24 @@ export async function del(id, flags) {
74
84
  await sdkFunnel.deleteFunnel(config.api_key, orgId, id);
75
85
  success(`Funnel ${id} deleted`);
76
86
  }
87
+ // List the pages currently published to a funnel. Resolves the funnel id
88
+ // from positional arg, --funnel flag, or the user's default funnel.
89
+ export async function pages(funnelArg, flags) {
90
+ const config = requireConfig();
91
+ const orgId = requireOrg(flags, config, 'myapi funnel pages [funnel_id] [--funnel <id>] [--org <id>]');
92
+ const funnelId = funnelArg || flags.funnel || config.default_funnel;
93
+ if (!funnelId)
94
+ error('Missing funnel id. Pass it as a positional arg, --funnel <id>, or set: myapi config set-funnel <id>');
95
+ const list = await sdkFunnel.listFunnelPages(config.api_key, orgId, funnelId);
96
+ if (flags.json) {
97
+ printJson(list);
98
+ return;
99
+ }
100
+ printTable(list, {
101
+ flags,
102
+ empty: 'No pages published to this funnel yet. Push one with: echo "<h1>Hello</h1>" | myapi funnel push /',
103
+ });
104
+ }
77
105
  export async function push(slug, flags) {
78
106
  const config = requireConfig();
79
107
  const orgId = requireOrg(flags, config, 'myapi funnel push [slug] [--funnel <id>] [--org <id>]');
@@ -158,6 +186,7 @@ const SUBCOMMAND_USAGE = {
158
186
  'create': 'myapi funnel create [--org <id>]',
159
187
  'get': 'myapi funnel get <id> [--org <id>] [--json]',
160
188
  'delete': 'myapi funnel delete <id> [--org <id>]',
189
+ 'pages': 'myapi funnel pages [funnel_id] [--funnel <id>] [--org <id>] [--json]',
161
190
  'push': `myapi funnel push [slug] [--funnel <id>] [--slug <path>] [--org <id>] < page.html
162
191
 
163
192
  Reads HTML from stdin and publishes to <slug> on your funnel. Funnel is resolved
@@ -194,6 +223,7 @@ Subcommands:
194
223
  get <id> Get funnel details
195
224
  delete Delete a funnel
196
225
  push Push a raw HTML page from stdin to a slug
226
+ pages List the pages currently published to a funnel
197
227
  verify Verify a published page is reachable
198
228
 
199
229
  All commands accept --org <id> (or set default: myapi config set-org <id>).`);
@@ -214,6 +244,7 @@ All commands accept --org <id> (or set default: myapi config set-org <id>).`);
214
244
  case 'delete': return del(args[0], flags);
215
245
  case 'push': return push(args[0], flags);
216
246
  case 'verify': return verify(args[0], flags);
247
+ case 'pages': return pages(args[0], flags);
217
248
  default: error(`Unknown subcommand: ${subcommand}. Run "myapi funnel --help" for a list of valid subcommands.`);
218
249
  }
219
250
  }
@@ -1,4 +1,6 @@
1
1
  import type { FlagSchema } from '../flags.js';
2
2
  import { type Flags } from '../helpers.js';
3
+ import type { Exposes } from '../exposes.js';
4
+ export declare const EXPOSES: Exposes;
3
5
  export declare const SCHEMA: FlagSchema;
4
6
  export declare function run(subcommand: string | undefined, args: string[], flags: Flags): Promise<void>;
@@ -3,8 +3,16 @@ import { requireConfig } from '../config.js';
3
3
  import { success, error, printTable, info, printJson, banner } from '../output.js';
4
4
  import { formatDate, pollJob } from '../utils.js';
5
5
  import { requireOrg, requireArg } from '../helpers.js';
6
+ export const EXPOSES = [
7
+ 'POST /image/orgs/{org_id}/generate',
8
+ 'GET /image/orgs/{org_id}/jobs/{job_id}',
9
+ 'GET /image/orgs/{org_id}/list',
10
+ 'GET /image/orgs/{org_id}/models',
11
+ 'DELETE /image/orgs/{org_id}/images/{image_id}',
12
+ ];
6
13
  export const SCHEMA = {
7
14
  org: 'string',
15
+ model: 'string',
8
16
  prompt: 'string',
9
17
  ratio: 'string',
10
18
  style: 'string',
@@ -14,7 +22,6 @@ export const SCHEMA = {
14
22
  const VALID_RATIOS = new Set(['1:1', '16:9', '9:16', '4:3', '3:4']);
15
23
  // Hex list: optional leading #, 3 or 6 hex digits, comma-separated.
16
24
  const HEX_LIST_RE = /^#?[0-9a-fA-F]{3}(?:[0-9a-fA-F]{3})?(?:\s*,\s*#?[0-9a-fA-F]{3}(?:[0-9a-fA-F]{3})?)*$/;
17
- const PRICE_USD = 0.05;
18
25
  function summarizeImage(j) {
19
26
  const prompt = (j.prompt || '');
20
27
  const truncated = prompt.length > 60 ? prompt.slice(0, 60) + '...' : prompt;
@@ -29,11 +36,11 @@ function summarizeImage(j) {
29
36
  }
30
37
  async function generate(promptArg, flags) {
31
38
  const config = requireConfig();
32
- const orgId = requireOrg(flags, config, 'myapi image generate <prompt> [--ratio 1:1|16:9|9:16|4:3|3:4] [--style <s>] [--colors <hex,hex>] [--text] [--org <id>]');
39
+ const orgId = requireOrg(flags, config, 'myapi image generate <prompt> [--model <id>] [--ratio 1:1|16:9|9:16|4:3|3:4] [--style <s>] [--colors <hex,hex>] [--text] [--org <id>]');
33
40
  // Convention: first required arg is positional. --prompt still works for back-compat.
34
41
  const prompt = promptArg || flags.prompt;
35
42
  if (!prompt) {
36
- error('Missing required arguments.\nUsage: myapi image generate <prompt> [--ratio <ratio>] [--style <s>] [--colors <c>] [--text] [--org <id>]\n or: myapi image generate --prompt "<text>" ...');
43
+ error('Missing required arguments.\nUsage: myapi image generate <prompt> [--model <id>] [--ratio <ratio>] [--style <s>] [--colors <c>] [--text] [--org <id>]\n or: myapi image generate --prompt "<text>" ...');
37
44
  }
38
45
  // Client-side validation: catch typos before they round-trip.
39
46
  if (flags.ratio && !VALID_RATIOS.has(flags.ratio)) {
@@ -43,6 +50,8 @@ async function generate(promptArg, flags) {
43
50
  error(`Invalid --colors "${flags.colors}". Expected comma-separated hex like "#ff6600,#003366" (3- or 6-digit, # optional).`);
44
51
  }
45
52
  const payload = { prompt };
53
+ if (flags.model)
54
+ payload.model = flags.model;
46
55
  if (flags.ratio)
47
56
  payload.aspect_ratio = flags.ratio;
48
57
  if (flags.style)
@@ -51,9 +60,9 @@ async function generate(promptArg, flags) {
51
60
  payload.colors = flags.colors;
52
61
  if (flags.text)
53
62
  payload.has_text = true;
54
- // Cost preview before kickoff. Goes to stderr (banner) so --json output
55
- // stays clean for piping.
56
- banner(`› Charging $${PRICE_USD.toFixed(2)} for this image generation…`);
63
+ // Cost is per-model see `myapi image models`. Banner shown on stderr so
64
+ // --json output stays clean for piping.
65
+ banner(`› Generating image${payload.model ? ` (${payload.model})` : ''}…`);
57
66
  const job = await sdkImage.generateImage(config.api_key, orgId, payload);
58
67
  const final = await pollJob({
59
68
  label: 'Generating image',
@@ -124,10 +133,26 @@ async function del(id, flags) {
124
133
  await sdkImage.deleteImage(config.api_key, orgId, id);
125
134
  success(`Image ${id} deleted (job history retained, URL nullified)`);
126
135
  }
136
+ async function models(flags) {
137
+ const config = requireConfig();
138
+ const orgId = requireOrg(flags, config, 'myapi image models [--org <id>]');
139
+ const res = await sdkImage.listModels(config.api_key, orgId);
140
+ if (flags.json) {
141
+ printJson(res);
142
+ return;
143
+ }
144
+ printTable(res.models.map(m => ({
145
+ id: m.id,
146
+ kind: m.kind,
147
+ default_size: m.default_size,
148
+ aspect_ratios: m.aspect_ratios.join(', '),
149
+ cost_per_image: `$${m.cost_per_image_usd}`,
150
+ })), { flags, empty: 'No image models available.' });
151
+ }
127
152
  // ── Dispatcher ───────────────────────────────────────────────────────────────
128
153
  const SUBCOMMAND_USAGE = {
129
154
  'list': 'myapi image list [--org <id>] [--json]',
130
- 'generate': `myapi image generate <prompt> [--ratio 1:1|16:9|9:16|4:3|3:4] [--style <s>] [--colors <hex,hex>] [--text] [--org <id>]
155
+ 'generate': `myapi image generate <prompt> [--model <id>] [--ratio 1:1|16:9|9:16|4:3|3:4] [--style <s>] [--colors <hex,hex>] [--text] [--org <id>]
131
156
  myapi image generate --prompt "<text>" ...
132
157
 
133
158
  Either form works; the positional prompt is the recommended shape.
@@ -136,9 +161,11 @@ Generation is asynchronous — the CLI polls for up to 90s. If it times out
136
161
  the job keeps running server-side; re-fetch with:
137
162
  myapi image get <job_id>
138
163
 
139
- Cost: $${PRICE_USD.toFixed(2)} per generation. Failed jobs aren't charged.
164
+ Cost is per-model; run "myapi image models" for the catalog and rates.
165
+ Failed jobs aren't charged.
140
166
 
141
167
  Flags:
168
+ --model Model id from the catalog (default: gemini-2.5-flash-image)
142
169
  --ratio Aspect ratio (allowed: ${[...VALID_RATIOS].join(', ')}; default 1:1)
143
170
  --style Free-form style hint (e.g. "watercolor", "cyberpunk neon")
144
171
  --colors Hex colors comma-separated (e.g. "#ff6600,#003366")
@@ -153,6 +180,11 @@ Prints just the asset URL. Errors if the job hasn't completed yet.
153
180
  Curl-friendly:
154
181
  curl -O "$(myapi image get-url <id>)"`,
155
182
  'delete': 'myapi image delete <job_id> [--org <id>]',
183
+ 'models': `myapi image models [--org <id>] [--json]
184
+
185
+ Lists available image-generation models with per-image pricing and
186
+ supported aspect ratios. Mirrors "myapi llm models" for the image
187
+ primitive.`,
156
188
  };
157
189
  export async function run(subcommand, args, flags) {
158
190
  if (!subcommand || (flags.help && !subcommand)) {
@@ -160,9 +192,10 @@ export async function run(subcommand, args, flags) {
160
192
 
161
193
  Subcommands:
162
194
  list List all your generated images
163
- generate <prompt> Generate a new AI image (async, polls up to 90s, $${PRICE_USD.toFixed(2)})
195
+ generate <prompt> Generate a new AI image (async, polls up to 90s; pricing per model — see "image models")
164
196
  get <job_id> Fetch full job metadata (JSON or human-readable)
165
197
  get-url <job_id> Print just the asset URL (curl-friendly)
198
+ models List available image models with per-image pricing
166
199
  delete <job_id> Delete the asset (job history retained)
167
200
 
168
201
  All commands accept --org <id> (or set default: myapi config set-org <id>).
@@ -182,6 +215,7 @@ The asset lands in your org's storage and is also visible via "myapi storage lis
182
215
  case 'generate': return generate(args[0], flags);
183
216
  case 'get': return get(args[0], flags);
184
217
  case 'get-url': return getUrl(args[0], flags);
218
+ case 'models': return models(flags);
185
219
  case 'delete': return del(args[0], flags);
186
220
  default: error(`Unknown subcommand: ${subcommand}. Run "myapi image --help" for available subcommands.`);
187
221
  }
@@ -1,6 +1,8 @@
1
1
  import type { FlagSchema } from '../flags.js';
2
2
  import type { Flags } from '../helpers.js';
3
+ import type { Exposes } from '../exposes.js';
3
4
  export declare const SCHEMA: FlagSchema;
5
+ export declare const EXPOSES: Exposes;
4
6
  export declare function run(subcommand: string | undefined, args: string[], flags: Flags): Promise<void>;
5
7
  export declare function runApiKeys(subcommand: string | undefined, args: string[], flags: Flags): Promise<void>;
6
8
  export declare function createNew(flags: Flags): Promise<void>;
@@ -7,6 +7,11 @@ import { requireArg } from '../helpers.js';
7
7
  export const SCHEMA = {
8
8
  name: 'string',
9
9
  };
10
+ export const EXPOSES = [
11
+ 'POST /hq/account/create/key',
12
+ 'GET /hq/account/keys',
13
+ 'DELETE /hq/account/delete/key/{key_id}',
14
+ ];
10
15
  const KEYS_HEADER = `Usage: myapi keys <subcommand>
11
16
 
12
17
  Manage programmatic API keys for your account.
@@ -0,0 +1,6 @@
1
+ import type { FlagSchema } from '../flags.js';
2
+ import { type Flags } from '../helpers.js';
3
+ import type { Exposes } from '../exposes.js';
4
+ export declare const EXPOSES: Exposes;
5
+ export declare const SCHEMA: FlagSchema;
6
+ export declare function run(subcommand: string | undefined, args: string[], flags: Flags): Promise<void>;