@myapihq/cli 1.3.12 → 2.0.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 (48) hide show
  1. package/dist/commands/account.d.ts +7 -1
  2. package/dist/commands/account.js +356 -18
  3. package/dist/commands/authproduct.d.ts +7 -0
  4. package/dist/commands/authproduct.js +286 -0
  5. package/dist/commands/billing.js +1 -1
  6. package/dist/commands/config.js +1 -1
  7. package/dist/commands/container.d.ts +1 -0
  8. package/dist/commands/container.js +115 -11
  9. package/dist/commands/domain.js +2 -2
  10. package/dist/commands/email/index.js +0 -13
  11. package/dist/commands/fn.d.ts +1 -0
  12. package/dist/commands/fn.js +64 -12
  13. package/dist/commands/keys.js +3 -3
  14. package/dist/commands/queue.d.ts +1 -0
  15. package/dist/commands/queue.js +10 -0
  16. package/dist/commands/setup.js +8 -8
  17. package/dist/commands/status.d.ts +1 -1
  18. package/dist/commands/status.js +11 -27
  19. package/dist/commands/storage.js +3 -1
  20. package/dist/commands/workflow.js +21 -6
  21. package/dist/completion.js +5 -4
  22. package/dist/config.js +1 -1
  23. package/dist/exposes.test.js +1 -2
  24. package/dist/index.js +31 -28
  25. package/dist/registrant.js +5 -5
  26. package/dist/sdk-queue.test.js +3 -2
  27. package/dist/skills/my-api-hq/SKILL.md +15 -12
  28. package/dist/skills/my-auth-api/README.md +33 -0
  29. package/dist/skills/my-auth-api/SKILL.md +112 -0
  30. package/dist/skills/my-auth-api/claude/.claude-plugin/plugin.json +6 -0
  31. package/dist/skills/my-auth-api/openapi/.gitkeep +0 -0
  32. package/dist/skills/my-crm-api/SKILL.md +1 -1
  33. package/dist/skills/my-domain-api/SKILL.md +4 -4
  34. package/dist/skills/my-email-api/README.md +1 -1
  35. package/dist/skills/my-email-api/SKILL.md +7 -18
  36. package/dist/skills/my-email-api/claude/.claude-plugin/plugin.json +1 -1
  37. package/dist/skills/my-email-verify-api/SKILL.md +1 -1
  38. package/dist/skills/my-email-verify-api/claude/.claude-plugin/plugin.json +1 -1
  39. package/dist/skills/my-git-api/README.md +43 -0
  40. package/dist/skills/my-git-api/SKILL.md +115 -0
  41. package/dist/skills/my-git-api/claude/.claude-plugin/plugin.json +6 -0
  42. package/dist/skills/my-git-api/openapi/.gitkeep +0 -0
  43. package/dist/skills/my-llm-api/claude/.claude-plugin/plugin.json +1 -1
  44. package/package.json +5 -4
  45. package/dist/commands/auth.d.ts +0 -11
  46. package/dist/commands/auth.js +0 -345
  47. package/dist/commands/email/campaign.d.ts +0 -4
  48. package/dist/commands/email/campaign.js +0 -200
package/dist/index.js CHANGED
@@ -21,7 +21,7 @@ import * as imageCmd from './commands/image.js';
21
21
  import * as storageCmd from './commands/storage.js';
22
22
  import * as pixelCmd from './commands/pixel.js';
23
23
  import * as urlCmd from './commands/url.js';
24
- import * as authCmd from './commands/auth.js';
24
+ import * as authProductCmd from './commands/authproduct.js';
25
25
  import * as configCmd from './commands/config.js';
26
26
  import * as statusCmd from './commands/status.js';
27
27
  import * as peopleCmd from './commands/people.js';
@@ -42,7 +42,7 @@ import * as doctorCmd from './commands/doctor.js';
42
42
  // one command means editing one file (its SCHEMA), not a global allowlist.
