@myapihq/cli 1.1.0-wip.4 → 1.2.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 (127) hide show
  1. package/dist/commands/{email.d.ts → audience.d.ts} +2 -0
  2. package/dist/commands/audience.js +245 -0
  3. package/dist/commands/auth.d.ts +5 -2
  4. package/dist/commands/auth.js +133 -5
  5. package/dist/commands/billing.d.ts +2 -0
  6. package/dist/commands/billing.js +18 -1
  7. package/dist/commands/company.d.ts +6 -0
  8. package/dist/commands/company.js +149 -0
  9. package/dist/commands/config.d.ts +2 -0
  10. package/dist/commands/config.js +20 -0
  11. package/dist/commands/crm/companies.d.ts +6 -0
  12. package/dist/commands/crm/companies.js +193 -0
  13. package/dist/commands/crm/contacts.d.ts +6 -0
  14. package/dist/commands/crm/contacts.js +241 -0
  15. package/dist/commands/crm/index.d.ts +6 -0
  16. package/dist/commands/crm/index.js +74 -0
  17. package/dist/commands/database.d.ts +6 -0
  18. package/dist/commands/database.js +259 -0
  19. package/dist/commands/domain.d.ts +3 -0
  20. package/dist/commands/domain.js +67 -1
  21. package/dist/commands/email/campaign.d.ts +2 -0
  22. package/dist/commands/email/campaign.js +34 -1
  23. package/dist/commands/email/index.d.ts +2 -0
  24. package/dist/commands/email/index.js +9 -0
  25. package/dist/commands/email/mailbox.d.ts +2 -0
  26. package/dist/commands/email/mailbox.js +5 -0
  27. package/dist/commands/email/message.d.ts +2 -0
  28. package/dist/commands/email/message.js +8 -0
  29. package/dist/commands/email/template.d.ts +2 -0
  30. package/dist/commands/email/template.js +54 -0
  31. package/dist/commands/email/verify.d.ts +7 -0
  32. package/dist/commands/email/verify.js +52 -0
  33. package/dist/commands/email/warmup.d.ts +2 -0
  34. package/dist/commands/email/warmup.js +7 -0
  35. package/dist/commands/funnel.d.ts +3 -0
  36. package/dist/commands/funnel.js +31 -0
  37. package/dist/commands/image.d.ts +2 -0
  38. package/dist/commands/image.js +43 -9
  39. package/dist/commands/keys.d.ts +2 -0
  40. package/dist/commands/keys.js +5 -0
  41. package/dist/commands/llm.d.ts +6 -0
  42. package/dist/commands/llm.js +156 -0
  43. package/dist/commands/org.d.ts +3 -0
  44. package/dist/commands/org.js +55 -0
  45. package/dist/commands/people.d.ts +6 -0
  46. package/dist/commands/people.js +136 -0
  47. package/dist/commands/pixel.d.ts +11 -3
  48. package/dist/commands/pixel.js +93 -0
  49. package/dist/commands/setup.d.ts +2 -0
  50. package/dist/commands/setup.js +57 -5
  51. package/dist/commands/status.d.ts +7 -0
  52. package/dist/commands/status.js +154 -0
  53. package/dist/commands/storage.d.ts +2 -0
  54. package/dist/commands/storage.js +14 -2
  55. package/dist/commands/update.d.ts +2 -0
  56. package/dist/commands/update.js +3 -0
  57. package/dist/commands/url.d.ts +7 -2
  58. package/dist/commands/url.js +6 -0
  59. package/dist/commands/verify.d.ts +7 -0
  60. package/dist/commands/verify.js +56 -0
  61. package/dist/commands/webhook.d.ts +2 -0
  62. package/dist/commands/webhook.js +31 -6
  63. package/dist/commands/workflow.d.ts +2 -0
  64. package/dist/commands/workflow.js +19 -1
  65. package/dist/completion.d.ts +3 -0
  66. package/dist/completion.js +78 -0
  67. package/dist/config.d.ts +2 -0
  68. package/dist/exposes.d.ts +2 -0
  69. package/dist/exposes.js +13 -0
  70. package/dist/exposes.test.js +99 -0
  71. package/dist/flags.test.js +84 -0
  72. package/dist/index.js +106 -14
  73. package/dist/prompt.d.ts +15 -0
  74. package/dist/prompt.js +27 -0
  75. package/dist/registrant.d.ts +6 -0
  76. package/dist/registrant.js +155 -0
  77. package/dist/services-sync.test.d.ts +1 -0
  78. package/dist/services-sync.test.js +32 -0
  79. package/dist/skills/my-api-hq/SKILL.md +51 -45
  80. package/dist/skills/my-crm-api/README.md +42 -0
  81. package/dist/skills/my-crm-api/SKILL.md +165 -0
  82. package/dist/skills/my-crm-api/claude/.claude-plugin/plugin.json +6 -0
  83. package/dist/skills/my-database-api/README.md +41 -0
  84. package/dist/skills/my-database-api/SKILL.md +107 -0
  85. package/dist/skills/my-database-api/claude/.claude-plugin/plugin.json +6 -0
  86. package/dist/skills/my-domain-api/SKILL.md +53 -26
  87. package/dist/skills/my-email-verify-api/README.md +33 -0
  88. package/dist/skills/my-email-verify-api/SKILL.md +91 -0
  89. package/dist/skills/my-email-verify-api/claude/.claude-plugin/plugin.json +6 -0
  90. package/dist/skills/my-funnel-api/SKILL.md +41 -37
  91. package/dist/skills/my-image-api/SKILL.md +48 -44
  92. package/dist/skills/my-llm-api/README.md +35 -0
  93. package/dist/skills/my-llm-api/SKILL.md +125 -0
  94. package/dist/skills/my-llm-api/claude/.claude-plugin/plugin.json +6 -0
  95. package/dist/skills/my-storage-api/README.md +1 -1
  96. package/dist/skills/my-storage-api/SKILL.md +44 -54
  97. package/dist/skills/my-webhook-api/README.md +1 -1
  98. package/dist/skills/my-webhook-api/SKILL.md +48 -92
  99. package/dist/skills/my-workflow-api/SKILL.md +46 -115
  100. package/dist/telemetry.d.ts +12 -0
  101. package/dist/telemetry.js +80 -0
  102. package/dist/telemetry.test.d.ts +1 -0
  103. package/dist/telemetry.test.js +101 -0
  104. package/package.json +13 -8
  105. package/dist/commands/email.js +0 -586
  106. package/dist/skills/my-email-api/README.md +0 -45
  107. package/dist/skills/my-email-api/SKILL.md +0 -104
  108. package/dist/skills/my-email-api/claude/.claude-plugin/plugin.json +0 -6
  109. package/dist/skills/my-email-api/make/.gitkeep +0 -0
  110. package/dist/skills/my-email-api/n8n/.gitkeep +0 -0
  111. package/dist/skills/my-email-api/openapi/.gitkeep +0 -0
  112. package/dist/skills/my-funnel-api/make/.gitkeep +0 -0
  113. package/dist/skills/my-funnel-api/n8n/.gitkeep +0 -0
  114. package/dist/skills/my-image-api/make/.gitkeep +0 -0
  115. package/dist/skills/my-image-api/n8n/.gitkeep +0 -0
  116. package/dist/skills/my-storage-api/make/.gitkeep +0 -0
  117. package/dist/skills/my-storage-api/n8n/.gitkeep +0 -0
  118. package/dist/skills/my-webhook-api/make/.gitkeep +0 -0
  119. package/dist/skills/my-webhook-api/n8n/.gitkeep +0 -0
  120. package/dist/skills/my-workflow-api/make/.gitkeep +0 -0
  121. package/dist/skills/my-workflow-api/n8n/.gitkeep +0 -0
  122. package/dist/utils.test.js +0 -48
  123. /package/dist/{utils.test.d.ts → exposes.test.d.ts} +0 -0
  124. /package/dist/skills/{my-api-hq/make → my-crm-api/openapi}/.gitkeep +0 -0
  125. /package/dist/skills/{my-api-hq/n8n → my-database-api/openapi}/.gitkeep +0 -0
  126. /package/dist/skills/{my-domain-api/make → my-email-verify-api/openapi}/.gitkeep +0 -0
  127. /package/dist/skills/{my-domain-api/n8n → my-llm-api/openapi}/.gitkeep +0 -0
