@myapihq/cli 2.10.0 → 2.11.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.
- package/dist/commands/import-key.test.d.ts +1 -0
- package/dist/commands/import-key.test.js +69 -0
- package/dist/commands/org.js +5 -1
- package/dist/commands/setup.d.ts +5 -1
- package/dist/commands/setup.js +67 -6
- package/dist/commands/storage.js +151 -14
- package/dist/config.d.ts +2 -0
- package/dist/errors.d.ts +4 -0
- package/dist/errors.js +30 -3
- package/dist/helpers.d.ts +20 -1
- package/dist/helpers.js +79 -1
- package/dist/index.js +6 -1
- package/dist/org-not-found.test.d.ts +1 -0
- package/dist/org-not-found.test.js +42 -0
- package/dist/org-notice.test.d.ts +1 -0
- package/dist/org-notice.test.js +37 -0
- package/dist/output.d.ts +6 -0
- package/dist/output.js +8 -1
- package/dist/skills/my-api-hq/SKILL.md +34 -14
- package/dist/skills/my-audience-api/SKILL.md +16 -1
- package/dist/skills/my-auth-api/SKILL.md +17 -2
- package/dist/skills/my-company-api/SKILL.md +16 -1
- package/dist/skills/my-container-api/SKILL.md +22 -7
- package/dist/skills/my-crm-api/SKILL.md +16 -1
- package/dist/skills/my-database-api/SKILL.md +13 -17
- package/dist/skills/my-domain-api/SKILL.md +16 -1
- package/dist/skills/my-email-api/SKILL.md +12 -16
- package/dist/skills/my-email-verify-api/SKILL.md +16 -1
- package/dist/skills/my-feedback-api/README.md +33 -0
- package/dist/skills/my-feedback-api/SKILL.md +118 -0
- package/dist/skills/my-feedback-api/claude/.claude-plugin/plugin.json +7 -0
- package/dist/skills/my-function-api/README.md +34 -0
- package/dist/skills/my-function-api/SKILL.md +16 -1
- package/dist/skills/my-funnel-api/SKILL.md +16 -1
- package/dist/skills/my-git-api/SKILL.md +17 -1
- package/dist/skills/my-image-api/SKILL.md +17 -1
- package/dist/skills/my-llm-api/SKILL.md +20 -6
- package/dist/skills/my-payments-api/README.md +33 -0
- package/dist/skills/my-payments-api/SKILL.md +16 -1
- package/dist/skills/my-people-api/SKILL.md +16 -1
- package/dist/skills/my-pixel-api/SKILL.md +26 -3
- package/dist/skills/my-queue-api/SKILL.md +35 -2
- package/dist/skills/my-storage-api/SKILL.md +37 -29
- package/dist/skills/my-task-api/SKILL.md +35 -2
- package/dist/skills/my-url-to/SKILL.md +16 -1
- package/dist/skills/my-webhook-api/SKILL.md +23 -3
- package/dist/skills/my-workflow-api/SKILL.md +32 -6
- package/package.json +2 -2
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// A resource sitting in another org answers exactly like a typo'd id. "Not
|
|
2
|
+
// found" sends the reader to check the id — which is correct, and which is why
|
|
3
|
+
// the org never gets questioned. Naming the org that was searched is what
|
|
4
|
+
// turns the commonest org-drift symptom into its own diagnosis.
|
|
5
|
+
//
|
|
6
|
+
// The risk on the other side is appending it to everything, which is the
|
|
7
|
+
// always-on banner in a different costume. These pin both edges.
|
|
8
|
+
import { describe, it, expect } from 'vitest';
|
|
9
|
+
import { withOrgContext } from './errors.js';
|
|
10
|
+
const ORG = { org_id: 'org-aaaaaaaa-1111', org_name: 'Acme' };
|
|
11
|
+
describe('withOrgContext', () => {
|
|
12
|
+
it('names the org searched on a 404', () => {
|
|
13
|
+
const out = withOrgContext('Funnel not found.', { status: 404, code: 'FUNNEL_NOT_FOUND' }, ORG);
|
|
14
|
+
expect(out).toContain('Funnel not found.');
|
|
15
|
+
expect(out).toContain('Acme');
|
|
16
|
+
expect(out).toContain('myapi org list');
|
|
17
|
+
});
|
|
18
|
+
it('fires on a not-found CODE even when the status is not 404', () => {
|
|
19
|
+
const out = withOrgContext('Resource not found.', { status: 400, code: 'not_found' }, ORG);
|
|
20
|
+
expect(out).toContain('Acme');
|
|
21
|
+
});
|
|
22
|
+
it('stays out of the way on unrelated errors', () => {
|
|
23
|
+
const msg = 'Too many requests. Please wait a moment and try again.';
|
|
24
|
+
expect(withOrgContext(msg, { status: 429, code: 'RATE_LIMITED' }, ORG)).toBe(msg);
|
|
25
|
+
});
|
|
26
|
+
it('says nothing when the org itself is what was not found', () => {
|
|
27
|
+
// "Looked in org X" where X is the id that does not exist restates the
|
|
28
|
+
// failure as though it were a clue.
|
|
29
|
+
const msg = 'Organization not found.';
|
|
30
|
+
expect(withOrgContext(msg, { status: 404, code: 'ORG_NOT_FOUND' }, ORG)).toBe(msg);
|
|
31
|
+
});
|
|
32
|
+
it('says nothing when no org was resolved', () => {
|
|
33
|
+
// Account-level commands (whoami, billing) never resolve an org; there is
|
|
34
|
+
// no org to blame and claiming one would be a fabrication.
|
|
35
|
+
const msg = 'Resource not found.';
|
|
36
|
+
expect(withOrgContext(msg, { status: 404, code: 'NOT_FOUND' }, undefined)).toBe(msg);
|
|
37
|
+
});
|
|
38
|
+
it('does not repeat an org the message already names', () => {
|
|
39
|
+
const msg = `Funnel not found in org ${ORG.org_id}.`;
|
|
40
|
+
expect(withOrgContext(msg, { status: 404, code: 'FUNNEL_NOT_FOUND' }, ORG)).toBe(msg);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// The org-change notice has two silent failure modes and no build breaks for
|
|
2
|
+
// either: always-speak turns it into noise that gets filtered out within a day
|
|
3
|
+
// (and costs tokens on every call in an agent loop), always-silent lets the
|
|
4
|
+
// wrong-org write it exists to catch go through unannounced. Pin both edges.
|
|
5
|
+
import { describe, it, expect } from 'vitest';
|
|
6
|
+
import { orgChangeNotice } from './helpers.js';
|
|
7
|
+
const NAMES = { 'org-a': 'Acme', 'org-b': 'Demo Corp' };
|
|
8
|
+
describe('orgChangeNotice', () => {
|
|
9
|
+
it('says nothing in steady state — the same org twice', () => {
|
|
10
|
+
expect(orgChangeNotice('org-a', 'org-a', NAMES)).toBeUndefined();
|
|
11
|
+
});
|
|
12
|
+
it('says nothing on the first ever resolution', () => {
|
|
13
|
+
// No prior means nothing has moved; announcing here would fire on every
|
|
14
|
+
// fresh config and train the reader to ignore the line.
|
|
15
|
+
expect(orgChangeNotice(undefined, 'org-a', NAMES)).toBeUndefined();
|
|
16
|
+
});
|
|
17
|
+
it('speaks when the org moves, naming both sides', () => {
|
|
18
|
+
const msg = orgChangeNotice('org-a', 'org-b', NAMES);
|
|
19
|
+
expect(msg).toBeDefined();
|
|
20
|
+
expect(msg).toContain('Acme');
|
|
21
|
+
expect(msg).toContain('Demo Corp');
|
|
22
|
+
});
|
|
23
|
+
it('still speaks when no name is cached, falling back to the id', () => {
|
|
24
|
+
// The cache is populated opportunistically by `org list` / `status`, so an
|
|
25
|
+
// agent that never ran either still has to be told the target moved.
|
|
26
|
+
const msg = orgChangeNotice('org-a', 'org-b', {});
|
|
27
|
+
expect(msg).toBeDefined();
|
|
28
|
+
expect(msg).toContain('org-a');
|
|
29
|
+
expect(msg).toContain('org-b');
|
|
30
|
+
});
|
|
31
|
+
it('shortens long ids so the line stays scannable', () => {
|
|
32
|
+
const long = 'org-7f1aa7f1-f6eb-4a6d-87b7-1bbe6584f5d6';
|
|
33
|
+
const msg = orgChangeNotice(long, 'org-b', {});
|
|
34
|
+
expect(msg).not.toContain(long);
|
|
35
|
+
expect(msg).toContain('org-7f1a');
|
|
36
|
+
});
|
|
37
|
+
});
|
package/dist/output.d.ts
CHANGED
|
@@ -5,6 +5,11 @@ export declare function success(message: string): void;
|
|
|
5
5
|
export declare function error(message: string): never;
|
|
6
6
|
export declare function info(message: string): void;
|
|
7
7
|
export declare function banner(message: string): void;
|
|
8
|
+
type ResolvedContext = {
|
|
9
|
+
org_id: string;
|
|
10
|
+
org_name?: string;
|
|
11
|
+
};
|
|
12
|
+
export declare function setResolvedContextSource(fn: () => ResolvedContext | undefined): void;
|
|
8
13
|
export declare function printJson(data: unknown): void;
|
|
9
14
|
export declare function spinnerFrame(i: number): string;
|
|
10
15
|
export declare function spinnerWrite(s: string): void;
|
|
@@ -16,3 +21,4 @@ export interface PrintTableOptions {
|
|
|
16
21
|
empty?: string;
|
|
17
22
|
}
|
|
18
23
|
export declare function printTable<T extends object>(rows: T[], opts?: PrintTableOptions): void;
|
|
24
|
+
export {};
|
package/dist/output.js
CHANGED
|
@@ -12,8 +12,15 @@ export function info(message) {
|
|
|
12
12
|
export function banner(message) {
|
|
13
13
|
process.stderr.write(message + '\n');
|
|
14
14
|
}
|
|
15
|
+
let resolvedContext;
|
|
16
|
+
export function setResolvedContextSource(fn) {
|
|
17
|
+
resolvedContext = fn;
|
|
18
|
+
}
|
|
15
19
|
export function printJson(data) {
|
|
16
|
-
|
|
20
|
+
const ctx = resolvedContext?.();
|
|
21
|
+
const stampable = ctx && data !== null && typeof data === 'object' && !Array.isArray(data);
|
|
22
|
+
const payload = stampable ? { ...data, _resolved: ctx } : data;
|
|
23
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
17
24
|
}
|
|
18
25
|
// Spinner / line-clear primitives. Used by polling helpers (utils.pollJob)
|
|
19
26
|
// and any handler that wants its own progress UI.
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: my-api-hq
|
|
3
|
-
version: 1.
|
|
3
|
+
version: 1.1.0
|
|
4
4
|
description: >
|
|
5
5
|
Auth, organizations, and billing hub. Start here to get an api_key and org_id — every other service depends on both.
|
|
6
6
|
triggers: [api key, account, organization, org, billing, balance, topup, credits, setup, defaults, brand, sync brand, doctor, health check, is my org healthy]
|
|
7
|
-
checksum: sha256-
|
|
7
|
+
checksum: sha256-6f54c719facde1ddcdee04ffcf9527ed42550cbfc67679ced5aea55fc7adba7d
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# MyApiHQ
|
|
@@ -15,14 +15,6 @@ The root service. It manages accounts, API keys, organizations, and billing. No
|
|
|
15
15
|
<!-- llm:start -->
|
|
16
16
|
MyApiHQ is the platform's foundation. Every other service (domain, funnel, auth, payments, fn, workflow, database, storage, email, webhook, crm, llm, image, pixel, 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
|
-
```
|
|
19
|
-
myapihq ──► org_id + api_key
|
|
20
|
-
│
|
|
21
|
-
┌───────┴────────┐
|
|
22
|
-
mydomainapi myfunnelapi
|
|
23
|
-
(domains) (websites)
|
|
24
|
-
```
|
|
25
|
-
|
|
26
18
|
### Anonymous vs registered accounts
|
|
27
19
|
|
|
28
20
|
Two tiers, chosen at setup time:
|
|
@@ -42,6 +34,7 @@ An anonymous account can upgrade at any time via `myapi account link <email>`
|
|
|
42
34
|
| Command | What it does |
|
|
43
35
|
|---|---|
|
|
44
36
|
| `myapi account setup` | Interactive setup: creates account, generates api_key, sets defaults |
|
|
37
|
+
| `myapi status` | Single-screen orientation: account + every resource in the default org. Start here when you don't know what already exists |
|
|
45
38
|
| `myapi account whoami` | Show current account, default org/funnel, balance, free-tier usage |
|
|
46
39
|
| `myapi account link [email]` | Upgrade anonymous account to registered (or add a second session) |
|
|
47
40
|
| `myapi account switch [index]` | Switch active account |
|
|
@@ -72,6 +65,7 @@ myapi account setup
|
|
|
72
65
|
myapi org create "Acme" --yes
|
|
73
66
|
|
|
74
67
|
# Day-to-day
|
|
68
|
+
myapi status # what exists already, in one screen
|
|
75
69
|
myapi account whoami # confirm what's active
|
|
76
70
|
myapi billing balance # before doing anything that costs credits
|
|
77
71
|
myapi billing topup 20 # add $20
|
|
@@ -98,28 +92,54 @@ Each org gets a free preview subdomain (`*.makeautonomous.com`) usable before re
|
|
|
98
92
|
- API keys have format `hq_live_...` and are sent as `Authorization: Bearer <key>`.
|
|
99
93
|
- `org sync-brand` is async (scrapes the site, polls the job).
|
|
100
94
|
|
|
101
|
-
##
|
|
95
|
+
## Scoping a key — and why `--org` is the one that saves you
|
|
102
96
|
|
|
103
97
|
A key's authority is inline and always a subset of the key that mints it, so
|
|
104
98
|
you can hand work a key that cannot exceed its job:
|
|
105
99
|
|
|
106
100
|
```bash
|
|
101
|
+
myapi keys create --name agent --org <id> --grant '*' # locked to ONE org
|
|
107
102
|
myapi keys create --name ci --grant funnel:write,storage:read
|
|
108
103
|
myapi keys create --name readonly --grant '*:read' # read anything, write nothing
|
|
109
104
|
myapi keys create --name billing-fn --org <id> --grant email --spend-cap 25
|
|
110
105
|
```
|
|
111
106
|
|
|
107
|
+
- `--org <id>` — **lock it to one org.** Omit for account-wide.
|
|
112
108
|
- `--grant <list>` — `slot:read` / `slot:write`; a bare slot means write, `*`
|
|
113
109
|
means all. **Omitting `--grant` mints an unrestricted key.**
|
|
114
|
-
- `--org <id>` — lock it to one org. Omit for account-wide.
|
|
115
110
|
- `--spend-cap <usd>` — hard ceiling; `0` means the key cannot spend at all.
|
|
116
111
|
- `keys revoke-all --kind function|manual|account` narrows the kill switch.
|
|
117
112
|
|
|
113
|
+
**Agents working for one org: use an org-locked key.** The org is otherwise
|
|
114
|
+
ambient — a saved default that survives across turns, where a stale one looks
|
|
115
|
+
exactly like a correct one. That is how a demo lands on a live site. Locking
|
|
116
|
+
turns a wrong-org write into a `403`. Keep your *own* key account-wide though:
|
|
117
|
+
an org-locked one cannot create orgs or manage billing.
|
|
118
|
+
|
|
119
|
+
Two more signals, no flags needed: resolving to a different org than last time
|
|
120
|
+
prints `→ org changed: <from> → <to>` on stderr, once — silence means it has
|
|
121
|
+
not moved. Under `--json`, object responses carry `_resolved: {org_id,
|
|
122
|
+
org_name}`; assert on that rather than assuming.
|
|
123
|
+
|
|
118
124
|
## Org profile fields
|
|
119
125
|
|
|
120
126
|
`myapi org create <name>` also takes `--tagline`, `--description`,
|
|
121
127
|
`--business-sector` and `--logo-url`. They populate the org's public profile
|
|
122
|
-
and the funnel created alongside it
|
|
123
|
-
|
|
128
|
+
and the funnel created alongside it.
|
|
129
|
+
|
|
130
|
+
## HTTP (from deployed code)
|
|
131
|
+
|
|
132
|
+
<!-- http:start -->
|
|
133
|
+
<!-- generated by `npm run canonical-sync` — do not edit -->
|
|
134
|
+
```
|
|
135
|
+
base https://api.myapihq.com
|
|
136
|
+
path GET /hq/orgs/{org_id}
|
|
137
|
+
auth Authorization: Bearer <key> (fn: env.__MYAPI_KEY · container: env.MYAPI_KEY)
|
|
138
|
+
reply { "success": true, "data": …, "error": null, "meta": {…} }
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
- **Per-slot host** — do not assume one host serves every slot.
|
|
142
|
+
- **Org id goes in the PATH** — there is no `X-Org-Id` header.
|
|
143
|
+
<!-- http:end -->
|
|
124
144
|
|
|
125
145
|
Run `myapi --help` or `myapi <command> --help` for full flag reference.
|
|
@@ -4,7 +4,7 @@ version: 1.0.0
|
|
|
4
4
|
description: >
|
|
5
5
|
Saved audiences = named Goldfox-filter snapshots over the people or company database. Build a target list once, name it, reuse it across campaigns, refresh to re-evaluate against current data. The persistence layer on top of my-people-api + my-company-api.
|
|
6
6
|
triggers: [audience, segment, target list, saved filter, goldfox, lead list, abm list, refresh, members, prospect database]
|
|
7
|
-
checksum: sha256-
|
|
7
|
+
checksum: sha256-3fc9f2966804381cb9e2b5f52d44a0c12c857f243b151a93a813c6345574f07f
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# MyAudienceAPI
|
|
@@ -136,4 +136,19 @@ myapi audience create "EU growth-stage SaaS accounts" \
|
|
|
136
136
|
- Audiences are per-org. Two orgs can have audiences with the same name; ids are globally unique.
|
|
137
137
|
- Look before you delete: confirm the target with `myapi audience get <id>`, pass `--org` explicitly; delete verbs require `--yes` in non-interactive runs.
|
|
138
138
|
|
|
139
|
+
## HTTP (from deployed code)
|
|
140
|
+
|
|
141
|
+
<!-- http:start -->
|
|
142
|
+
<!-- generated by `npm run canonical-sync` — do not edit -->
|
|
143
|
+
```
|
|
144
|
+
base https://api.myapihq.com
|
|
145
|
+
path POST /audience/orgs/{org_id}/audiences
|
|
146
|
+
auth Authorization: Bearer <key> (fn: env.__MYAPI_KEY · container: env.MYAPI_KEY)
|
|
147
|
+
reply { "success": true, "data": …, "error": null, "meta": {…} }
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
- **Per-slot host** — do not assume one host serves every slot.
|
|
151
|
+
- **Org id goes in the PATH** — there is no `X-Org-Id` header.
|
|
152
|
+
<!-- http:end -->
|
|
153
|
+
|
|
139
154
|
Run `myapi audience --help` for full flag reference.
|
|
@@ -4,7 +4,7 @@ version: 1.0.0
|
|
|
4
4
|
description: >
|
|
5
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
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-
|
|
7
|
+
checksum: sha256-07690e940717e8f65c195f9fbecdc1def9372edfd52dea19f6570227008d28ad
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# MyAuthAPI
|
|
@@ -121,4 +121,19 @@ with no email — for throwaway or machine-owned orgs. It cannot receive
|
|
|
121
121
|
password resets or magic links, so attach a real identity before anything
|
|
122
122
|
depends on it. `myapi status` shows `Type: anonymous`.
|
|
123
123
|
|
|
124
|
-
**End-to-end example:** `examples/authenticated-app/` walks the full seam — hosted login → token verification → per-user KV record → deployed container — including the parts that cost real users hours (verify the id_token for identity; the access token is a bearer credential for `<issuer>/userinfo`).
|
|
124
|
+
**End-to-end example:** `examples/authenticated-app/` in github.com/myapihq/myapi walks the full seam — hosted login → token verification → per-user KV record → deployed container — including the parts that cost real users hours (verify the id_token for identity; the access token is a bearer credential for `<issuer>/userinfo`).
|
|
125
|
+
|
|
126
|
+
## HTTP (from deployed code)
|
|
127
|
+
|
|
128
|
+
<!-- http:start -->
|
|
129
|
+
<!-- generated by `npm run canonical-sync` — do not edit -->
|
|
130
|
+
```
|
|
131
|
+
base https://api.myapihq.com
|
|
132
|
+
path POST /auth/orgs/{org_id}/tenant
|
|
133
|
+
auth Authorization: Bearer <key> (fn: env.__MYAPI_KEY · container: env.MYAPI_KEY)
|
|
134
|
+
reply { "success": true, "data": …, "error": null, "meta": {…} }
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
- **Per-slot host** — do not assume one host serves every slot.
|
|
138
|
+
- **Org id goes in the PATH** — there is no `X-Org-Id` header.
|
|
139
|
+
<!-- http:end -->
|
|
@@ -4,7 +4,7 @@ version: 1.0.0
|
|
|
4
4
|
description: >
|
|
5
5
|
Company database backed by the Goldfox crawl. Filter companies by Goldfox confidence tier, country/TLD consistency, behavioral page signals (has_careers_page, has_investors_page, has_shop_page, has_c_level, has_decision_maker), legal-entity status, headcount, and source-URL count. Account-based targeting and B2B firmographics.
|
|
6
6
|
triggers: [companies, accounts, firmographics, abm, search, filter, goldfox, careers signal, investors, c-level, shop, b2b targeting]
|
|
7
|
-
checksum: sha256-
|
|
7
|
+
checksum: sha256-5204c6218af2d4c52b1b81aa0d917b69c863be1d3c0384d2d2f7d9dda1587534
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# MyCompanyAPI
|
|
@@ -107,4 +107,19 @@ myapi audience members $AID --limit 50 --json > accounts.json
|
|
|
107
107
|
- `keyword` is a substring match on the company's **domain** — use `--keyword stripe` to find domains containing "stripe".
|
|
108
108
|
- For a persistent account list, use `my-audience-api` with `--from company`.
|
|
109
109
|
|
|
110
|
+
## HTTP (from deployed code)
|
|
111
|
+
|
|
112
|
+
<!-- http:start -->
|
|
113
|
+
<!-- generated by `npm run canonical-sync` — do not edit -->
|
|
114
|
+
```
|
|
115
|
+
base https://api.myapihq.com
|
|
116
|
+
path POST /company/orgs/{org_id}/search
|
|
117
|
+
auth Authorization: Bearer <key> (fn: env.__MYAPI_KEY · container: env.MYAPI_KEY)
|
|
118
|
+
reply { "success": true, "data": …, "error": null, "meta": {…} }
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
- **Per-slot host** — do not assume one host serves every slot.
|
|
122
|
+
- **Org id goes in the PATH** — there is no `X-Org-Id` header.
|
|
123
|
+
<!-- http:end -->
|
|
124
|
+
|
|
110
125
|
Run `myapi company --help` for full flag reference.
|
|
@@ -4,7 +4,7 @@ version: 1.0.0
|
|
|
4
4
|
description: >
|
|
5
5
|
Run containers on demand — long-running services, background workers, and scheduled jobs. The heavier-duty sibling of edge functions, for native deps and long execution.
|
|
6
6
|
triggers: [container, cloud run, dynamic app, custom domain app, service, worker, scheduled job, deploy container, docker image]
|
|
7
|
-
checksum: sha256-
|
|
7
|
+
checksum: sha256-a5aabfe95b85f1e6ceb2b9254441183d540e81f888cefbdcf302385b95db2fd0
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# MyContainerAPI
|
|
@@ -92,14 +92,14 @@ myapi container deploy <id> --source ./my-app
|
|
|
92
92
|
# 2b. Or ship an image you already built and pushed.
|
|
93
93
|
myapi container deploy <id> registry.example.com/my-app:v1
|
|
94
94
|
|
|
95
|
-
#
|
|
96
|
-
#
|
|
95
|
+
# A plain deploy takes 100% of traffic the moment it lands. Gate it with
|
|
96
|
+
# --smoke, or hold it back with --no-promote and test the revision yourself.
|
|
97
97
|
|
|
98
|
-
# 3.
|
|
99
|
-
#
|
|
98
|
+
# 3. Verify content, not status: a build whose frontend never bundled
|
|
99
|
+
# still binds its port and returns 200.
|
|
100
100
|
curl -s https://<your-domain>/ | grep -q 'assets/' || echo "BROKEN BUILD"
|
|
101
101
|
|
|
102
|
-
#
|
|
102
|
+
# 4. Serve it on a custom domain. The parent domain must already be
|
|
103
103
|
# registered: myapi domain register synthesisdaily.com
|
|
104
104
|
myapi container domain <id> app.synthesisdaily.com
|
|
105
105
|
# → app.synthesisdaily.com now serves the container over HTTPS
|
|
@@ -150,6 +150,21 @@ service costs nothing while idle.
|
|
|
150
150
|
`invalid_json_response`. Build the tarball yourself and pass
|
|
151
151
|
`--source ctx.tar.gz`, or keep the directory clean.
|
|
152
152
|
|
|
153
|
+
## HTTP (from deployed code)
|
|
154
|
+
|
|
155
|
+
<!-- http:start -->
|
|
156
|
+
<!-- generated by `npm run canonical-sync` — do not edit -->
|
|
157
|
+
```
|
|
158
|
+
base https://api.myapihq.com
|
|
159
|
+
path POST /container/orgs/{org_id}/containers
|
|
160
|
+
auth Authorization: Bearer <key> (fn: env.__MYAPI_KEY · container: env.MYAPI_KEY)
|
|
161
|
+
reply { "success": true, "data": …, "error": null, "meta": {…} }
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
- **Per-slot host** — do not assume one host serves every slot.
|
|
165
|
+
- **Org id goes in the PATH** — there is no `X-Org-Id` header.
|
|
166
|
+
<!-- http:end -->
|
|
167
|
+
|
|
153
168
|
Run `myapi container --help` for the full flag reference.
|
|
154
169
|
|
|
155
|
-
**End-to-end example:** `examples/authenticated-app/` walks the full seam — hosted login → token verification → per-user KV record → deployed container
|
|
170
|
+
**End-to-end example:** `examples/authenticated-app/` in github.com/myapihq/myapi walks the full seam — hosted login → token verification → per-user KV record → deployed container. Every constraint it hits is in **Runtime constraints** above.
|
|
@@ -4,7 +4,7 @@ version: 1.0.0
|
|
|
4
4
|
description: >
|
|
5
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
6
|
triggers: [crm, contact, company, lead, engagement, pipeline, lifecycle, qualified, customer, webhook ingest, promote]
|
|
7
|
-
checksum: sha256-
|
|
7
|
+
checksum: sha256-3f840c8d7205d6a3eacc7c2be3ba2580a52a1964c085af241fd9ad67d48e19b6
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# MyCRMAPI
|
|
@@ -167,4 +167,19 @@ myapi crm contacts events <id> --kind webhook_received
|
|
|
167
167
|
- **Only `webhook_received` fires today.** Email and pixel auto-ingest are coming; the CLI surface will not change.
|
|
168
168
|
- **Free in v1.** Metered later if usage warrants.
|
|
169
169
|
|
|
170
|
+
## HTTP (from deployed code)
|
|
171
|
+
|
|
172
|
+
<!-- http:start -->
|
|
173
|
+
<!-- generated by `npm run canonical-sync` — do not edit -->
|
|
174
|
+
```
|
|
175
|
+
base https://api.myapihq.com
|
|
176
|
+
path POST /crm/orgs/{org_id}/contacts
|
|
177
|
+
auth Authorization: Bearer <key> (fn: env.__MYAPI_KEY · container: env.MYAPI_KEY)
|
|
178
|
+
reply { "success": true, "data": …, "error": null, "meta": {…} }
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
- **Per-slot host** — do not assume one host serves every slot.
|
|
182
|
+
- **Org id goes in the PATH** — there is no `X-Org-Id` header.
|
|
183
|
+
<!-- http:end -->
|
|
184
|
+
|
|
170
185
|
Run `myapi crm --help` or `myapi crm <namespace> --help` for inline reference.
|
|
@@ -4,7 +4,7 @@ version: 1.0.0
|
|
|
4
4
|
description: >
|
|
5
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
6
|
triggers: [database, kv, key value, namespace, store, state, etag, cas, session, idempotency]
|
|
7
|
-
checksum: sha256-
|
|
7
|
+
checksum: sha256-9b6f14fa5b0115ce042c71f861cb71ec8993aa68447d740b63f5b3689c23b629
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# MyDatabaseAPI
|
|
@@ -105,26 +105,22 @@ myapi database get "by-email:$EMAIL" --ns users --json | jq -r .value
|
|
|
105
105
|
- **Free in v1.** Metered later if usage shows a need. Cost discipline still applies — store data, not blobs.
|
|
106
106
|
|
|
107
107
|
|
|
108
|
-
##
|
|
109
|
-
|
|
110
|
-
The CLI is not what runs in production — a deployed function or container calls
|
|
111
|
-
the HTTP API directly. That surface was previously only discoverable by
|
|
112
|
-
grepping the CLI bundle, which cost one team an hour per slot.
|
|
108
|
+
## HTTP (from deployed code)
|
|
113
109
|
|
|
110
|
+
<!-- http:start -->
|
|
111
|
+
<!-- generated by `npm run canonical-sync` — do not edit -->
|
|
114
112
|
```
|
|
115
|
-
base
|
|
116
|
-
path
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
reply { "success": true, "data": …, "error": null, "meta": {…} }
|
|
121
|
-
Unwrap `data`. On failure `success` is false and `error` is
|
|
122
|
-
{ code, message }.
|
|
113
|
+
base https://api.myapihq.com
|
|
114
|
+
path PUT /database/orgs/{org_id}/namespaces/{ns}/keys/{key}
|
|
115
|
+
body writes are WRAPPED: {"value": <json>} — not the bare value
|
|
116
|
+
auth Authorization: Bearer <key> (fn: env.__MYAPI_KEY · container: env.MYAPI_KEY)
|
|
117
|
+
reply { "success": true, "data": …, "error": null, "meta": {…} }
|
|
123
118
|
```
|
|
124
119
|
|
|
125
|
-
**
|
|
126
|
-
**
|
|
120
|
+
- **Per-slot host** — do not assume one host serves every slot.
|
|
121
|
+
- **Org id goes in the PATH** — there is no `X-Org-Id` header.
|
|
122
|
+
<!-- http:end -->
|
|
127
123
|
|
|
128
124
|
Run `myapi database --help` for inline reference.
|
|
129
125
|
|
|
130
|
-
**End-to-end example:** `examples/authenticated-app/` walks the full seam — hosted login → token verification → per-user KV record → deployed container — including the parts that cost real users hours (KV writes must be wrapped as `{"value": …}`).
|
|
126
|
+
**End-to-end example:** `examples/authenticated-app/` in github.com/myapihq/myapi walks the full seam — hosted login → token verification → per-user KV record → deployed container — including the parts that cost real users hours (KV writes must be wrapped as `{"value": …}`).
|
|
@@ -4,7 +4,7 @@ version: 1.0.0
|
|
|
4
4
|
description: >
|
|
5
5
|
Register new domains and manage edge settings. Required before a funnel can go live on a custom URL.
|
|
6
6
|
triggers: [domain, register domain, dns, custom domain, edge, cdn, security level, browser check, renew, namecheap]
|
|
7
|
-
checksum: sha256-
|
|
7
|
+
checksum: sha256-ffe00d434534f444320a3e84323e87168c0c5797445fa0f39eeb55ad8278f721
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# MyDomainAPI
|
|
@@ -133,4 +133,19 @@ myapi domain records create <domain> --type CNAME --name app --content x.com --p
|
|
|
133
133
|
reassign path, so pass `--org` explicitly and check `domain list --filter all`
|
|
134
134
|
first.
|
|
135
135
|
|
|
136
|
+
## HTTP (from deployed code)
|
|
137
|
+
|
|
138
|
+
<!-- http:start -->
|
|
139
|
+
<!-- generated by `npm run canonical-sync` — do not edit -->
|
|
140
|
+
```
|
|
141
|
+
base https://api.mydomainapi.com
|
|
142
|
+
path GET /domain/orgs/{org_id}/list
|
|
143
|
+
auth Authorization: Bearer <key> (fn: env.__MYAPI_KEY · container: env.MYAPI_KEY)
|
|
144
|
+
reply { "success": true, "data": …, "error": null, "meta": {…} }
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
- **Per-slot host** — do not assume one host serves every slot.
|
|
148
|
+
- **Org id goes in the PATH** — there is no `X-Org-Id` header.
|
|
149
|
+
<!-- http:end -->
|
|
150
|
+
|
|
136
151
|
Run `myapi domain --help` or `myapi domain <subcommand> --help` for full flag reference.
|
|
@@ -4,7 +4,7 @@ version: 1.0.0
|
|
|
4
4
|
description: >
|
|
5
5
|
Send transactional and bulk email from your own domain. Create mailboxes, send/receive messages, generate AI templates, and manage warmup.
|
|
6
6
|
triggers: [email, mailbox, send email, transactional email, template, warmup, inbox, outbox, ses, sender reputation]
|
|
7
|
-
checksum: sha256-
|
|
7
|
+
checksum: sha256-98aedd0274a450fdd68a2d0cfe3a8af33520c58b2ce6e7cfaee7840fd5526aa6
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# MyEmailAPI
|
|
@@ -64,6 +64,7 @@ myapi email warmup stats --address hello@yourdomain.com
|
|
|
64
64
|
|
|
65
65
|
- A mailbox is uniquely identified by its address (`username@domain`).
|
|
66
66
|
- Sending is opt-in per mailbox. Newly-created mailboxes can receive but not send until `activate-sending` runs.
|
|
67
|
+
- **`402`** — `INSUFFICIENT_FUNDS`: top up or enable `myapi billing auto-recharge`. `SPEND_CAP_EXCEEDED`: raise your own ceiling with `myapi billing spend-cap`.
|
|
67
68
|
- Templates are org-scoped. Set a default org once: `myapi config set-org <id>`.
|
|
68
69
|
|
|
69
70
|
|
|
@@ -81,24 +82,19 @@ Two things that read as contradictory and are not:
|
|
|
81
82
|
to run Google Workspace or another provider on the apex, check the existing
|
|
82
83
|
records first with `myapi domain records <domain>`.
|
|
83
84
|
|
|
84
|
-
##
|
|
85
|
-
|
|
86
|
-
The CLI is not what runs in production — a deployed function or container calls
|
|
87
|
-
the HTTP API directly. That surface was previously only discoverable by
|
|
88
|
-
grepping the CLI bundle, which cost one team an hour per slot.
|
|
85
|
+
## HTTP (from deployed code)
|
|
89
86
|
|
|
87
|
+
<!-- http:start -->
|
|
88
|
+
<!-- generated by `npm run canonical-sync` — do not edit -->
|
|
90
89
|
```
|
|
91
|
-
base
|
|
92
|
-
path
|
|
93
|
-
auth
|
|
94
|
-
|
|
95
|
-
body application/json
|
|
96
|
-
reply { "success": true, "data": …, "error": null, "meta": {…} }
|
|
97
|
-
Unwrap `data`. On failure `success` is false and `error` is
|
|
98
|
-
{ code, message }.
|
|
90
|
+
base https://api.myemailapi.com
|
|
91
|
+
path POST /email/send
|
|
92
|
+
auth Authorization: Bearer <key> (fn: env.__MYAPI_KEY · container: env.MYAPI_KEY)
|
|
93
|
+
reply { "success": true, "data": …, "error": null, "meta": {…} }
|
|
99
94
|
```
|
|
100
95
|
|
|
101
|
-
**
|
|
102
|
-
**
|
|
96
|
+
- **Per-slot host** — do not assume one host serves every slot.
|
|
97
|
+
- **Account-scoped, not org-scoped** — no `{org_id}` segment; the key identifies the account.
|
|
98
|
+
<!-- http:end -->
|
|
103
99
|
|
|
104
100
|
Run `myapi email --help` or `myapi email <namespace> --help` for full flag reference.
|
|
@@ -4,7 +4,7 @@ version: 1.0.0
|
|
|
4
4
|
description: >
|
|
5
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
6
|
triggers: [email verify, email validation, deliverability, smtp, syntax check, dns mx, microsoft, mx lookup, bounce prevention]
|
|
7
|
-
checksum: sha256-
|
|
7
|
+
checksum: sha256-c8ae836c355066eee8a12753f818d3a90c35b99983d74913c8fc76edcc99668f
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# MyEmailVerifyAPI
|
|
@@ -90,4 +90,19 @@ done < emails.txt | grep -v ' undeliverable$' > verified.txt
|
|
|
90
90
|
- 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.
|
|
91
91
|
- Verification is per-org; you'll get rate-limited if you blast more than ~1 req/sec per key.
|
|
92
92
|
|
|
93
|
+
## HTTP (from deployed code)
|
|
94
|
+
|
|
95
|
+
<!-- http:start -->
|
|
96
|
+
<!-- generated by `npm run canonical-sync` — do not edit -->
|
|
97
|
+
```
|
|
98
|
+
base https://api.myemailapi.com
|
|
99
|
+
path POST /email/orgs/{org_id}/verify
|
|
100
|
+
auth Authorization: Bearer <key> (fn: env.__MYAPI_KEY · container: env.MYAPI_KEY)
|
|
101
|
+
reply { "success": true, "data": …, "error": null, "meta": {…} }
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
- **Per-slot host** — do not assume one host serves every slot.
|
|
105
|
+
- **Org id goes in the PATH** — there is no `X-Org-Id` header.
|
|
106
|
+
<!-- http:end -->
|
|
107
|
+
|
|
93
108
|
Run `myapi email verify --help` for inline reference.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
# my-feedback-api
|
|
3
|
+
|
|
4
|
+
The loop back from the people using what you built. A page collects feedback with a public widget key that authenticates nobody; you read, filter, and close it.
|
|
5
|
+
|
|
6
|
+
## What it does
|
|
7
|
+
|
|
8
|
+
- Public widget keys — embed in page source, restrict by origin, revoke without losing collected feedback
|
|
9
|
+
- Three kinds (`bug` | `issue` | `suggestion`), chosen by the reporter rather than inferred
|
|
10
|
+
- Filterable listing by kind and status, newest first, paged with `--limit` / `--offset`
|
|
11
|
+
- `resolve` closes an item; unknown ids answer identically so ids can't be probed across orgs
|
|
12
|
+
|
|
13
|
+
## Quickstart
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
myapi feedback widget create marketing --origins example.com,www.example.com
|
|
17
|
+
myapi feedback list --status open
|
|
18
|
+
myapi feedback resolve <id>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Authentication
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
export MYAPI_KEY=hq_live_...
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Requires `api_key` + `org_id` from **myapihq**. The widget key is separate and deliberately public — it goes in your page source.
|
|
28
|
+
|
|
29
|
+
## Documentation
|
|
30
|
+
|
|
31
|
+
Full command reference and why `kind` is a claim rather than a guess: see `SKILL.md`.
|
|
32
|
+
|
|
33
|
+
Run `myapi feedback --help` for inline reference.
|