@myapihq/cli 1.3.13 → 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.
- package/dist/commands/account.d.ts +7 -1
- package/dist/commands/account.js +356 -18
- package/dist/commands/authproduct.d.ts +7 -0
- package/dist/commands/authproduct.js +286 -0
- package/dist/commands/billing.js +1 -1
- package/dist/commands/config.js +1 -1
- package/dist/commands/container.d.ts +1 -0
- package/dist/commands/container.js +115 -11
- package/dist/commands/domain.js +2 -2
- package/dist/commands/email/index.js +0 -13
- package/dist/commands/fn.d.ts +1 -0
- package/dist/commands/fn.js +64 -12
- package/dist/commands/keys.js +3 -3
- package/dist/commands/queue.d.ts +1 -0
- package/dist/commands/queue.js +10 -0
- package/dist/commands/setup.js +8 -8
- package/dist/commands/status.d.ts +1 -1
- package/dist/commands/status.js +11 -27
- package/dist/commands/storage.js +3 -1
- package/dist/commands/workflow.js +21 -6
- package/dist/completion.js +5 -4
- package/dist/config.js +1 -1
- package/dist/exposes.test.js +1 -2
- package/dist/index.js +31 -28
- package/dist/registrant.js +5 -5
- package/dist/sdk-queue.test.js +3 -2
- package/dist/skills/my-api-hq/SKILL.md +15 -12
- package/dist/skills/my-auth-api/README.md +33 -0
- package/dist/skills/my-auth-api/SKILL.md +112 -0
- package/dist/skills/my-auth-api/claude/.claude-plugin/plugin.json +6 -0
- package/dist/skills/my-auth-api/openapi/.gitkeep +0 -0
- package/dist/skills/my-crm-api/SKILL.md +1 -1
- package/dist/skills/my-domain-api/SKILL.md +4 -4
- package/dist/skills/my-email-api/README.md +1 -1
- package/dist/skills/my-email-api/SKILL.md +7 -18
- package/dist/skills/my-email-api/claude/.claude-plugin/plugin.json +1 -1
- package/dist/skills/my-email-verify-api/SKILL.md +1 -1
- package/dist/skills/my-email-verify-api/claude/.claude-plugin/plugin.json +1 -1
- package/dist/skills/my-git-api/README.md +43 -0
- package/dist/skills/my-git-api/SKILL.md +115 -0
- package/dist/skills/my-git-api/claude/.claude-plugin/plugin.json +6 -0
- package/dist/skills/my-git-api/openapi/.gitkeep +0 -0
- package/dist/skills/my-llm-api/claude/.claude-plugin/plugin.json +1 -1
- package/package.json +2 -2
- package/dist/commands/auth.d.ts +0 -11
- package/dist/commands/auth.js +0 -345
- package/dist/commands/email/campaign.d.ts +0 -4
- 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
|
|
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
|
-
...
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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(
|
|
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
|
|
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
|
|
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
|
|
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
|
|
325
|
+
async function dispatchAccount(subcommand, restArgs, flags) {
|
|
324
326
|
if (!subcommand || (flags.help && !subcommand)) {
|
|
325
|
-
info(
|
|
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
|
|
332
|
-
case 'link': return
|
|
333
|
-
case 'switch': return
|
|
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
|
|
340
|
+
banner('› Note: `myapi account install-skills` is deprecated. Use `myapi install-skills` instead.');
|
|
338
341
|
if (flags.help) {
|
|
339
|
-
info(
|
|
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
|
|
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
|
|
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 =>
|
|
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(
|
|
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
|
|
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
|
|
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
|
|
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
|
|
440
|
-
keys → myapi
|
|
441
|
-
setup → myapi
|
|
442
|
-
whoami → myapi
|
|
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
|
|
package/dist/registrant.js
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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);
|
package/dist/sdk-queue.test.js
CHANGED
|
@@ -78,9 +78,10 @@ describe('queue jobs', () => {
|
|
|
78
78
|
});
|
|
79
79
|
});
|
|
80
80
|
describe('queue.EXPOSES', () => {
|
|
81
|
-
it('covers all
|
|
82
|
-
expect(queue.EXPOSES).toHaveLength(
|
|
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
|
|
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
|
|
31
|
-
- **Registered** (verified email via `myapi
|
|
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
|
|
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
|
|
41
|
-
| `myapi
|
|
42
|
-
| `myapi
|
|
43
|
-
| `myapi
|
|
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
|
|
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
|
|
65
|
+
myapi account setup
|
|
63
66
|
myapi org create "Acme" --yes
|
|
64
67
|
|
|
65
68
|
# Day-to-day
|
|
66
|
-
myapi
|
|
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
|
|
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
|
|
32
|
+
myapi account registrant set
|
|
33
33
|
|
|
34
34
|
# Or non-interactive (agent)
|
|
35
|
-
myapi
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
6
|
-
triggers: [email, mailbox, send email, transactional email,
|
|
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
|
|
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
|
|
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).
|
|
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.
|
|
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
|
|
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,
|
|
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
|
|
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
|
|
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
|
}
|