@@ -0,0 +1,165 @@
1
+ ---
2
+ name: my-crm-api
3
+ version: 1.0.0
4
+ description: >
5
+ The canonical store of engaged contacts + companies for an org. Auto-ingests from inbound webhooks via a configurable dot-path. Fixed lifecycle_stage enum (cold | warm | qualified | customer | churned). Append-only event timeline with reserved kinds. Soft delete + restore. Promote-from-Goldfox closes the discovery → engagement loop.
6
+ triggers: [crm, contact, company, lead, engagement, pipeline, lifecycle, qualified, customer, webhook ingest, promote]
7
+ checksum: sha256-pending
8
+ ---
9
+
10
+ # MyCRMAPI
11
+
12
+ The store that closes the funnel. Today's loop without CRM: discover people (Goldfox) → save audience → send email → track pixel → form-fill via webhook → … nothing. People who *engage* live nowhere. CRM is where they land — automatically.
13
+
14
+ ## Capabilities
15
+ <!-- llm:start -->
16
+
17
+ ### Where CRM sits in the stack
18
+
19
+ - **mypeopleapi / mycompanyapi** — read-only Goldfox global lead universe (the crawl)
20
+ - **myaudienceapi** — saved filter snapshots over Goldfox
21
+ - **mycrmapi** — engaged contacts + companies, *private to your org*, with engagement history
22
+
23
+ A Goldfox row becomes a CRM contact when:
24
+ 1. You explicitly **promote** it (`myapi crm contacts promote <goldfox_person_id>`)
25
+ 2. *Or* a downstream service receives engagement for that email and auto-upserts the contact
26
+
27
+ ### Lifecycle stages (fixed enum — same for contacts and companies)
28
+
29
+ ```
30
+ cold | warm | qualified | customer | churned
31
+ ```
32
+
33
+ Move stage with `myapi crm contacts update <id> --stage qualified`. Every stage change emits a `stage_changed` event with `{from, to}` so the timeline shows the journey.
34
+
35
+ ### Contact sources (fixed enum)
36
+
37
+ ```
38
+ goldfox | email | pixel | webhook | manual
39
+ ```
40
+
41
+ Set automatically based on how the contact entered the CRM. Useful filter when you want "only contacts I've personally added" (`--source manual`) vs "warmed via Goldfox outreach" (`--source goldfox`).
42
+
43
+ ### Event timeline — reserved kinds
44
+
45
+ ```
46
+ created | promoted | stage_changed
47
+ email_sent | email_opened | email_clicked | email_replied
48
+ pixel_visit | webhook_received
49
+ ```
50
+
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.
52
+
53
+ **Engagement-event kinds bump `last_engagement_at`**: email_sent/opened/clicked/replied, pixel_visit, webhook_received. Admin kinds (created, promoted, stage_changed) don't. That's the right semantics — promoting a Goldfox lead into the CRM is not engagement.
54
+
55
+ ### Auto-ingest
56
+
57
+ Today (v1):
58
+ - **Webhook**: configurable per endpoint via `crm_email_path` — a JSON dot-path. Default `"email"` ingests `{"email":"x@y.com"}`. For Stripe, set `data.object.customer_email`; for GitHub, `sender.email`. Empty string disables ingest for that endpoint.
59
+
60
+ Coming next (backend wiring in progress):
61
+ - **Email**: every `myapi email message send` writes `email_sent`; opens/clicks fire `email_opened`/`email_clicked`
62
+ - **Pixel**: `identify` calls with an email write `pixel_visit`
63
+
64
+ If a contact doesn't exist for the matched email, it's auto-created with `source=` matching the originating service. The contact's company is auto-linked by email domain (creates the company on first sight).
65
+
66
+ ### Soft delete + restore
67
+
68
+ `myapi crm contacts delete <id>` sets `deleted_at` but **retains the event timeline**. By default soft-deleted contacts are excluded from search — pass `--include-deleted` to see them. Restore with `myapi crm contacts restore <id>`.
69
+
70
+ ### Goldfox enrichment (deferred)
71
+
72
+ A CRM contact promoted from Goldfox carries a `goldfox_person_id` reference. In v2 the GET response will join to Goldfox live, embedding the latest row inline as `goldfox_person`. Today that field is null until the BQ get-by-id helper lands. Search filters that hit Goldfox-only fields are not yet wired into CRM search.
73
+
74
+ ### Search filter — re-engagement semantics
75
+
76
+ `--max-last-engagement-days N` returns contacts last engaged *more than* N days ago. This intentionally **includes contacts with no engagement at all** (promoted-but-never-emailed Goldfox leads), because those are exactly the natural targets of a re-engagement campaign. If you want to distinguish "never tried" from "tried and went cold," layer `--source goldfox` (never engaged after promotion) or post-filter the JSON.
77
+
78
+ ### Failure modes
79
+
80
+ - `404 CONTACT_NOT_FOUND` / `COMPANY_NOT_FOUND`
81
+ - `409` on duplicate email/domain in the same org
82
+ - `400 INVALID_STAGE` if you pass a value outside the enum
83
+ - `400 GOLDFOX_PERSON_NOT_FOUND` on promote with an unknown id
84
+ <!-- llm:end -->
85
+
86
+ ## Commands
87
+ <!-- generated:start -->
88
+
89
+ ### Contacts
90
+ | Command | What it does |
91
+ |---|---|
92
+ | `myapi crm contacts list [--limit N]` | List all contacts (newest engagement first) |
93
+ | `myapi crm contacts search [--stage ...] [--source ...] [--email ...] [--min/max-last-engagement-days N]` | Filter contacts |
94
+ | `myapi crm contacts create <email> [--first-name ...] [--last-name ...] [--stage ...] [--custom-json ...]` | Manually create (source='manual') |
95
+ | `myapi crm contacts get <id>` | Fetch one contact (with embedded Goldfox enrichment when available) |
96
+ | `myapi crm contacts update <id> [--stage ...] [...]` | Patch fields. Stage change emits `stage_changed` event |
97
+ | `myapi crm contacts delete <id>` | Soft delete (events retained) |
98
+ | `myapi crm contacts restore <id>` | Restore a soft-deleted contact |
99
+ | `myapi crm contacts promote <goldfox_person_id>` | Idempotent Goldfox → CRM promotion |
100
+ | `myapi crm contacts events <id> [--kind ...]` | Timeline (newest first), filter by kind |
101
+
102
+ ### Companies
103
+ | Command | What it does |
104
+ |---|---|
105
+ | `myapi crm companies list / search / create / get / update / delete / restore` | Same shape as contacts |
106
+ | `myapi crm companies promote <domain>` | Goldfox company id IS its domain — pass the domain |
107
+
108
+ <!-- generated:end -->
109
+
110
+ All commands accept `--org <id>` (or set default: `myapi config set-org <id>`) and `--json` for machine-readable output.
111
+
112
+ ## Examples
113
+ <!-- llm:start -->
114
+ ```bash
115
+ # Discover → promote → engage workflow
116
+ myapi people search --keyword saas --has-c-level --country US --limit 5 --json \
117
+ | jq -r '.people[].id' \
118
+ | while read pid; do myapi crm contacts promote "$pid"; done
119
+
120
+ # Find everyone in 'qualified' for a follow-up email
121
+ myapi crm contacts search --stage qualified --json | jq -r '.contacts[].email'
122
+
123
+ # Re-engagement: contacts last engaged > 30 days ago (or never engaged at all)
124
+ myapi crm contacts search --max-last-engagement-days 30
125
+
126
+ # Manual add + tag with custom fields
127
+ myapi crm contacts create alice@acme.com \
128
+ --first-name Alice --stage warm \
129
+ --custom-json '{"intro_via":"riccardo","topic":"video editing"}'
130
+
131
+ # Update stage as the deal progresses — emits a stage_changed event
132
+ myapi crm contacts update <id> --stage qualified
133
+ myapi crm contacts update <id> --stage customer
134
+
135
+ # See the full engagement timeline
136
+ myapi crm contacts events <id>
137
+
138
+ # What landed in CRM from this Stripe webhook?
139
+ myapi crm contacts search --source webhook --json \
140
+ | jq '.contacts[] | {email, last_engagement_at}'
141
+ ```
142
+
143
+ ### End-to-end recipe — configure a webhook that auto-creates CRM contacts
144
+
145
+ ```bash
146
+ # Endpoint that ingests Stripe customer.created events
147
+ WH=$(myapi webhook create stripe --crm-email-path 'data.object.customer_email' --json)
148
+ URL=$(echo "$WH" | jq -r .url)
149
+ echo "Point Stripe at: $URL"
150
+
151
+ # Later, after Stripe fires...
152
+ myapi crm contacts search --source webhook --email "$STRIPE_CUSTOMER_EMAIL"
153
+ myapi crm contacts events <id> --kind webhook_received
154
+ ```
155
+ <!-- llm:end -->
156
+
157
+ ## Notes
158
+
159
+ - **Reserved event kinds — no custom events in v1.** If an agent needs custom state per contact, use `myapi database` keyed by contact id. The curated timeline stays the authoritative engagement record.
160
+ - **Event payloads carry an `external_id`** field used by the backend's idempotency index — same value as the natural id of the underlying action (`goldfox_person_id` for `promoted`, `delivery_id` for `webhook_received`, future `message_id` for `email_sent`). Read the semantic field (e.g. `goldfox_person_id`); `external_id` is a backend-internal duplicate. Old rows may still carry a legacy `message_id` field — same value as `external_id`; safe to ignore.
161
+ - **Goldfox enrichment field deferred** — the live join lands once the BQ get-by-id helper is wired backend-side. CLI treats it as optional today.
162
+ - **Email + Pixel auto-ingest not yet wired**. Only `webhook_received` events fire today. Email and pixel ingest are coming — the CLI surface stays unchanged when they land.
163
+ - **Free in v1.** Metered later if usage shows a need.
164
+
165
+ Run `myapi crm --help` or `myapi crm <namespace> --help` for inline reference.
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "my-crm-api",
3
+ "description": "The canonical store of engaged people + companies. Auto-ingest from inbound webhooks (configurable dot-path). Fixed lifecycle_stage enum, soft delete, event timeline.",
4
+ "version": "1.0.0",
5
+ "published": true
6
+ }
@@ -0,0 +1,41 @@
1
+ # my-database-api
2
+
3
+ Per-org KV store with namespaces. JSON values up to 256 KB per key. Compare-and-swap via `If-Match` etags. The substrate for stateful agent-built apps on MyAPI.
4
+
5
+ ## What it does
6
+
7
+ - Explicit, named namespaces (containers for keys)
8
+ - `get` / `set` / `del` / list keys (with prefix + cursor pagination)
9
+ - Inline values on list via `--values`
10
+ - Optimistic concurrency: `--if-match <etag>` returns an error if another writer raced
11
+
12
+ ## Quickstart
13
+
14
+ ```bash
15
+ myapi database create my-app
16
+ myapi database set users '{"alice":{"plan":"pro"}}' --ns my-app
17
+ myapi database get users --ns my-app
18
+ myapi database keys --ns my-app --values
19
+ ```
20
+
21
+ ## Authentication
22
+
23
+ ```bash
24
+ export MYAPI_KEY=mak_...
25
+ ```
26
+
27
+ Requires `api_key` and `org_id` from **myapihq**.
28
+
29
+ ## When to use
30
+
31
+ - Application state for a function or workflow: sessions, lookup tables, idempotency keys, lightweight counters
32
+ - Storing the state behind a CRM-like product an agent builds (the user table, the per-user URL ownership map)
33
+ - Anything where you'd reach for Redis but don't need its perf envelope
34
+
35
+ When **not** to use: blobs/binary (use `myapi storage`), large rows (>256 KB), complex queries (no secondary indexes today — prefix scans only).
36
+
37
+ ## Documentation
38
+
39
+ Per-key size limit, CAS semantics, pagination model: see `SKILL.md`.
40
+
41
+ Run `myapi database --help` for inline reference.
@@ -0,0 +1,107 @@
1
+ ---
2
+ name: my-database-api
3
+ version: 1.0.0
4
+ description: >
5
+ Per-org KV store with named namespaces, JSON values up to 256 KB, prefix-scan listing, and compare-and-swap via etag. The substrate for any stateful agent-built app on MyAPI — user tables, session stores, idempotency keys, per-user lookup maps.
6
+ triggers: [database, kv, key value, namespace, store, state, etag, cas, session, idempotency]
7
+ checksum: sha256-pending
8
+ ---
9
+
10
+ # MyDatabaseAPI
11
+
12
+ A small KV primitive scoped to your MyAPI org. Two resources: namespaces (containers) and keys (the actual values). Values are JSON; binary belongs in `myapi storage`. Compare-and-swap via etags is supported on day one.
13
+
14
+ ## Capabilities
15
+ <!-- llm:start -->
16
+ Use this when you need **state behind a workflow or a function** — the user table for a SaaS the agent is building on MyAPI primitives, a per-customer settings store, idempotency keys for webhook handlers, a session cache. Anything where Redis is overkill but raw env-var configuration isn't enough.
17
+
18
+ ### Model
19
+ - An **organization** owns many **namespaces**
20
+ - A **namespace** owns many **keys**
21
+ - A **key** points to one JSON **value** (≤ 256 KB serialized)
22
+ - Every value has an opaque **etag** that changes on every successful write
23
+
24
+ ### Limits
25
+ - **Key** ≤ 512 bytes (UTF-8)
26
+ - **Value** ≤ 256 KB serialized JSON. For blobs/binary, use `myapi storage`.
27
+ - **Namespace name** matches `^[a-z0-9][a-z0-9_-]{0,62}$`; the `__myapi_` prefix is reserved.
28
+
29
+ ### Compare-and-swap
30
+ Pass `--if-match <etag>` from a previous `get` to make `set` or `del` conditional. Returns an error if another writer changed the value between your read and write. Without `--if-match`, last-write-wins.
31
+
32
+ ### Listing
33
+ - Default: keys only, one per line
34
+ - `--values` adds inline values + etags (cost: a bigger response payload)
35
+ - `--prefix foo` for prefix-scoped listing
36
+ - `--limit N` (1–1000, default 50)
37
+ - Paginates via `--cursor` — the previous response's `next_cursor`
38
+
39
+ ### Failure modes
40
+ - `412 ETAG_MISMATCH` on CAS conflict (CLI surfaces it as a friendly error)
41
+ - `404 NAMESPACE_NOT_FOUND` / `KEY_NOT_FOUND`
42
+ - `409 NAMESPACE_EXISTS` on re-create
43
+ - `400 VALUE_NOT_JSON` if the body's `value` isn't valid JSON
44
+ - `413 VALUE_TOO_LARGE` if you exceed 256 KB (CLI also pre-flight checks)
45
+ <!-- llm:end -->
46
+
47
+ ## Commands
48
+ <!-- generated:start -->
49
+ | Command | What it does |
50
+ |---|---|
51
+ | `myapi database namespaces [--json]` | List namespaces in the org |
52
+ | `myapi database create <name>` | Create a namespace |
53
+ | `myapi database delete-namespace <name>` | Delete namespace AND all its keys (irreversible) |
54
+ | `myapi database keys --ns <ns> [--prefix <p>] [--limit N] [--values] [--cursor <c>]` | List keys, optionally with inline values |
55
+ | `myapi database get <key> --ns <ns>` | Get value + etag (etag printed to stderr) |
56
+ | `myapi database set <key> <value-json> --ns <ns> [--if-match <etag>] [--file <path>]` | Set key. CAS via --if-match |
57
+ | `myapi database del <key> --ns <ns> [--if-match <etag>]` | Delete key. CAS via --if-match |
58
+ <!-- generated:end -->
59
+
60
+ Pass `-` as `<value-json>` to read the value from stdin, or `--file <path>` to read from a file.
61
+
62
+ ## Examples
63
+ <!-- llm:start -->
64
+ ```bash
65
+ # Create a namespace, set a key, read it back
66
+ myapi database create my-app
67
+ myapi database set user:alice '{"plan":"pro","trial_ends":"2026-06-01"}' --ns my-app
68
+ myapi database get user:alice --ns my-app
69
+ # stdout: {"plan":"pro","trial_ends":"2026-06-01"}
70
+ # stderr: — etag=A1B2C3 · updated=2026-05-12T17:00:00Z
71
+
72
+ # List keys with a prefix
73
+ myapi database keys --ns my-app --prefix user: --values
74
+
75
+ # Compare-and-swap update
76
+ ETAG=$(myapi database get user:alice --ns my-app --json | jq -r .etag)
77
+ myapi database set user:alice '{"plan":"enterprise"}' --ns my-app --if-match "$ETAG"
78
+
79
+ # Idempotency keys for a webhook handler
80
+ myapi database set "delivery:$DELIVERY_ID" 'true' --ns idempotency --if-match '"00000000"' \
81
+ || { echo "already processed"; exit 0; }
82
+ ```
83
+
84
+ ### End-to-end recipe — user table for an agent-built SaaS
85
+
86
+ ```bash
87
+ # Bootstrap a "users" namespace
88
+ myapi database create users
89
+
90
+ # Sign-up handler: webhook receives { email, name } → store the user
91
+ myapi database set "by-email:$EMAIL" "$(jq -nc --arg n "$NAME" '{name:$n, plan:"trial"}')" \
92
+ --ns users
93
+
94
+ # Login handler: look up by email
95
+ myapi database get "by-email:$EMAIL" --ns users --json | jq -r .value
96
+ ```
97
+ <!-- llm:end -->
98
+
99
+ ## Notes
100
+
101
+ - **No transactions across keys.** Each key is independently atomic; multi-key updates aren't atomic. Use a single composite-JSON value if you need joint atomicity.
102
+ - **No secondary indexes today.** Prefix scans are the only query primitive. Design your keys for the access pattern (`user:by-email:alice@x.com`, `user:by-plan:pro:alice@x.com`, etc.).
103
+ - **No TTL today.** Keys live until deleted. If you need expiry, store `expires_at` in the value and let your reader drop stale rows.
104
+ - **Eventual `key_count`.** The `keys` field on a namespace is approximate; don't use it for strict pagination math.
105
+ - **Free in v1.** Metered later if usage shows a need. Cost discipline still applies — store data, not blobs.
106
+
107
+ Run `myapi database --help` for inline reference.
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "my-database-api",
3
+ "description": "Per-org KV store with namespaces + compare-and-swap. JSON values up to 256 KB. The substrate for stateful agent-built apps.",
4
+ "version": "1.0.0",
5
+ "published": true
6
+ }
@@ -1,62 +1,89 @@
1
1
  ---