43
43
  const COMBINED_SCHEMA = {
44
44
  ...accountCmd.SCHEMA,
45
- ...authCmd.SCHEMA,
45
+ ...authProductCmd.SCHEMA,
46
46
  ...billingCmd.SCHEMA,
47
47
  ...configCmd.SCHEMA,
48
48
  ...domainCmd.SCHEMA,
@@ -153,7 +153,7 @@ async function main() {
153
153
  if (args.length === 0) {
154
154
  const config = loadConfig();
155
155
  if (!config?.api_key) {
156
- info('No account found. Run: myapi auth setup');
156
+ info('No account found. Run: myapi account setup');
157
157
  info('');
158
158
  }
159
159
  printHelp();
@@ -164,7 +164,9 @@ async function main() {
164
164
  try {
165
165
  switch (command) {
166
166
  case 'auth':
167
- await dispatchAuth(subcommand, restArgs, flags);
167
+ // `auth` is the end-user auth product (my-auth-api). Operator/account
168
+ // commands live under `myapi account`.
169
+ await authProductCmd.run(subcommand, restArgs, flags);
168
170
  break;
169
171
  case 'update':
170
172
  await updateCmd.update(flags);
@@ -173,7 +175,7 @@ async function main() {
173
175
  await orgCmd.run(subcommand, restArgs, flags);
174
176
  break;
175
177
  case 'account':
176
- await accountCmd.run(subcommand, restArgs, flags);
178
+ await dispatchAccount(subcommand, restArgs, flags);
177
179
  break;
178
180
  case 'billing':
179
181
  await billingCmd.run(subcommand, restArgs, flags);
@@ -249,7 +251,7 @@ async function main() {
249
251
  await setupCmd.setup(flags);
250
252
  break;
251
253
  case 'whoami':
252
- await authCmd.whoami(flags);
254
+ await accountCmd.whoami(flags);
253
255
  break;
254
256
  case 'status':
255
257
  await statusCmd.run(subcommand, restArgs, flags);
@@ -262,7 +264,7 @@ async function main() {
262
264
  break;
263
265
  case 'install-skills':
264
266
  if (flags.help) {
265
- info(authCmd.INSTALL_SKILLS_HELP);
267
+ info(accountCmd.INSTALL_SKILLS_HELP);
266
268
  break;
267
269
  }
268
270
  await setupCmd.installSkills();
@@ -292,10 +294,10 @@ async function main() {
292
294
  catch (err) {
293
295
  if (err instanceof MyApiError) {
294
296
  if (err.status === 401)
295
- error('Invalid API key. Run: myapi auth setup');
297
+ error('Invalid API key. Run: myapi account setup');
296
298
  else if (err.status === 402) {
297
299
  if (err.code === 'REGISTRATION_REQUIRED' || err.code === 'UPGRADE_REQUIRED')
298
- error('A verified email is required. Run: myapi auth link');
300
+ error('A verified email is required. Run: myapi account link');
299
301
  else if (err.code === 'NO_PAYMENT_METHOD')
300
302
  error('No payment method on file. Run: myapi billing setup');
301
303
  else {
@@ -304,7 +306,7 @@ async function main() {
304
306
  // free credit and opens the paid surface.
305
307
  const cfg = loadConfig();
306
308
  if (cfg?.is_anonymous) {
307
- error('Insufficient balance. Anonymous accounts have no free credit — link an email to unlock $5: myapi auth link <email>');
309
+ error('Insufficient balance. Anonymous accounts have no free credit — link an email to unlock $5: myapi account link <email>');
308
310
  }
309
311
  error('Insufficient balance. Run: myapi billing topup <amount>');
310
312
  }
@@ -320,33 +322,34 @@ async function main() {
320
322
  }
321
323
  }
322
324
  }
323
- async function dispatchAuth(subcommand, restArgs, flags) {
325
+ async function dispatchAccount(subcommand, restArgs, flags) {
324
326
  if (!subcommand || (flags.help && !subcommand)) {
325
- info(authCmd.HELP);
327
+ info(accountCmd.HELP);
326
328
  return;
327
329
  }
328
330
  switch (subcommand) {
331
+ case 'mailing-address': return accountCmd.run('mailing-address', restArgs, flags);
329
332
  case 'setup': return setupCmd.setup(flags);
330
333
  case 'import-key': return setupCmd.importKey(restArgs[0], flags);
331
- case 'whoami': return authCmd.whoami(flags);
332
- case 'link': return authCmd.link(flags, restArgs[0]);
333
- case 'switch': return authCmd.switchCmd(flags, restArgs[0]);
334
+ case 'whoami': return accountCmd.whoami(flags);
335
+ case 'link': return accountCmd.link(flags, restArgs[0]);
336
+ case 'switch': return accountCmd.switchCmd(flags, restArgs[0]);
334
337
  case 'install-skills':
335
338
  // DEPRECATED: install-skills is now a top-level command. The auth subcommand
336
339
  // form is kept for one minor version with a warning, then will be removed.
337
- banner('› Note: `myapi auth install-skills` is deprecated. Use `myapi install-skills` instead.');
340
+ banner('› Note: `myapi account install-skills` is deprecated. Use `myapi install-skills` instead.');
338
341
  if (flags.help) {
339
- info(authCmd.INSTALL_SKILLS_HELP);
342
+ info(accountCmd.INSTALL_SKILLS_HELP);
340
343
  return;
341
344
  }
342
345
  await setupCmd.installSkills();
343
346
  success('› Skills installed.');
344
347
  return;
345
348
  case 'config': return configCmd.run(restArgs[0], restArgs.slice(1), flags);
346
- case 'registrant': return authCmd.registrant(restArgs[0], flags);
349
+ case 'registrant': return accountCmd.registrant(restArgs[0], flags);
347
350
  case 'api-keys':
348
351
  case 'keys': return keysCmd.runApiKeys(restArgs[0], restArgs.slice(1), flags);
349
- default: info('Unknown subcommand. Run: myapi auth --help');
352
+ default: info('Unknown subcommand. Run: myapi account --help');
350
353
  }
351
354
  }
352
355
  const HELP_TARGETS = {
@@ -372,7 +375,7 @@ const HELP_TARGETS = {
372
375
  task: f => taskCmd.run(undefined, [], f),
373
376
  doctor: f => doctorCmd.run(undefined, [], f),
374
377
  org: f => orgCmd.run(undefined, [], f),
375
- account: f => accountCmd.run(undefined, [], f),
378
+ account: f => dispatchAccount(undefined, [], f),
376
379
  billing: f => billingCmd.run(undefined, [], f),
377
380
  keys: f => keysCmd.run(undefined, [], f),
378
381
  config: f => configCmd.run(undefined, [], f),
@@ -383,7 +386,7 @@ async function dispatchHelp(target) {
383
386
  return;
384
387
  }
385
388
  if (target === 'auth') {
386
- info(authCmd.HELP);
389
+ info(authProductCmd.HELP);
387
390
  return;
388
391
  }
389
392
  const handler = HELP_TARGETS[target];
@@ -398,16 +401,16 @@ function printHelp() {
398
401
  ? `Quick start:
399
402
  echo '<h1>Hello!</h1>' | myapi funnel push /`
400
403
  : `Quick start:
401
- myapi auth setup --help`;
404
+ myapi account setup --help`;
402
405
  info(`myapi - MyAPI command-line interface
403
406
 
404
407
  Usage: myapi <command> [subcommand] [args]
405
408
  myapi --version
406
409
 
407
410
  Commands:
408
- account Account-scoped settings (mailing address)
411
+ account Your MyAPI account · setup · whoami · link · keys · config · mailing-address
409
412
  audience Save filter snapshots as named audiences (people or companies)
410
- auth Manage account · setup · whoami · link
413
+ auth Auth for your app's end users OIDC tenant, clients, usage, custom domain
411
414
  billing Check balance and manage billing
412
415
  company Search the company database (filter by industry, size, country, ...)
413
416
  container Run containers — services, workers, and scheduled jobs
@@ -436,10 +439,10 @@ Commands:
436
439
  workflow Run actions (send email, post to Slack) when a webhook fires
437
440
 
438
441
  Aliases:
439
- config → myapi auth config
440
- keys → myapi auth api-keys
441
- setup → myapi auth setup
442
- whoami → myapi auth whoami
442
+ config → myapi account config
443
+ keys → myapi account api-keys
444
+ setup → myapi account setup
445
+ whoami → myapi account whoami
443
446
 
444
447
  Run "myapi <command> --help" for subcommand help.
445
448
 
@@ -4,7 +4,7 @@
4
4
  // Sources, in priority order:
5
5
  // 1. --registrant-json '<inline JSON>'
6
6
  // 2. Per-field flags (--registrant-name, --registrant-email, …)
7
- // 3. Stored on the active account (set via `myapi auth registrant set`)
7
+ // 3. Stored on the active account (set via `myapi account registrant set`)
8
8
  // 4. Interactive TTY prompt — offers to save to config
9
9
  // 5. Hard error in non-interactive contexts
10
10
  //
@@ -127,7 +127,7 @@ export async function resolveRegistrantForRegister(flags, config) {
127
127
  const save = await confirm(' Save as your default for future domain registrations? (Y/n) ', true);
128
128
  if (save) {
129
129
  saveConfig({ ...config, registrant: r });
130
- console.error(' ✓ Saved. Manage with: myapi auth registrant <get|clear>');
130
+ console.error(' ✓ Saved. Manage with: myapi account registrant <get|clear>');
131
131
  }
132
132
  }
133
133
  return r;
@@ -135,18 +135,18 @@ export async function resolveRegistrantForRegister(flags, config) {
135
135
  // 5: hard error.
136
136
  error(`Missing registrant field(s): ${missing.join(', ')}\n\n` +
137
137
  `Provide them via one of:\n` +
138
- ` myapi auth registrant set (one-time interactive setup)\n` +
138
+ ` myapi account registrant set (one-time interactive setup)\n` +
139
139
  ` --registrant-json '{"name":"...","email":"...","phone":"...","street":"...","city":"...","postal_code":"...","country_code":"DE"}'\n` +
140
140
  ` Per-field flags: --registrant-name, --registrant-email, --registrant-phone,\n` +
141
141
  ` --registrant-street, --registrant-city, --registrant-postal-code,\n` +
142
142
  ` --registrant-country, --registrant-state (US/CA only)`);
143
143
  }
144
- // ── Used by `myapi auth registrant set` ────────────────────────────────────
144
+ // ── Used by `myapi account registrant set` ────────────────────────────────────
145
145
  // Public so the auth subcommand can drive the same prompt sequence without
146
146
  // going through the register flow.
147
147
  export async function promptAndSave(config, prefill = {}) {
148
148
  if (isNonInteractive()) {
149
- error('myapi auth registrant set requires a TTY. Use --json \'{...}\' instead.');
149
+ error('myapi account registrant set requires a TTY. Use --json \'{...}\' instead.');
150
150
  }
151
151
  console.error('› Setting your WHOIS registrant info (used at every domain register call):');
152
152
  const r = await promptRegistrant(prefill);
@@ -78,9 +78,10 @@ describe('queue jobs', () => {
78
78
  });
79
79
  });
80
80
  describe('queue.EXPOSES', () => {
81
- it('covers all 6 queue endpoints', () => {
82
- expect(queue.EXPOSES).toHaveLength(6);
81
+ it('covers all 7 queue endpoints', () => {
82
+ expect(queue.EXPOSES).toHaveLength(7);
83
83
  expect(queue.EXPOSES).toContain('POST /queue/orgs/{org_id}/queues/{name}/jobs');
84
84
  expect(queue.EXPOSES).toContain('GET /queue/orgs/{org_id}/jobs/{id}');
85
+ expect(queue.EXPOSES).toContain('DELETE /queue/orgs/{org_id}/queues/{name}');
85
86
  });
86
87
  });
@@ -13,7 +13,7 @@ The root service. It manages accounts, API keys, organizations, and billing. No
13
13
 
14
14
  ## Capabilities
15
15
  <!-- llm:start -->
16
- MyApiHQ is the platform's foundation. Every other service (domain, funnel, email, image, storage, pixel, webhook, workflow, url) requires both an `api_key` and (for org-scoped resources) an `org_id` minted here. Setup is one command — `myapi auth setup` — which provisions an account, generates an api_key, creates a default org, and stores everything in `~/.myapi/config.json`. Subsequent commands pick up those defaults automatically.
16
+ MyApiHQ is the platform's foundation. Every other service (domain, funnel, email, image, storage, pixel, webhook, workflow, url) requires both an `api_key` and (for org-scoped resources) an `org_id` minted here. Setup is one command — `myapi account setup` — which provisions an account, generates an api_key, creates a default org, and stores everything in `~/.myapi/config.json`. Subsequent commands pick up those defaults automatically.
17
17
 
18
18
  ```
19
19
  myapihq ──► org_id + api_key
@@ -27,30 +27,33 @@ myapihq ──► org_id + api_key
27
27
 
28
28
  Two tiers, chosen at setup time:
29
29
 
30
- - **Anonymous** (`myapi auth setup --anonymous`): zero-friction account creation. **Starts with $0 credit.** Good for catalog browsing, reading help, inspecting schemas — nothing that costs upstream money. The agent-onboarding path: provisions an account in one call, no email needed.
31
- - **Registered** (verified email via `myapi auth link <email>`): unlocks $5 free credit and the paid surface (LLM, image, email, domain register, etc.). Required for `myapi billing setup` and anything that hits Stripe.
30
+ - **Anonymous** (`myapi account setup --anonymous`): zero-friction account creation. **Starts with $0 credit.** Good for catalog browsing, reading help, inspecting schemas — nothing that costs upstream money. The agent-onboarding path: provisions an account in one call, no email needed.
31
+ - **Registered** (verified email via `myapi account link <email>`): unlocks $5 free credit and the paid surface (LLM, image, email, domain register, etc.). Required for `myapi billing setup` and anything that hits Stripe.
32
32
 
33
- An anonymous account can upgrade at any time via `myapi auth link <email>` — the credit grants on successful verification. Anonymous accounts that need paid actions hit a friendly `INSUFFICIENT_BALANCE` or `REGISTRATION_REQUIRED` error pointing at `myapi auth link`.
33
+ An anonymous account can upgrade at any time via `myapi account link <email>` — the credit grants on successful verification. Anonymous accounts that need paid actions hit a friendly `INSUFFICIENT_BALANCE` or `REGISTRATION_REQUIRED` error pointing at `myapi account link`.
34
34
  <!-- llm:end -->
35
35
 
36
36
  ## Commands
37
37
  <!-- generated:start -->
38
38
  | Command | What it does |
39
39
  |---|---|
40
- | `myapi auth setup` | Interactive setup: creates account, generates api_key, sets defaults |
41
- | `myapi auth whoami` | Show current account, default org/funnel, balance, free-tier usage |
42
- | `myapi auth link [email]` | Upgrade anonymous account to registered (or add a second session) |
43
- | `myapi auth switch [index]` | Switch active account |
40
+ | `myapi account setup` | Interactive setup: creates account, generates api_key, sets defaults |
41
+ | `myapi account whoami` | Show current account, default org/funnel, balance, free-tier usage |
42
+ | `myapi account link [email]` | Upgrade anonymous account to registered (or add a second session) |
43
+ | `myapi account switch [index]` | Switch active account |
44
44
  | `myapi org list` | List all orgs (`*` marks the default) |
45
45
  | `myapi org create --name "..."` | Create a new org (`--yes` auto-sets as default) |
46
46
  | `myapi org get [id]` | Inspect one org (defaults to current default) |
47
47
  | `myapi org update [id]` | Update fields (name, tagline, description, business-sector, logo-url) |
48
48
  | `myapi org delete <id>` | Delete an org and cascade |
49
49
  | `myapi org sync-brand <domain>` | Scrape a live site and auto-fill brand info |
50
- | `myapi keys list / create / revoke <id>` | Manage API keys (alias `myapi auth api-keys`) |
50
+ | `myapi keys list / create / revoke <id>` | Manage API keys (alias `myapi account api-keys`) |
51
51
  | `myapi billing balance` | Check balance |
52
52
  | `myapi billing topup <amount>` | Top up by dollar amount |
53
53
  | `myapi billing history` | Recent transactions |
54
+ | `myapi billing usage [--period month|30d]` | Spend rolled up by service (this month, or trailing 30d) |
55
+ | `myapi billing spend-cap [<amount> | clear] [--period month|day]` | Set/show/clear the account-level spend ceiling (IAM Layer 2) |
56
+ | `myapi account mailing-address ["<address>"]` | Get or set the account's CAN-SPAM mailing address (required for email send) |
54
57
  | `myapi config set-org <id>` / `set-funnel <id>` / `set-domain <name>` | Set CLI defaults |
55
58
  | `myapi install-skills` | Install agent skill files into ~/.claude/, ~/.gemini/, ~/.cursor/ |
56
59
  <!-- generated:end -->
@@ -59,11 +62,11 @@ An anonymous account can upgrade at any time via `myapi auth link <email>` — t
59
62
  <!-- llm:start -->
60
63
  ```bash
61
64
  # Cold start: provision account + default org
62
- myapi auth setup
65
+ myapi account setup
63
66
  myapi org create "Acme" --yes
64
67
 
65
68
  # Day-to-day
66
- myapi auth whoami # confirm what's active
69
+ myapi account whoami # confirm what's active
67
70
  myapi billing balance # before doing anything that costs credits
68
71
  myapi billing topup 20 # add $20
69
72
 
@@ -71,7 +74,7 @@ myapi billing topup 20 # add $20
71
74
  myapi org sync-brand acme.com
72
75
 
73
76
  # Switch between multiple accounts
74
- myapi auth switch 2
77
+ myapi account switch 2
75
78
  ```
76
79
 
77
80
  If any service returns `402`, run `myapi billing balance` and top up before retrying.
@@ -0,0 +1,33 @@
1
+ ---
2
+ # my-auth-api
3
+
4
+ Add authentication to apps you build on MyAPI — a managed OIDC identity provider
5
+ for your app's **end users** (à la Kinde/Auth0). Not your MyAPI account; that's
6
+ `myapi account`.
7
+
8
+ ## What it does
9
+
10
+ - One OIDC **auth tenant** per org (issuer + JWKS + hosted login page)
11
+ - Register **OIDC clients** (your apps): `spa` (public) or `web` (confidential)
12
+ - Managed **Google sign-in** — no customer GCP account
13
+ - RS256 tokens, verified locally against the tenant JWKS
14
+ - Standard OIDC endpoints (`/authorize`, `/token`, `/userinfo`, `/jwks`,
15
+ `/.well-known/openid-configuration`) consumed by your app + the JS SDK
16
+
17
+ ## Quickstart
18
+
19
+ ```bash
20
+ # Provision the tenant, then register an app
21
+ myapi auth tenant create
22
+ myapi auth client create --name "My App" --type spa \
23
+ --redirect https://app.example.com/callback
24
+
25
+ myapi auth tenant # issuer + hosted login URL
26
+ myapi auth client list
27
+ ```
28
+
29
+ Point any OIDC client library at the tenant `issuer`; verify access tokens
30
+ against `<issuer>/jwks`.
31
+
32
+ > Sign-in methods: managed Google, email/password (with verification + reset),
33
+ > and magic links — pick per tenant with `auth tenant create --connections`.
@@ -0,0 +1,112 @@
1
+ ---
2
+ name: my-auth-api
3
+ version: 1.0.0
4
+ description: >
5
+ Add authentication to apps you build on MyAPI — a managed OIDC identity provider for your app's END USERS (à la Kinde/Auth0). One auth tenant per org; register OIDC clients; sign users in with managed Google or the hosted login page; verify RS256 tokens against the tenant JWKS.
6
+ triggers: [auth, authentication, login, sign-in, oidc, oauth, jwt, jwks, sso, google sign-in, user accounts, identity provider, kinde, auth0, clerk]
7
+ checksum: sha256-pending
8
+ ---
9
+
10
+ # MyAuthAPI
11
+
12
+ Authentication for the **end users of apps you build on MyAPI** — not your MyAPI
13
+ account (that's `myapi account`). It's a managed multi-tenant **OIDC identity
14
+ provider**: each org gets one auth tenant, you register OIDC clients (your apps)
15
+ against it, and your users sign in via managed Google or the hosted login page.
16
+ Tokens are RS256, verified locally against the tenant's JWKS — no per-request
17
+ call back to MyAPI.
18
+
19
+ ## Capabilities
20
+ <!-- llm:start -->
21
+ Auth is the identity layer for apps an agent deploys (containers, funnels). It
22
+ closes the gap between "shipped an app" and "the app has real users with
23
+ accounts" — natively, on the same org/domain/bill, no third-party auth to wire.
24
+
25
+ **Mental model:** one **tenant** per org (your identity provider) → many
26
+ **clients** (your apps) registered against it → end users sign in and get
27
+ RS256 tokens your app verifies against the tenant **JWKS**.
28
+
29
+ The standard OIDC machine endpoints live under the tenant issuer and are
30
+ consumed by your app + the JS SDK, **not** the CLI:
31
+ `/.well-known/openid-configuration`, `/jwks`, `/authorize`, `/token`,
32
+ `/userinfo`. The CLI manages the two things you set up by hand: the tenant and
33
+ its clients.
34
+
35
+ - **Tenant** — `auth tenant create` provisions (idempotent) your org's OIDC
36
+ issuer + hosted login URL. `auth tenant` shows them.
37
+ - **Client** — `auth client create` registers an app. `type spa` is a public
38
+ client (no secret; for browser/SPA/mobile). `type web` is confidential and
39
+ returns a `client_secret` **once** — store it immediately. `--redirect` lists
40
+ allowed callback URIs (absolute https, or http://localhost for dev).
41
+ - **Usage** — `auth usage` shows monthly active users (auth is billed per MAU).
42
+ - **Custom domain** — `auth domain set --domain auth.acme.com` serves auth on
43
+ your own domain; it prints the DNS record, TLS provisions automatically, and
44
+ the domain becomes your issuer once active.
45
+
46
+ **Sign-in methods** are chosen per tenant via
47
+ `auth tenant create --connections google,password,magic` (default `google`):
48
+ **managed Google** (no customer GCP account), **email/password** (with
49
+ verification + password reset), and **magic links** (passwordless email). All
50
+ are served by the hosted login page. Verifying tokens, the authorize/token
51
+ dance, userinfo, and the password/magic/reset flows are handled by the hosted
52
+ page + standard OIDC — point any OIDC client library at the tenant issuer; the
53
+ CLI is only the management surface.
54
+ <!-- llm:end -->
55
+
56
+ ## Commands
57
+ <!-- generated:start -->
58
+ | Command | What it does |
59
+ |---|---|
60
+ | `myapi auth tenant` | Show your org's OIDC auth tenant (issuer + hosted login URL + sign-in methods) |
61
+ | `myapi auth tenant create` | Create/enable the tenant (`--connections google,password,magic`; `--theme <json>`) |
62
+ | `myapi auth client list` | List the OIDC clients (apps) registered to your tenant |
63
+ | `myapi auth client create` | Register an OIDC client (`--name`, `--type spa\|web`, `--redirect`) |
64
+ | `myapi auth usage` | Monthly active users (MAU) for the current period |
65
+ | `myapi auth domain` | Show/set/delete a custom auth domain (`set --domain auth.acme.com`) |
66
+ <!-- generated:end -->
67
+
68
+ ## Examples
69
+ <!-- llm:start -->
70
+ ```bash
71
+ # 1. Provision your org's auth tenant (one time)
72
+ myapi auth tenant create
73
+ # → issuer + login_url for the hosted login page
74
+
75
+ # 2. Register your app as an OIDC client
76
+ # SPA / browser app (public, no secret):
77
+ myapi auth client create --name "My SPA" --type spa \
78
+ --redirect https://app.example.com/callback
79
+
80
+ # Server-side / confidential app (secret returned ONCE):
81
+ myapi auth client create --name "My API" --type web \
82
+ --redirect https://app.example.com/auth/callback
83
+
84
+ # 3. Inspect
85
+ myapi auth tenant
86
+ myapi auth client list
87
+
88
+ # 4. In your app: point any OIDC client library at the tenant `issuer`.
89
+ # Verify access tokens locally against <issuer>/jwks (RS256) — no call back.
90
+ ```
91
+ <!-- llm:end -->
92
+
93
+ ## Tenant vs client
94
+
95
+ - **Tenant** = your identity provider (one per org). It owns the issuer, signing
96
+ keys (JWKS), and the hosted login page. Create it once.
97
+ - **Client** = one app authenticating against the tenant. Register one per app
98
+ (or per environment). `spa` = public, `web` = confidential (has a secret).
99
+
100
+ ## Operator auth is different
101
+
102
+ `myapi auth` is for **your app's users**. To manage **your own MyAPI account**
103
+ (login, API keys, billing config), use `myapi account` (`whoami`, `link`,
104
+ `api-keys`, `config`, …).
105
+
106
+ ## Notes
107
+
108
+ - The `client_secret` for `web` clients is shown **once** at creation and cannot
109
+ be retrieved later — store it immediately. SPA clients have no secret.
110
+ - Redirect URIs are matched exactly: absolute `https://…` (or
111
+ `http://localhost…` for local dev).
112
+ - `402` errors mean insufficient credits — run `myapi billing topup <amount>`.
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "my-auth-api",
3
+ "description": "Managed OIDC identity provider for the end users of apps built on MyAPI. Per-org auth tenant + OIDC clients, RS256/JWKS, hosted login, managed Google sign-in. A Kinde alternative.",
4
+ "version": "1.0.0",
5
+ "published": true
6
+ }
File without changes
@@ -45,7 +45,7 @@ Set automatically based on how the contact entered the CRM. Useful filter when y
45
45
  ```
46
46
  created | promoted | stage_changed
47
47
  email_sent | email_opened | email_clicked | email_replied
48
- pixel_visit | webhook_received
48
+ pixel_visit | webhook_received | payment
49
49
  ```
50
50
 
51
51
  Agents cannot write events directly — the closed enum is intentional. If you need custom state, use **mydatabaseapi** (KV) keyed on the contact id; the curated timeline stays authoritative for engagement.
@@ -29,10 +29,10 @@ The CLI stores this locally so you only enter it once:
29
29
 
30
30
  ```bash
31
31
  # One-time interactive setup (human)
32
- myapi auth registrant set
32
+ myapi account registrant set
33
33
 
34
34
  # Or non-interactive (agent)
35
- myapi auth registrant set --registrant-json '{
35
+ myapi account registrant set --registrant-json '{
36
36
  "name":"Simon Janin", "email":"simon@example.com", "phone":"+33612345678",
37
37
  "street":"1 rue de la Paix", "city":"Paris",
38
38
  "postal_code":"75001", "country_code":"FR"
@@ -47,7 +47,7 @@ Resolution at register time (highest wins): `--registrant-json` → per-field fl
47
47
  | Command | What it does |
48
48
  |---|---|
49
49
  | `myapi domain check <domain>` | Check availability and yearly price |
50
- | `myapi domain register <domain> [--years N] <registrant flags>` | Register a new domain (deducts credits). Requires ICANN WHOIS contact info — store once with `myapi auth registrant set`, or pass per-call via `--registrant-json` / `--registrant-*` flags |
50
+ | `myapi domain register <domain> [--years N] <registrant flags>` | Register a new domain (deducts credits). Requires ICANN WHOIS contact info — store once with `myapi account registrant set`, or pass per-call via `--registrant-json` / `--registrant-*` flags |
51
51
  | `myapi domain renew <domain>` | Renew a registered domain for another period |
52
52
  | `myapi domain list [--filter all\|unassigned\|org]` | List domains in your account |
53
53
  | `myapi domain assign <domain>` | Assign domain to your default (or `--org`) org |
@@ -69,7 +69,7 @@ Resolution at register time (highest wins): `--registrant-json` → per-field fl
69
69
  <!-- llm:start -->
70
70
  ```bash
71
71
  # One-time: store your WHOIS contact info (used by every register call)
72
- myapi auth registrant set
72
+ myapi account registrant set
73
73
 
74
74
  # Register and bring online
75
75
  myapi domain check example.com
@@ -36,7 +36,7 @@ export MYAPI_KEY=mak_...
36
36
  Requires:
37
37
  - An `api_key` from **myapihq**
38
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>`
39
+ - Default `org_id` (for templates/campaigns) — set with `myapi account config set-org <id>`
40
40
 
41
41
  ## Documentation
42
42
 
@@ -2,20 +2,20 @@
2
2
  name: my-email-api
3
3
  version: 1.0.0
4
4
  description: >
5
- Send transactional and bulk email from your own domain. Create mailboxes, send/receive messages, generate AI templates, run drip campaigns, and manage warmup.
6
- triggers: [email, mailbox, send email, transactional email, drip campaign, template, warmup, inbox, outbox, ses, sender reputation]
5
+ Send transactional and bulk email from your own domain. Create mailboxes, send/receive messages, generate AI templates, and manage warmup.
6
+ triggers: [email, mailbox, send email, transactional email, template, warmup, inbox, outbox, ses, sender reputation]
7
7
  checksum: sha256-pending
8
8
  ---
9
9
 
10
10
  # MyEmailAPI
11
11
 
12
- 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.
12
+ Account-scoped email infrastructure tied to your registered domains. Mailboxes belong to domains; sending and receiving work without per-org plumbing. Templates are org-scoped.
13
13
 
14
14
  ## Capabilities
15
15
  <!-- llm:start -->
16
- Email is built around mailboxes. Each mailbox lives on a registered domain (e.g. `hello@yourdomain.com`) and must be activated for sending before transactional sends or campaigns work — newly-created mailboxes can receive but not send.
16
+ Email is built around mailboxes. Each mailbox lives on a registered domain (e.g. `hello@yourdomain.com`) and must be activated for sending before transactional sends work — newly-created mailboxes can receive but not send.
17
17
 
18
- Templates are AI-generated HTML emails (org-scoped). Campaigns combine a template + a contact list + a per-day rate limit, sending to recipients over time. Warmup is a separate flow that gradually ramps a mailbox's send rate to build inbox reputation before high-volume campaigns.
18
+ Templates are AI-generated HTML emails (org-scoped). Warmup is a separate flow that gradually ramps a mailbox's send rate to build inbox reputation before high-volume sending.
19
19
 
20
20
  A registered domain via **mydomainapi** is the prerequisite — mailboxes need a domain to live on.
21
21
  <!-- llm:end -->
@@ -28,7 +28,6 @@ A registered domain via **mydomainapi** is the prerequisite — mailboxes need a
28
28
  | `email message` | `send`, `status`, `sent`, `inbox`, `outbox`, `get` | Transactional send + read |
29
29
  | `email warmup` | `start`, `stats`, `pause`, `resume`, `stop` | IP/domain warmup for sending reputation |
30
30
  | `email template` | `generate`, `list`, `get`, `preview`, `edit`, `send-test`, `delete` | AI-generated HTML templates |
31
- | `email campaign` | `create`, `list`, `get`, `update`, `upload-contacts`, `upload-contacts-file`, `start`, `pause`, `resume`, `stats` | Drip campaigns |
32
31
  <!-- generated:end -->
33
32
 
34
33
  ## Examples
@@ -55,16 +54,7 @@ myapi email template preview <id> # public preview URL — share with
55
54
  myapi email template send-test <id> --to me@yourdomain.com
56
55
  myapi email template edit <id> --prompt "Make the CTA larger and red"
57
56
 
58
- # 5. Drip campaign
59
- myapi email campaign create "Welcome series" \
60
- --template-id <id> --from hello@yourdomain.com --per-day 50
61
- myapi email campaign upload-contacts <campaign_id> --emails "alice@x.com,bob@y.com"
62
- # (or for big lists)
63
- myapi email campaign upload-contacts-file <campaign_id> --file ./contacts.csv
64
- myapi email campaign start <campaign_id>
65
- myapi email campaign stats <campaign_id>
66
-
67
- # 6. Warm up before a big send
57
+ # 5. Warm up before a big send
68
58
  myapi email warmup start --address hello@yourdomain.com
69
59
  myapi email warmup stats --address hello@yourdomain.com
70
60
  ```
@@ -74,7 +64,6 @@ myapi email warmup stats --address hello@yourdomain.com
74
64
 
75
65
  - A mailbox is uniquely identified by its address (`username@domain`).
76
66
  - Sending is opt-in per mailbox. Newly-created mailboxes can receive but not send until `activate-sending` runs.
77
- - Templates and campaigns are org-scoped. Set a default org once: `myapi config set-org <id>`.
78
- - An active or paused campaign blocks `domain unassign` with `DOMAIN_IN_USE`.
67
+ - Templates are org-scoped. Set a default org once: `myapi config set-org <id>`.
79
68
 
80
69
  Run `myapi email --help` or `myapi email <namespace> --help` for full flag reference.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "my-email-api",
3
- "description": "Send transactional and bulk email from your own domain. Mailboxes, AI templates, drip campaigns, and warmup.",
3
+ "description": "Send transactional and bulk email from your own domain. Mailboxes, AI templates, and warmup.",
4
4
  "version": "1.0.0",
5
5
  "published": true
6
6
  }
@@ -85,7 +85,7 @@ done < emails.txt | grep -v ' undeliverable$' > verified.txt
85
85
 
86
86
  - This is the **cheap layer only**. The full pipeline at outreach scale typically chains: this verify (free signal) → SMTP probe (medium cost) → catch-all detector (slow). Only the first is exposed today.
87
87
  - The `confidence` field is a hint, not a guarantee. A `deliverable` verdict at 0.95 confidence is still ≈5% bounce risk in practice.
88
- - For bulk verification, call this in parallel from your code with throttling there is no batch endpoint today. A batch + async-job endpoint is on the backend roadmap.
88
+ - For bulk verification use the async batch endpoint: `myapi email verify bulk < emails.txt` (one address per line) returns a `job_id`, then poll `myapi email verify job <job_id>` for status + per-address results.
89
89
  - Verification is per-org; you'll get rate-limited if you blast more than ~1 req/sec per key.
90
90
 
91
91
  Run `myapi email verify --help` for inline reference.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "my-email-verify-api",
3
- "description": "Sync single-address email verification — syntax + DNS + Microsoft probe. Pre-send quality gate for campaigns.",
3
+ "description": "Sync single-address email verification — syntax + DNS + Microsoft probe. Pre-send quality gate for outbound.",
4
4
  "version": "1.0.0",
5
5
  "published": true
6
6
  }