@myapihq/cli 1.0.84 → 1.1.0-wip.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/dist/commands/auth.d.ts +8 -3
  2. package/dist/commands/auth.js +11 -29
  3. package/dist/commands/billing.d.ts +8 -4
  4. package/dist/commands/billing.js +43 -22
  5. package/dist/commands/config.d.ts +8 -5
  6. package/dist/commands/config.js +52 -27
  7. package/dist/commands/domain.d.ts +12 -9
  8. package/dist/commands/domain.js +117 -86
  9. package/dist/commands/email.d.ts +4 -12
  10. package/dist/commands/email.js +490 -128
  11. package/dist/commands/funnel.d.ts +10 -7
  12. package/dist/commands/funnel.js +75 -55
  13. package/dist/commands/image.js +25 -15
  14. package/dist/commands/keys.d.ts +8 -3
  15. package/dist/commands/keys.js +67 -28
  16. package/dist/commands/org.d.ts +9 -5
  17. package/dist/commands/org.js +99 -46
  18. package/dist/commands/pixel.js +23 -11
  19. package/dist/commands/setup.d.ts +3 -2
  20. package/dist/commands/setup.js +44 -77
  21. package/dist/commands/storage.js +25 -15
  22. package/dist/commands/update.d.ts +2 -1
  23. package/dist/commands/url.js +19 -7
  24. package/dist/commands/webhook.d.ts +8 -5
  25. package/dist/commands/webhook.js +52 -36
  26. package/dist/commands/workflow.d.ts +13 -7
  27. package/dist/commands/workflow.js +158 -56
  28. package/dist/flags.d.ts +8 -0
  29. package/dist/flags.js +88 -0
  30. package/dist/flags.test.d.ts +1 -0
  31. package/dist/flags.test.js +73 -0
  32. package/dist/helpers.d.ts +6 -0
  33. package/dist/helpers.js +29 -0
  34. package/dist/index.js +93 -107
  35. package/dist/output.d.ts +10 -1
  36. package/dist/output.js +4 -6
  37. package/dist/skills/my-email-api/README.md +45 -0
  38. package/dist/skills/my-email-api/SKILL.md +106 -0
  39. package/dist/skills/my-email-api/claude/.claude-plugin/plugin.json +6 -0
  40. package/dist/skills/my-email-api/make/.gitkeep +0 -0
  41. package/dist/skills/my-email-api/n8n/.gitkeep +0 -0
  42. package/dist/skills/my-email-api/openapi/.gitkeep +0 -0
  43. package/dist/skills/my-webhook-api/README.md +40 -0
  44. package/dist/skills/my-webhook-api/SKILL.md +65 -0
  45. package/dist/skills/my-webhook-api/claude/.claude-plugin/plugin.json +6 -0
  46. package/dist/skills/my-webhook-api/make/.gitkeep +0 -0
  47. package/dist/skills/my-webhook-api/n8n/.gitkeep +0 -0
  48. package/dist/skills/my-webhook-api/openapi/.gitkeep +0 -0
  49. package/dist/skills/my-workflow-api/README.md +37 -0
  50. package/dist/skills/my-workflow-api/SKILL.md +98 -0
  51. package/dist/skills/my-workflow-api/claude/.claude-plugin/plugin.json +6 -0
  52. package/dist/skills/my-workflow-api/make/.gitkeep +0 -0
  53. package/dist/skills/my-workflow-api/n8n/.gitkeep +0 -0
  54. package/dist/skills/my-workflow-api/openapi/.gitkeep +0 -0
  55. package/dist/utils.d.ts +0 -4
  56. package/dist/utils.js +0 -33
  57. package/dist/utils.test.d.ts +1 -0
  58. package/dist/utils.test.js +48 -0
  59. package/package.json +9 -4
  60. package/dist/commands/account.d.ts +0 -4
  61. package/dist/commands/account.js +0 -80
package/dist/index.js CHANGED
@@ -1,10 +1,9 @@
1
1
  #!/usr/bin/env node
2
- // manually maintained — do not regenerate from scripts/generate-indexes.js
3
- import { parseArgs } from './utils.js';
4
2
  import { error, info, success } from './output.js';