2
2
  name: my-domain-api
3
+ version: 1.0.0
3
4
  description: >
4
5
  Register new domains and manage edge settings. Required before a funnel can go live on a custom URL.
6
+ triggers: [domain, register domain, dns, custom domain, edge, cdn, security level, browser check, renew, namecheap]
7
+ checksum: sha256-pending
5
8
  ---
6
9
 
7
10
  # MyDomainAPI
8
11
 
9
12
  Handles domain registration, assignment to orgs, and edge (CDN/security) settings. DNS is fully managed — you never touch nameservers manually.
10
13
 
11
- ## How It Fits Together
14
+ ## Capabilities
15
+ <!-- llm:start -->
16
+ Domains are how you take a funnel from `your-org.makeautonomous.com` to `your-real-brand.com`. The flow is: check availability, register (deducts credits), assign to an org, watch status until DNS propagates. From that point, your org's funnel serves at `https://yourdomain.com`. SSL provisions automatically a few minutes after status flips to `active`.
12
17
 
13
- - Requires `api_key` and `org_id` from **myapihq**.
14
- - A domain assigned to an org is the prerequisite for a **myfunnelapi** funnel to be reachable at a custom URL.
15
- - Without a domain, funnels still work on the free `*.makeautonomous.com` preview subdomain.
18
+ You can also import existing domains (without re-registering) and tune CDN/security settings per-domain.
16
19
 
17
- ## Typical Flow
20
+ Without a domain, funnels still work on the free `*.makeautonomous.com` preview subdomain.
21
+
22
+ ### Registrant (ICANN requirement)
23
+
24
+ Every `myapi domain register` call needs WHOIS contact info — name, email, phone, address, country code (ISO alpha-2). State is required for US/CA registrants.
25
+
26
+ The CLI stores this locally so you only enter it once:
18
27
 
19
28
  ```bash
20
- myapi domain check example.com # check availability + price
21
- myapi domain register example.com # register it (deducts credits)
22
- myapi domain assign example.com # assign to your default org
23
- myapi domain status example.com # watch until status = active
29
+ # One-time interactive setup (human)
30
+ myapi auth registrant set
31
+
32
+ # Or non-interactive (agent)
33
+ myapi auth registrant set --registrant-json '{
34
+ "name":"Simon Janin", "email":"simon@example.com", "phone":"+33612345678",
35
+ "street":"1 rue de la Paix", "city":"Paris",
36
+ "postal_code":"75001", "country_code":"FR"
37
+ }'
24
38
  ```
25
39
 
26
- After `status` shows `active`, your funnel will be live at `https://example.com`. SSL provisioning takes a few extra minutes after activation.
27
-
28
- ## All Commands
40
+ Resolution at register time (highest wins): `--registrant-json` per-field flags (`--registrant-name`, …) stored config interactive TTY prompt → error. Stored contact info is never sent to the backend except as a per-request field on register.
41
+ <!-- llm:end -->
29
42
 