5
3
  import { loadConfig } from './config.js';
6
4
  import { MyApiError } from '@myapihq/sdk';
7
5
  import * as fs from 'fs';
6
+ import { parseFlags } from './flags.js';
8
7
  const pkgPath = new URL('../package.json', import.meta.url);
9
8
  const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
10
9
  import * as keysCmd from './commands/keys.js';
@@ -14,8 +13,29 @@ import * as setupCmd from './commands/setup.js';
14
13
  import * as updateCmd from './commands/update.js';
15
14
  import * as domainCmd from './commands/domain.js';
16
15
  import * as funnelCmd from './commands/funnel.js';
16
+ import * as webhookCmd from './commands/webhook.js';
17
+ import * as workflowCmd from './commands/workflow.js';
18
+ import * as emailCmd from './commands/email.js';
17
19
  import * as authCmd from './commands/auth.js';
18
20
  import * as configCmd from './commands/config.js';
21
+ // Each command file declares the value flags it understands. We union them
22
+ // into a single schema for the upfront parse, so adding a new value flag in
23
+ // one command means editing one file (its SCHEMA), not a global allowlist.
24
+ const COMBINED_SCHEMA = {
25
+ ...authCmd.SCHEMA,
26
+ ...billingCmd.SCHEMA,
27
+ ...configCmd.SCHEMA,
28
+ ...domainCmd.SCHEMA,
29
+ ...emailCmd.SCHEMA,
30
+ ...funnelCmd.SCHEMA,
31
+ ...keysCmd.SCHEMA,
32
+ ...orgCmd.SCHEMA,
33
+ ...webhookCmd.SCHEMA,
34
+ ...workflowCmd.SCHEMA,
35
+ // Top-level flags
36
+ version: 'boolean',
37
+ V: 'boolean',
38
+ };
19
39
  const ERROR_MESSAGES = {
20
40
  DOMAIN_NOT_FOUND: 'Domain not found.',
21
41
  INVALID_DOMAIN: 'Invalid domain name.',
@@ -43,7 +63,7 @@ function friendlyError(code) {
43
63
  return ERROR_MESSAGES[code] || code;
44
64
  }
45
65
  async function main() {
46
- const { args, flags } = parseArgs(process.argv.slice(2));
66
+ const { args, flags } = parseFlags(process.argv.slice(2), COMBINED_SCHEMA);
47
67
  if (flags.version || flags.v || flags.V) {
48
68
  const latest = await updateCmd.latestVersion();
49
69
  const updateNote = latest && updateCmd.isNewer(latest, pkg.version)
@@ -71,89 +91,16 @@ async function main() {
71
91
  try {
72
92
  switch (command) {
73
93
  case 'auth':
74
- if (!subcommand || (flags.help && !subcommand)) {
75
- 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');
76
- break;
77
- }
78
- if (subcommand === 'setup')
79
- await setupCmd.setup(flags);
80
- else if (subcommand === 'import-key')
81
- await setupCmd.importKey(restArgs[0], flags);
82
- else if (subcommand === 'whoami')
83
- await authCmd.whoami(flags);
84
- else if (subcommand === 'link')
85
- await authCmd.link(flags, restArgs[0]);
86
- else if (subcommand === 'switch')
87
- await authCmd.switchCmd(flags, restArgs[0]);
88
- else if (subcommand === 'install-skills') {
89
- if (flags.help) {
90
- 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.');
91
- break;
92
- }
93
- await setupCmd.installSkills();
94
- success('› Skills installed.');
95
- }
96
- else if (subcommand === 'config')
97
- await configCmd.run(restArgs[0], restArgs.slice(1), flags);
98
- else if (subcommand === 'api-keys') {
99
- if (flags.help && !restArgs[0]) {
100
- 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 hq_live_xxxxxxxxxxxxxxxxxxxx');
101
- break;
102
- }
103
- if (!restArgs[0]) {
104
- info('Run: myapi auth api-keys --help');
105
- break;
106
- }
107
- if (restArgs[0] === 'create')
108
- await keysCmd.createNew(flags);
109
- else if (restArgs[0] === 'list')
110
- await keysCmd.list(flags);
111
- else if (restArgs[0] === 'revoke')
112
- await keysCmd.revoke(restArgs[1], flags);
113
- }
114
- else
115
- info('Unknown subcommand. Run: myapi auth --help');
94
+ await dispatchAuth(subcommand, restArgs, flags);
116
95
  break;
117
96
  case 'update':
118
97
  await updateCmd.update(flags);
119
98
  break;
120
99
  case 'org':
121
- if (!subcommand || (flags.help && !subcommand)) {
122
- info('Usage: myapi org <subcommand>\n\nSubcommands:\n list List organizations\n create Create an organization · myapi org create "Name" --yes\n get Get details of an organization\n delete Delete an organization\n sync-brand Sync brand info (name, logo, description) from an existing website into an org');
123
- break;
124
- }
125
- if (subcommand === 'list')
126
- await orgCmd.list(flags);
127
- else if (subcommand === 'create')
128
- await orgCmd.create(restArgs, flags);
129
- else if (subcommand === 'get')
130
- await orgCmd.get(restArgs[0], flags);
131
- else if (subcommand === 'delete')
132
- await orgCmd.del(restArgs[0], flags);
133
- else if (subcommand === 'sync-brand')
134
- await orgCmd.importOrg(restArgs, flags);
135
- else if (subcommand === 'import') {
136
- process.stderr.write('› Note: "org import" is deprecated — use "org sync-brand" instead.\n');
137
- await orgCmd.importOrg(restArgs, flags);
138
- }
139
- else
140
- printHelp();
100
+ await orgCmd.run(subcommand, restArgs, flags);
141
101
  break;
142
102
  case 'billing':
143
- if (!subcommand || (flags.help && !subcommand)) {
144
- info('Usage: myapi billing <subcommand>\n\nSubcommands:\n balance Check balance\n history View billing history\n topup Top up your balance\n setup Setup a payment method');
145
- break;
146
- }
147
- if (subcommand === 'balance')
148
- await billingCmd.balance(flags);
149
- else if (subcommand === 'history')
150
- await billingCmd.history(flags);
151
- else if (subcommand === 'topup')
152
- await billingCmd.topup(restArgs[0], flags);
153
- else if (subcommand === 'setup')
154
- await billingCmd.setup(flags);
155
- else
156
- printHelp();
103
+ await billingCmd.run(subcommand, restArgs, flags);
157
104
  break;
158
105
  case 'domain':
159
106
  await domainCmd.run(subcommand, restArgs, flags);
@@ -161,6 +108,15 @@ async function main() {
161
108
  case 'funnel':
162
109
  await funnelCmd.run(subcommand, restArgs, flags);
163
110
  break;
111
+ case 'webhook':
112
+ await webhookCmd.run(subcommand, restArgs, flags);
113
+ break;
114
+ case 'workflow':
115
+ await workflowCmd.run(subcommand, restArgs, flags);
116
+ break;
117
+ case 'email':
118
+ await emailCmd.run(subcommand, restArgs, flags);
119
+ break;
164
120
  // Convenience aliases
165
121
  case 'setup':
166
122
  await setupCmd.setup(flags);
@@ -169,45 +125,21 @@ async function main() {
169
125
  await authCmd.whoami(flags);
170
126
  break;
171
127
  case 'keys':
172
- if (!subcommand || (flags.help && !subcommand)) {
173
- 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 hq_live_xxxxxxxxxxxxxxxxxxxx\n\nAlias for: myapi auth api-keys');
174
- break;
175
- }
176
- if (subcommand === 'create')
177
- await keysCmd.createNew(flags);
178
- else if (subcommand === 'list')
179
- await keysCmd.list(flags);
180
- else if (subcommand === 'revoke')
181
- await keysCmd.revoke(restArgs[0], flags);
128
+ await keysCmd.run(subcommand, restArgs, flags);
182
129
  break;
183
130
  case 'config':
184
131
  await configCmd.run(subcommand, restArgs, { ...flags, _via: 'config' });
185
132
  break;
186
133
  case 'install-skills':
187
134
  if (flags.help) {
188
- info('Usage: myapi install-skills\n\nAlias for: myapi auth install-skills');
135
+ info(authCmd.INSTALL_SKILLS_HELP);
189
136
  break;
190
137
  }
191
138
  await setupCmd.installSkills();
192
139
  success('› Skills installed.');
193
140
  break;
194
141
  case 'help':
195
- if (subcommand === 'funnel')
196
- await funnelCmd.run(undefined, [], { help: true });
197
- else if (subcommand === 'domain')
198
- await domainCmd.run(undefined, [], { help: true });
199
- else if (subcommand === 'auth')
200
- 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 switch [index] Switch active account by index or email\n config Manage CLI defaults (org, funnel, domain)\n install-skills Install or update the MyAPI skills pack for AI agents\n api-keys Manage API keys · list / create / revoke');
201
- else if (subcommand === 'org')
202
- info('Usage: myapi org <subcommand>\n\nSubcommands:\n list List organizations\n create Create an organization · myapi org create "Name" --yes\n get Get details of an organization\n delete Delete an organization\n sync-brand Sync brand info from an existing website into an org');
203
- else if (subcommand === 'billing')
204
- info('Usage: myapi billing <subcommand>\n\nSubcommands:\n balance Check balance\n history View billing history\n topup Top up your balance\n setup Setup a payment method');
205
- else if (subcommand === 'keys')
206
- info('Usage: myapi keys <subcommand>\n\nSubcommands:\n list List all API keys\n create Create a new API key\n revoke <id> Revoke an API key\n\nAlias for: myapi auth api-keys');
207
- else if (subcommand)
208
- info(`Run: myapi ${subcommand} --help`);
209
- else
210
- printHelp();
142
+ await dispatchHelp(subcommand);
211
143
  break;
212
144
  default:
213
145
  error(`Unknown command: ${command}. Run "myapi" for available commands.`);
@@ -223,7 +155,7 @@ async function main() {
223
155
  else if (err.code === 'NO_PAYMENT_METHOD')
224
156
  error('No payment method on file. Run: myapi billing setup');
225
157
  else
226
- error(`Insufficient balance. Run: myapi billing topup <amount>`);
158
+ error('Insufficient balance. Run: myapi billing topup <amount>');
227
159
  }
228
160
  else
229
161
  error(friendlyError(err.code) || err.message);
@@ -233,6 +165,57 @@ async function main() {
233
165
  }
234
166
  }
235
167
  }
168
+ async function dispatchAuth(subcommand, restArgs, flags) {
169
+ if (!subcommand || (flags.help && !subcommand)) {
170
+ info(authCmd.HELP);
171
+ return;
172
+ }
173
+ switch (subcommand) {
174
+ case 'setup': return setupCmd.setup(flags);
175
+ case 'import-key': return setupCmd.importKey(restArgs[0], flags);
176
+ case 'whoami': return authCmd.whoami(flags);
177
+ case 'link': return authCmd.link(flags, restArgs[0]);
178
+ case 'switch': return authCmd.switchCmd(flags, restArgs[0]);
179
+ case 'install-skills':
180
+ if (flags.help) {
181
+ info(authCmd.INSTALL_SKILLS_HELP);
182
+ return;
183
+ }
184
+ await setupCmd.installSkills();
185
+ success('› Skills installed.');
186
+ return;
187
+ case 'config': return configCmd.run(restArgs[0], restArgs.slice(1), flags);
188
+ case 'api-keys':
189
+ case 'keys': return keysCmd.runApiKeys(restArgs[0], restArgs.slice(1), flags);
190
+ default: info('Unknown subcommand. Run: myapi auth --help');
191
+ }
192
+ }
193
+ const HELP_TARGETS = {
194
+ funnel: f => funnelCmd.run(undefined, [], f),
195
+ domain: f => domainCmd.run(undefined, [], f),
196
+ webhook: f => webhookCmd.run(undefined, [], f),
197
+ workflow: f => workflowCmd.run(undefined, [], f),
198
+ email: f => emailCmd.run(undefined, [], f),
199
+ org: f => orgCmd.run(undefined, [], f),
200
+ billing: f => billingCmd.run(undefined, [], f),
201
+ keys: f => keysCmd.run(undefined, [], f),
202
+ config: f => configCmd.run(undefined, [], f),
203
+ };
204
+ async function dispatchHelp(target) {
205
+ if (!target) {
206
+ printHelp();
207
+ return;
208
+ }
209
+ if (target === 'auth') {
210
+ info(authCmd.HELP);
211
+ return;
212
+ }
213
+ const handler = HELP_TARGETS[target];
214
+ if (handler)
215
+ await handler({ help: true });
216
+ else
217
+ info(`Run: myapi ${target} --help`);
218
+ }
236
219
  function printHelp() {
237
220
  const config = loadConfig();
238
221
  const quickStart = config?.api_key
@@ -252,6 +235,9 @@ Commands:
252
235
  update Update CLI and skills to the latest version
253
236
  domain Manage domain configurations
254
237
  funnel Manage websites (publish pages, custom domains, funnels)
238
+ webhook Manage inbound webhook endpoints and inspect deliveries
239
+ email Manage mailboxes, send/read email, templates, and campaigns
240
+ workflow Run actions (send email, post to Slack) when a webhook fires
255
241
 
256
242
  Aliases:
257
243
  whoami → myapi auth whoami
package/dist/output.d.ts CHANGED
@@ -1,6 +1,15 @@
1
+ export type TableFlags = {
2
+ json?: boolean | string | number;
3
+ } & Record<string, unknown>;
1
4
  export declare function success(message: string): void;
2
5
  export declare function error(message: string): never;
3
6
  export declare function info(message: string): void;
4
7
  export declare function banner(message: string): void;
5
8
  export declare function printJson(data: unknown): void;
6
- export declare function printTable(rows: Record<string, unknown>[]): void;
9
+ export interface PrintTableOptions {
10
+ /** Pass `flags` so `--json` (any truthy form) routes to JSON output. */
11
+ flags?: TableFlags;
12
+ /** Hint shown when the table is empty (instead of "No data found."). */
13
+ empty?: string;
14
+ }
15
+ export declare function printTable(rows: Record<string, unknown>[], opts?: PrintTableOptions): void;
package/dist/output.js CHANGED
@@ -15,19 +15,17 @@ export function banner(message) {
15
15
  export function printJson(data) {
16
16
  console.log(JSON.stringify(data, null, 2));
17
17
  }
18
- export function printTable(rows) {
19
- if (process.argv.includes('--json')) {
18
+ export function printTable(rows, opts = {}) {
19
+ if (opts.flags && opts.flags.json) {
20
20
  printJson(rows);
21
21
  return;
22
22
  }
23
23
  if (rows.length === 0) {
24
- console.log("No data found.");
24
+ console.log(opts.empty ?? 'No data found.');
25
25
  return;
26
26
  }
27
27
  const columns = Object.keys(rows[0]);
28
- const colWidths = columns.map(col => {
29
- return Math.max(col.length, ...rows.map(row => String(row[col] ?? '').length));
30
- });
28
+ const colWidths = columns.map(col => Math.max(col.length, ...rows.map(row => String(row[col] ?? '').length)));
31
29
  const printRow = (row) => {
32
30
  console.log(row.map((cell, i) => cell.padEnd(colWidths[i] + 2)).join(''));
33
31
  };
@@ -0,0 +1,45 @@
1
+ ---
2
+ # my-email-api
3
+
4
+ Send transactional email and run drip campaigns from mailboxes on your own registered domains. Includes AI template generation, warmup, and inbox/outbox reading.
5
+
6
+ ## What it does
7
+
8
+ - Create mailboxes on your registered domains
9
+ - Send transactional emails (one-shot or templated)
10
+ - Read inbox, outbox, sent history, and per-message status
11
+ - Generate HTML email templates with AI from a prompt
12
+ - Run paced drip campaigns against uploaded contact lists
13
+ - Manage IP/domain warmup for sender reputation
14
+
15
+ ## Quickstart
16
+
17
+ ```bash
18
+ # Create a mailbox + activate sending
19
+ myapi email mailbox create --domain yourdomain.com --username hello
20
+ myapi email mailbox activate-sending --address hello@yourdomain.com
21
+
22
+ # Send
23
+ myapi email message send \
24
+ --from hello@yourdomain.com \
25
+ --to recipient@example.com \
26
+ --subject "Hi" \
27
+ --body "Test"
28
+ ```
29
+
30
+ ## Authentication
31
+
32
+ ```bash
33
+ export MYAPI_KEY=mak_...
34
+ ```
35
+
36
+ Requires:
37
+ - An `api_key` from **myapihq**
38
+ - A registered domain via **mydomainapi**, assigned to your org
39
+ - Default `org_id` (for templates/campaigns) — set with `myapi auth config set-org <id>`
40
+
41
+ ## Documentation
42
+
43
+ Full command reference and flow diagrams: see `SKILL.md`.
44
+
45
+ Run `myapi email --help` for inline reference.
@@ -0,0 +1,106 @@
1
+ ---
2
+ name: my-email-api
3
+ description: >
4
+ Send transactional and bulk email from your own domain. Create mailboxes, send/receive messages, generate AI templates, run drip campaigns, and manage warmup.
5
+ ---
6
+
7
+ # MyEmailAPI
8
+
9
+ Account-scoped email infrastructure tied to your registered domains. Mailboxes belong to domains; sending and receiving work without per-org plumbing. Templates and campaigns are org-scoped (one campaign belongs to one org).
10
+
11
+ ## How It Fits Together
12
+
13
+ - Requires `api_key` from **myapihq** and a registered domain via **mydomainapi**.
14
+ - Mailboxes live on a domain (e.g. `hello@yourdomain.com`).
15
+ - Sending must be activated per-mailbox (`mailbox activate-sending`) before transactional sends or campaigns.
16
+ - Templates and campaigns require `org_id` (set a default with `myapi auth config set-org`).
17
+
18
+ ## Quick Start
19
+
20
+ ```bash
21
+ # 1. Create a mailbox on your registered domain
22
+ myapi email mailbox create --domain yourdomain.com --username hello --display-name "Hello"
23
+
24
+ # 2. Activate sending (required before send/campaign)
25
+ myapi email mailbox activate-sending --address hello@yourdomain.com
26
+
27
+ # 3. Send a transactional email
28
+ myapi email message send \
29
+ --from hello@yourdomain.com \
30
+ --to recipient@example.com \
31
+ --subject "Hi" \
32
+ --body "Test message"
33
+
34
+ # 4. Read inbox / outbox
35
+ myapi email message inbox hello@yourdomain.com
36
+ myapi email message outbox hello@yourdomain.com
37
+ ```
38
+
39
+ ## Command Map
40
+
41
+ | Namespace | Subcommands | Purpose |
42
+ |---|---|---|
43
+ | `email mailbox` | `create`, `list`, `activate-sending` | Create and manage mailboxes on your domains |
44
+ | `email message` | `send`, `status`, `sent`, `inbox`, `outbox`, `get` | Transactional send + read |
45
+ | `email warmup` | `start`, `stats`, `pause`, `resume`, `stop` | IP/domain warmup for sending reputation |
46
+ | `email template` | `generate`, `list`, `edit`, `send-test`, `delete` | AI-generated HTML templates (org-scoped) |
47
+ | `email campaign` | `create`, `list`, `get`, `update`, `upload-contacts`, `start`, `pause`, `resume`, `stats` | Drip campaigns (org-scoped) |
48
+
49
+ ## Templates (AI-generated)
50
+
51
+ ```bash
52
+ # Generate a template — polls the LLM job (up to 90s)
53
+ myapi email template generate \
54
+ --prompt "A welcome email with our brand colors and a CTA to /onboarding" \
55
+ --name welcome-v1
56
+
57
+ # List, edit, delete
58
+ myapi email template list
59
+ myapi email template edit <id> --prompt "Make the CTA larger and red"
60
+ myapi email template send-test <id> --to me@yourdomain.com
61
+ myapi email template delete <id>
62
+ ```
63
+
64
+ ## Campaigns
65
+
66
+ Campaigns send a template to a contact list at a per-day rate.
67
+
68
+ ```bash
69
+ # 1. Create a campaign linked to an existing template + sender mailbox
70
+ myapi email campaign create \
71
+ --name "Welcome series" \
72
+ --template-id <template_id> \
73
+ --from hello@yourdomain.com \
74
+ --per-day 50
75
+
76
+ # 2. Upload contacts
77
+ myapi email campaign upload-contacts <campaign_id> \
78
+ --emails "alice@example.com,bob@example.com"
79
+
80
+ # 3. Start (only after upload-contacts has finished processing)
81
+ myapi email campaign start <campaign_id>
82
+
83
+ # 4. Monitor
84
+ myapi email campaign stats <campaign_id>
85
+ myapi email campaign pause <campaign_id>
86
+ myapi email campaign resume <campaign_id>
87
+ ```
88
+
89
+ ## Warmup
90
+
91
+ Warmup gradually ramps mailbox sending to build reputation with inbox providers. Recommended before high-volume campaigns.
92
+
93
+ ```bash
94
+ myapi email warmup start --address hello@yourdomain.com
95
+ myapi email warmup stats --address hello@yourdomain.com
96
+ myapi email warmup pause --address hello@yourdomain.com
97
+ ```
98
+
99
+ ## Notes
100
+
101
+ - A single mailbox is uniquely identified by its address (`username@domain`).
102
+ - Sending must be activated explicitly — newly-created mailboxes can receive but not send.
103
+ - Templates and campaigns are org-scoped. Set a default org once: `myapi auth config set-org <id>`.
104
+ - Domain assignment to org is enforced at unassign time: an active or paused campaign sending from a mailbox on the domain will block `domain unassign` with `DOMAIN_IN_USE`.
105
+
106
+ Run `myapi email --help` or `myapi email <namespace> --help` for full flag reference.
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "my-email-api",
3
+ "description": "Send transactional and bulk email from your own domain. Mailboxes, AI templates, drip campaigns, and warmup.",
4
+ "version": "1.0.0",
5
+ "published": true
6
+ }
File without changes
File without changes
File without changes
@@ -0,0 +1,40 @@
1
+ ---
2
+ # my-webhook-api
3
+
4
+ Inbound HTTP endpoints that receive POSTs from third-party services and store every delivery for inspection. Pair with my-workflow-api to react to incoming events.
5
+
6
+ ## What it does
7
+
8
+ - Create per-org webhook endpoints with unique inbound URLs
9
+ - Store every inbound delivery (body + headers)
10
+ - Inspect individual deliveries by id
11
+ - Bind webhooks to workflows for event-driven actions
12
+
13
+ ## Quickstart
14
+
15
+ ```bash
16
+ # Create an endpoint
17
+ myapi webhook create --name "stripe-events"
18
+ # → prints: Inbound URL: https://api.myapihq.com/webhook/in/<slug>
19
+
20
+ # POST to it from anywhere
21
+ curl -X POST <inbound-url> -d '{"event":"x"}'
22
+
23
+ # List + inspect
24
+ myapi webhook list
25
+ myapi webhook delivery <delivery_id>
26
+ ```
27
+
28
+ ## Authentication
29
+
30
+ ```bash
31
+ export MYAPI_KEY=mak_...
32
+ ```
33
+
34
+ Requires `api_key` and `org_id` from **myapihq**.
35
+
36
+ ## Documentation
37
+
38
+ Full command reference and workflow integration: see `SKILL.md`.
39
+
40
+ Run `myapi webhook --help` for inline reference.
@@ -0,0 +1,65 @@
1
+ ---
2
+ name: my-webhook-api
3
+ description: >
4
+ Inbound webhook endpoints. Receive HTTP POSTs from third parties (forms, Stripe, GitHub, etc.) and either inspect the deliveries directly or wire them to a workflow.
5
+ ---
6
+
7
+ # MyWebhookAPI
8
+
9
+ Per-org HTTP endpoints that accept inbound POSTs and durably store every delivery. A webhook on its own is a passive receiver — pair it with **myworkflowapi** to react to incoming events (send email, post to Slack, etc.).
10
+
11
+ ## How It Fits Together
12
+
13
+ - Requires `api_key` and `org_id` from **myapihq**.
14
+ - Each endpoint has a unique inbound URL (returned at create time).
15
+ - Deliveries are stored verbatim — full request body + headers — for inspection.
16
+ - `myworkflowapi` workflows bind to a webhook endpoint via its `id`.
17
+
18
+ ## Quick Start
19
+
20
+ ```bash
21
+ # 1. Create a webhook endpoint
22
+ myapi webhook create --name "stripe-events" --description "Stripe payment events"
23
+ # → prints: Inbound URL: https://api.myapihq.com/webhook/in/<slug>
24
+
25
+ # 2. POST to the inbound URL from your service
26
+ curl -X POST https://api.myapihq.com/webhook/in/<slug> \
27
+ -H "Content-Type: application/json" \
28
+ -d '{"event":"payment.succeeded"}'
29
+
30
+ # 3. List endpoints / inspect a delivery
31
+ myapi webhook list
32
+ myapi webhook delivery <delivery_id>
33
+ ```
34
+
35
+ ## All Commands
36
+
37
+ | Command | What it does |
38
+ |---|---|
39
+ | `myapi webhook create` | Create an endpoint, returns id + inbound URL |
40
+ | `myapi webhook list` | List all endpoints in your org |
41
+ | `myapi webhook delete <id>` | Delete an endpoint and all its deliveries |
42
+ | `myapi webhook delivery <delivery_id>` | Get the full payload + headers for one delivery |
43
+
44
+ ## Wiring to a Workflow
45
+
46
+ Webhooks become useful when a workflow fires on each inbound POST. See **myworkflowapi**:
47
+
48
+ ```bash
49
+ # Create the webhook
50
+ WID=$(myapi webhook create --name "leads" --json | jq -r .id)
51
+
52
+ # Bind a workflow that sends an email each time the webhook fires
53
+ myapi workflow create \
54
+ --name "Notify on lead" \
55
+ --endpoint-id $WID \
56
+ --steps '[{"type":"send_email","to":"sales@yourdomain.com","subject":"New lead"}]'
57
+ ```
58
+
59
+ ## Notes
60
+
61
+ - The inbound URL is public — anyone with the URL can POST to it. Treat the slug as a secret.
62
+ - Deliveries are kept indefinitely. Delete the endpoint to purge them.
63
+ - Failed workflow runs do not affect the delivery record — the inbound POST is always saved.
64
+
65
+ Run `myapi webhook --help` for full flag reference.
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "my-webhook-api",
3
+ "description": "Receive inbound HTTP webhooks. Per-org endpoints with full delivery history.",
4
+ "version": "1.0.0",
5
+ "published": true
6
+ }
File without changes
File without changes
File without changes
@@ -0,0 +1,37 @@
1
+ ---
2
+ # my-workflow-api
3
+
4
+ Run a chain of actions (send email, post to Slack, call an HTTP endpoint) every time an inbound webhook fires. No backend required.
5
+
6
+ ## What it does
7
+
8
+ - Bind ordered step chains to webhook endpoints
9
+ - Steps can: send transactional email, hit Slack, call any HTTP URL
10
+ - Template values from the inbound webhook payload (`{{ payload.field }}`)
11
+ - Per-run status tracking (attempt, error, started/finished timestamps)
12
+ - Enable/disable without losing config
13
+
14
+ ## Quickstart
15
+
16
+ ```bash
17
+ # Create a webhook + workflow that sends Slack on every POST
18
+ WID=$(myapi webhook create --name "leads" --json | jq -r .id)
19
+ myapi workflow create \
20
+ --name "Slack on lead" \
21
+ --endpoint-id $WID \
22
+ --steps '[{"type":"slack","webhook_url":"..."}]'
23
+ ```
24
+
25
+ ## Authentication
26
+
27
+ ```bash
28
+ export MYAPI_KEY=mak_...
29
+ ```
30
+
31
+ Requires `api_key` + `org_id` from **myapihq**, and a webhook endpoint id from **mywebhookapi**.
32
+
33
+ ## Documentation
34
+
35
+ Full command reference, step types, and templating: see `SKILL.md`.
36
+
37
+ Run `myapi workflow --help` for inline reference.