43
+ ## Commands
44
+ <!-- generated:start -->
30
45
  | Command | What it does |
31
46
  |---|---|
32
47
  | `myapi domain check <domain>` | Check availability and yearly price |
33
- | `myapi domain register <domain> [--years N]` | Register a new domain (explicit domain required) |
48
+ | `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 |
49
+ | `myapi domain renew <domain>` | Renew a registered domain for another period |
34
50
  | `myapi domain list [--filter all\|unassigned\|org]` | List domains in your account |
35
- | `myapi domain assign <domain>` | Assign domain to the default (or `--org`) org (explicit domain required) |
36
- | `myapi domain unassign <domain>` | Remove domain from its org (explicit domain required) |
37
- | `myapi domain status <domain>` | Check registration + DNS propagation status |
51
+ | `myapi domain assign <domain>` | Assign domain to your default (or `--org`) org |
52
+ | `myapi domain unassign <domain>` | Remove domain from its org |
53
+ | `myapi domain status <domain>` | Registration + DNS propagation status |
38
54
  | `myapi domain settings <domain>` | View edge/CDN settings |
39
- | `myapi domain update-settings <domain>` | Update edge settings (security level, browser check, cache purge) |
55
+ | `myapi domain update-settings <domain>` | Change security level, browser check, purge cache |
56
+ <!-- generated:end -->
40
57
 
41
- `register`, `assign`, and `unassign` always require an explicit domain argument — they do not fall back to any stored default, to prevent accidental destructive actions.
58
+ ## Examples
59
+ <!-- llm:start -->
60
+ ```bash
61
+ # One-time: store your WHOIS contact info (used by every register call)
62
+ myapi auth registrant set
42
63
 
43
- ## Edge Settings
64
+ # Register and bring online
65
+ myapi domain check example.com
66
+ myapi domain register example.com
67
+ myapi domain assign example.com
68
+ myapi domain status example.com # poll until status = active
44
69
 
45
- Fine-tune CDN/security behavior per domain:
70
+ # Renew before expiry
71
+ myapi domain renew example.com
46
72
 
47
- ```bash
73
+ # Tune the edge for AI bot traffic
48
74
  myapi domain update-settings example.com \
49
- --security=essentially_off \
50
- --browser-check=off \
51
- --purge-cache
75
+ --security=essentially_off --browser-check=off --purge-cache
52
76
  ```
53
77
 
54
- Security levels: `essentially_off` · `low` · `medium` · `high` · `under_attack`.
78
+ Security levels: `essentially_off` · `low` · `medium` · `high` · `under_attack`.
79
+
55
80
  Set `essentially_off` + `browser-check=off` to allow AI crawlers and training bots through without challenge pages.
81
+ <!-- llm:end -->
56
82
 
57
83
  ## Notes
58
84
 
59
- - All commands default to `--org` from your saved config. Set it once with `myapi auth config set-org <id>`.
85
+ - `register`, `renew`, `assign`, and `unassign` always require an explicit domain argument they don't fall back to a stored default, to prevent accidental destructive actions.
86
+ - All commands default to `--org` from your saved config (set with `myapi config set-org <id>`).
60
87
  - `402` errors mean insufficient credits — run `myapi billing topup <amount>`.
61
88
 
62
89
  Run `myapi domain --help` or `myapi domain <subcommand> --help` for full flag reference.
@@ -0,0 +1,33 @@
1
+ ---
2
+ # my-email-verify-api
3
+
4
+ Synchronous single-address email verification — syntax + DNS + Microsoft probe. Pre-send quality gate for outbound campaigns.
5
+
6
+ ## What it does
7
+
8
+ - Validates email syntax (instant)
9
+ - Looks up DNS / MX records (sub-second)
10
+ - Probes Microsoft GetCredentialType for Microsoft-hosted domains
11
+ - Returns `deliverable` / `undeliverable` / `unknown` with confidence score
12
+ - Sets `smtp_recommended: true` when the cheap layer was inconclusive
13
+
14
+ ## Quickstart
15
+
16
+ ```bash
17
+ myapi email verify alice@example.com
18
+ myapi email verify alice@example.com --json # full check breakdown
19
+ ```
20
+
21
+ ## Authentication
22
+
23
+ ```bash
24
+ export MYAPI_KEY=mak_...
25
+ ```
26
+
27
+ Requires `api_key` and `org_id` from **myapihq**.
28
+
29
+ ## Documentation
30
+
31
+ Verdicts, confidence semantics, and pre-send filter recipe: see `SKILL.md`.
32
+
33
+ Run `myapi email verify --help` for inline reference.
@@ -0,0 +1,91 @@
1
+ ---
2
+ name: my-email-verify-api
3
+ version: 1.0.0
4
+ description: >
5
+ Synchronous single-address email verification — syntax + DNS + Microsoft GetCredentialType probe. Returns a verdict in <1s for ~50% of inputs; the rest get verdict='unknown' with smtp_recommended=true. The pre-send quality gate for any outbound campaign.
6
+ triggers: [email verify, email validation, deliverability, smtp, syntax check, dns mx, microsoft, mx lookup, bounce prevention]
7
+ checksum: sha256-pending
8
+ ---
9
+
10
+ # MyEmailVerifyAPI
11
+
12
+ A cheap, fast quality gate for a single email address. Runs three layers in sequence: syntax check (instant) → DNS / MX lookup (sub-second) → Microsoft GetCredentialType probe (sub-second for non-Microsoft, slower for federated domains). Returns a definitive `deliverable` / `undeliverable` verdict for about half of inputs; the rest get `verdict: 'unknown'` with `smtp_recommended: true`, suggesting a downstream SMTP probe that isn't part of this API today.
13
+
14
+ ## Capabilities
15
+ <!-- llm:start -->
16
+ Use this before any campaign send — pipe the audience members through `verify` and drop the undeliverable ones to protect your sender reputation.
17
+
18
+ Verdicts:
19
+ - **`deliverable`** — high-confidence acceptance. Safe to send.
20
+ - **`undeliverable`** — high-confidence reject. Skip. Most common causes: malformed syntax (`missing '@'`), no MX records, Microsoft positively returns "no such mailbox".
21
+ - **`unknown`** — couldn't determine cheaply. The `smtp_recommended` flag will be `true`; in practice, treat as "send but watch the bounce signal" or run a more expensive SMTP probe externally.
22
+
23
+ Response shape (full check breakdown available via `--json`):
24
+ ```json
25
+ {
26
+ "email": "alice@example.com",
27
+ "verdict": "deliverable" | "undeliverable" | "unknown",
28
+ "confidence": 0.0..1.0,
29
+ "smtp_recommended": true,
30
+ "checks": {
31
+ "syntax": { "valid": true, "detail": "missing '@'" },
32
+ "dns": { "valid": true, "mx_records": ["mx1.example.com", ...] },
33
+ "microsoft": { "verdict": "...", "if_exists_result": 0, "domain_type": 4, "federated": false }
34
+ },
35
+ "elapsed_ms": 124
36
+ }
37
+ ```
38
+
39
+ Latency notes: syntax + DNS are <100ms. Microsoft GetCredentialType is fast for non-Microsoft domains, can take 5–8s on federated (custom) Microsoft tenants while it walks redirects. Set call timeouts ≥10s for safety.
40
+ <!-- llm:end -->
41
+
42
+ ## Commands
43
+ <!-- generated:start -->
44
+ | Command | What it does |
45
+ |---|---|
46
+ | `myapi email verify <email> [--json]` | Run all three verification layers on one address; print verdict + confidence + key checks |
47
+ <!-- generated:end -->
48
+
49
+ Pass `--json` for the full check breakdown (syntax detail, MX records, Microsoft probe result). The default human render shows the verdict + a one-line summary per check that fired.
50
+
51
+ ## Examples
52
+ <!-- llm:start -->
53
+ ```bash
54
+ # Clear undeliverable — syntax fails instantly
55
+ myapi email verify not-an-email
56
+ # → Verdict: ✗ undeliverable (confidence 1.00)
57
+ # → Syntax: missing '@'
58
+ # → Took: 0ms
59
+
60
+ # Generic domain — unknown verdict, MX visible, confidence 0.5
61
+ myapi email verify hello@gmail.com
62
+ # → Verdict: ? unknown (confidence 0.50)
63
+ # → SMTP next: yes — consider an SMTP probe
64
+ # → MX: gmail-smtp-in.l.google.com, alt1...
65
+
66
+ # Full breakdown
67
+ myapi email verify alice@corp.com --json | jq '.checks'
68
+ ```
69
+
70
+ ### End-to-end recipe — filter an audience before send
71
+
72
+ ```bash
73
+ # Pull all members from a saved audience
74
+ AID=$(myapi audience list --json | jq -r '.[0].id')
75
+ myapi audience members $AID --limit 100 --json | jq -r '.people[].email' > emails.txt
76
+
77
+ # Verify each in parallel (modest concurrency to be polite)
78
+ while read email; do
79
+ myapi email verify "$email" --json | jq -r '"\(.email) \(.verdict)"'
80
+ done < emails.txt | grep -v ' undeliverable$' > verified.txt
81
+ ```
82
+ <!-- llm:end -->
83
+
84
+ ## Notes
85
+
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
+ - 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.
89
+ - Verification is per-org; you'll get rate-limited if you blast more than ~1 req/sec per key.
90
+
91
+ Run `myapi email verify --help` for inline reference.
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "my-email-verify-api",
3
+ "description": "Sync single-address email verification — syntax + DNS + Microsoft probe. Pre-send quality gate for campaigns.",
4
+ "version": "1.0.0",
5
+ "published": true
6
+ }