@myapihq/sdk 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.
- package/dist/audience.d.ts +71 -0
- package/dist/audience.js +54 -0
- package/dist/client.d.ts +1 -1
- package/dist/client.js +8 -1
- package/dist/company.d.ts +20 -0
- package/dist/company.js +25 -0
- package/dist/config.d.ts +6 -0
- package/dist/config.js +20 -2
- package/dist/crm.d.ts +122 -0
- package/dist/crm.js +84 -0
- package/dist/database.d.ts +36 -0
- package/dist/database.js +65 -0
- package/dist/domain.d.ts +19 -1
- package/dist/domain.js +22 -2
- package/dist/email-verify.d.ts +30 -0
- package/dist/email-verify.js +17 -0
- package/dist/email.d.ts +33 -0
- package/dist/email.js +53 -0
- package/dist/exposes.d.ts +2 -0
- package/dist/exposes.js +14 -0
- package/dist/funnel.d.ts +10 -0
- package/dist/funnel.js +20 -0
- package/dist/hq.d.ts +10 -0
- package/dist/hq.js +28 -0
- package/dist/image.d.ts +14 -0
- package/dist/image.js +12 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.js +13 -2
- package/dist/llm.d.ts +50 -0
- package/dist/llm.js +27 -0
- package/dist/people.d.ts +54 -0
- package/dist/people.js +22 -0
- package/dist/pixel.d.ts +3 -0
- package/dist/pixel.js +15 -0
- package/dist/services.d.ts +17 -0
- package/dist/services.js +190 -0
- package/dist/storage.d.ts +3 -1
- package/dist/storage.js +7 -0
- package/dist/url.d.ts +2 -0
- package/dist/url.js +4 -0
- package/dist/webhook.d.ts +8 -1
- package/dist/webhook.js +14 -2
- package/dist/workflow.d.ts +2 -0
- package/dist/workflow.js +12 -0
- package/package.json +2 -1
- package/scripts/scaffold-sdk.js +501 -0
- package/src/audience.ts +162 -0
- package/src/client.ts +9 -1
- package/src/company.ts +48 -0
- package/src/config.ts +21 -1
- package/src/crm.ts +235 -0
- package/src/database.ts +103 -0
- package/src/domain.ts +44 -2
- package/src/email.ts +84 -0
- package/src/exposes.ts +16 -0
- package/src/funnel.ts +34 -0
- package/src/hq.ts +41 -0
- package/src/image.ts +31 -0
- package/src/index.ts +12 -1
- package/src/llm.ts +86 -0
- package/src/people.ts +84 -0
- package/src/pixel.ts +16 -0
- package/src/services.ts +220 -0
- package/src/storage.ts +15 -6
- package/src/url.ts +5 -0
- package/src/webhook.ts +25 -2
- package/src/workflow.ts +13 -0
package/src/hq.ts
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
import { request } from './client';
|
|
2
2
|
import { HQ_BASE as BASE_URL } from './config';
|
|
3
|
+
import type { Exposes } from './exposes';
|
|
4
|
+
|
|
5
|
+
export const EXPOSES: Exposes = [
|
|
6
|
+
'POST /hq/account/anonymous',
|
|
7
|
+
'POST /hq/account/send-code',
|
|
8
|
+
'POST /hq/account/verify-code',
|
|
9
|
+
'PATCH /hq/account/upgrade',
|
|
10
|
+
'GET /hq/account/me',
|
|
11
|
+
'GET /hq/account/free-tier',
|
|
12
|
+
'POST /hq/account/create/key',
|
|
13
|
+
'GET /hq/account/keys',
|
|
14
|
+
'DELETE /hq/account/delete/key/{key_id}',
|
|
15
|
+
'POST /hq/orgs',
|
|
16
|
+
'GET /hq/orgs',
|
|
17
|
+
'GET /hq/orgs/{org_id}',
|
|
18
|
+
'PATCH /hq/orgs/{org_id}',
|
|
19
|
+
'DELETE /hq/orgs/{org_id}',
|
|
20
|
+
'POST /hq/org-imports',
|
|
21
|
+
'GET /hq/org-imports/{import_id}',
|
|
22
|
+
'POST /hq/org-imports/{import_id}/confirm',
|
|
23
|
+
'GET /hq/billing/balance',
|
|
24
|
+
'GET /hq/billing/history',
|
|
25
|
+
'POST /hq/billing/setup-payment',
|
|
26
|
+
'POST /hq/billing/topup',
|
|
27
|
+
];
|
|
3
28
|
|
|
4
29
|
export interface Org {
|
|
5
30
|
id: string;
|
|
@@ -61,6 +86,22 @@ export async function upgradeAccount(apiKey: string, email: string): Promise<Aut
|
|
|
61
86
|
return request('PATCH', `${BASE_URL}/hq/account/upgrade`, apiKey, { email });
|
|
62
87
|
}
|
|
63
88
|
|
|
89
|
+
// The backend returns an array of per-service free-tier rows, or null if the
|
|
90
|
+
// account has no free-tier allocations. (Previously typed as a single scalar
|
|
91
|
+
// object — that was incorrect and surfaced as `undefined/undefined` in the
|
|
92
|
+
// CLI's whoami output.)
|
|
93
|
+
export type FreeTierEntry = {
|
|
94
|
+
service: string;
|
|
95
|
+
used: number;
|
|
96
|
+
allowance: number;
|
|
97
|
+
remaining?: number;
|
|
98
|
+
reset_at?: string;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export async function getFreeTier(apiKey: string): Promise<FreeTierEntry[] | null> {
|
|
102
|
+
return request('GET', `${BASE_URL}/hq/account/free-tier`, apiKey);
|
|
103
|
+
}
|
|
104
|
+
|
|
64
105
|
export async function getAccount(apiKey: string): Promise<AccountInfo> {
|
|
65
106
|
return request('GET', `${BASE_URL}/hq/account/me`, apiKey);
|
|
66
107
|
}
|
package/src/image.ts
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
import { request } from './client';
|
|
2
2
|
import { IMAGE_BASE as BASE_URL } from './config';
|
|
3
|
+
import type { Exposes } from './exposes';
|
|
4
|
+
|
|
5
|
+
export const EXPOSES: Exposes = [
|
|
6
|
+
'POST /image/orgs/{org_id}/generate',
|
|
7
|
+
'GET /image/orgs/{org_id}/jobs/{job_id}',
|
|
8
|
+
'GET /image/orgs/{org_id}/list',
|
|
9
|
+
'GET /image/orgs/{org_id}/models',
|
|
10
|
+
'DELETE /image/orgs/{org_id}/images/{image_id}',
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
// Catalog row from GET /image/.../models. Mirrors the shape of the LLM
|
|
14
|
+
// model catalog but with per-image pricing (image gen is priced per
|
|
15
|
+
// image, not per token).
|
|
16
|
+
export interface ImageModel {
|
|
17
|
+
id: string;
|
|
18
|
+
kind: 'image';
|
|
19
|
+
aspect_ratios: string[]; // e.g. ['1:1', '16:9', '9:16', '4:3', '3:4']
|
|
20
|
+
default_size: string; // e.g. '1024x1024'
|
|
21
|
+
cost_per_image_usd: number;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface ImageModelsResponse {
|
|
25
|
+
models: ImageModel[];
|
|
26
|
+
}
|
|
3
27
|
|
|
4
28
|
|
|
5
29
|
|
|
@@ -15,6 +39,9 @@ export interface ImageJob {
|
|
|
15
39
|
|
|
16
40
|
export async function generateImage(apiKey: string, orgId: string, payload: {
|
|
17
41
|
prompt: string;
|
|
42
|
+
// Optional model id; must be in GET /image/.../models. Defaults
|
|
43
|
+
// server-side to gemini-2.5-flash-image.
|
|
44
|
+
model?: string;
|
|
18
45
|
aspect_ratio?: '1:1' | '16:9' | '9:16' | '4:3' | '3:4';
|
|
19
46
|
style?: string;
|
|
20
47
|
colors?: string;
|
|
@@ -34,3 +61,7 @@ export async function listImages(apiKey: string, orgId: string): Promise<ImageJo
|
|
|
34
61
|
export async function deleteImage(apiKey: string, orgId: string, jobId: string): Promise<void> {
|
|
35
62
|
return request('DELETE', `${BASE_URL}/image/orgs/${encodeURIComponent(orgId)}/images/${encodeURIComponent(jobId)}`, apiKey);
|
|
36
63
|
}
|
|
64
|
+
|
|
65
|
+
export async function listModels(apiKey: string, orgId: string): Promise<ImageModelsResponse> {
|
|
66
|
+
return request('GET', `${BASE_URL}/image/orgs/${encodeURIComponent(orgId)}/models`, apiKey);
|
|
67
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
export * from './types';
|
|
2
2
|
export * from './client';
|
|
3
|
-
|
|
3
|
+
// Note: config constants (STORAGE_BASE etc.) are NOT re-exported from the
|
|
4
|
+
// barrel. TypeScript compiles `export * from './config'` to a runtime
|
|
5
|
+
// `__exportStar` call that Node's cjs-module-lexer can't see through, so
|
|
6
|
+
// downstream ESM consumers fail with "Named export not found" against the
|
|
7
|
+
// CJS-compiled SDK. If you need a base URL in a downstream package, mirror
|
|
8
|
+
// the constant locally — it's one line and the comment makes it obvious.
|
|
4
9
|
export * as hq from './hq';
|
|
5
10
|
export * as domain from './domain';
|
|
6
11
|
export * as email from './email';
|
|
@@ -11,3 +16,9 @@ export * as storage from './storage';
|
|
|
11
16
|
export * as webhook from './webhook';
|
|
12
17
|
export * as workflow from './workflow';
|
|
13
18
|
export * as url from './url';
|
|
19
|
+
export * as people from './people';
|
|
20
|
+
export * as company from './company';
|
|
21
|
+
export * as audience from './audience';
|
|
22
|
+
export * as llm from './llm';
|
|
23
|
+
export * as database from './database';
|
|
24
|
+
export * as crm from './crm';
|
package/src/llm.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// Scaffolded from schema by scripts/scaffold-sdk.js — DO NOT remove the
|
|
2
|
+
// EXPOSES array (the coverage tool verifies it against the live schema).
|
|
3
|
+
// Types and function names ARE editable; re-running the scaffolder against
|
|
4
|
+
// a service whose config has been changed will diff vs. existing file
|
|
5
|
+
// (use --dry-run to inspect).
|
|
6
|
+
|
|
7
|
+
import { request } from './client';
|
|
8
|
+
import { LLM_BASE as BASE_URL } from './config';
|
|
9
|
+
import type { Exposes } from './exposes';
|
|
10
|
+
|
|
11
|
+
export const EXPOSES: Exposes = [
|
|
12
|
+
'POST /llm/orgs/{org_id}/complete',
|
|
13
|
+
'POST /llm/orgs/{org_id}/embed',
|
|
14
|
+
'GET /llm/orgs/{org_id}/models',
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
export type Role = 'system' | 'user' | 'assistant';
|
|
18
|
+
|
|
19
|
+
export interface Message {
|
|
20
|
+
role: Role;
|
|
21
|
+
content: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface CompleteRequest {
|
|
25
|
+
model: string;
|
|
26
|
+
messages: Message[];
|
|
27
|
+
max_tokens?: number;
|
|
28
|
+
temperature?: number;
|
|
29
|
+
stop?: string[];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface CompleteResponse {
|
|
33
|
+
model: string;
|
|
34
|
+
content: string;
|
|
35
|
+
finish_reason: string; // 'stop' | 'length' | 'safety' | ...
|
|
36
|
+
usage: {
|
|
37
|
+
input_tokens: number;
|
|
38
|
+
output_tokens: number;
|
|
39
|
+
cost_usd: number;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface EmbedRequest {
|
|
44
|
+
model: string;
|
|
45
|
+
input: string | string[]; // single string or batch
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Always returned as an array — even for a single-string input you get a
|
|
49
|
+
// one-element array. Each element is the dense vector as a flat number[].
|
|
50
|
+
// Embed-only usage has no output_tokens.
|
|
51
|
+
export interface EmbedResponse {
|
|
52
|
+
model: string;
|
|
53
|
+
embeddings: number[][];
|
|
54
|
+
usage: {
|
|
55
|
+
input_tokens: number;
|
|
56
|
+
cost_usd: number;
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Catalog row. 'chat' models have context + output_per_1m; 'embed' models
|
|
61
|
+
// have dimensions instead. Pricing is per 1M tokens at upstream rates
|
|
62
|
+
// (we resell at-cost while building our own inference).
|
|
63
|
+
export interface Model {
|
|
64
|
+
id: string;
|
|
65
|
+
kind: 'chat' | 'embed';
|
|
66
|
+
context?: number;
|
|
67
|
+
dimensions?: number;
|
|
68
|
+
input_per_1m: number;
|
|
69
|
+
output_per_1m?: number;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface ModelsResponse {
|
|
73
|
+
models: Model[];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export async function complete(apiKey: string, orgId: string, req: CompleteRequest): Promise<CompleteResponse> {
|
|
77
|
+
return request('POST', `${BASE_URL}/llm/orgs/${encodeURIComponent(orgId)}/complete`, apiKey, req);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export async function embed(apiKey: string, orgId: string, req: EmbedRequest): Promise<EmbedResponse> {
|
|
81
|
+
return request('POST', `${BASE_URL}/llm/orgs/${encodeURIComponent(orgId)}/embed`, apiKey, req);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export async function listModels(apiKey: string, orgId: string): Promise<ModelsResponse> {
|
|
85
|
+
return request('GET', `${BASE_URL}/llm/orgs/${encodeURIComponent(orgId)}/models`, apiKey);
|
|
86
|
+
}
|
package/src/people.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// Scaffolded from schema by scripts/scaffold-sdk.js — DO NOT remove the
|
|
2
|
+
// EXPOSES array (the coverage tool verifies it against the live schema).
|
|
3
|
+
// Types and function names ARE editable; re-running the scaffolder against
|
|
4
|
+
// a service whose config has been changed will diff vs. existing file
|
|
5
|
+
// (use --dry-run to inspect).
|
|
6
|
+
|
|
7
|
+
import { request } from './client';
|
|
8
|
+
import { PEOPLE_BASE as BASE_URL } from './config';
|
|
9
|
+
import type { Exposes } from './exposes';
|
|
10
|
+
|
|
11
|
+
import type { SearchFilter } from './audience';
|
|
12
|
+
|
|
13
|
+
export const EXPOSES: Exposes = [
|
|
14
|
+
'POST /people/orgs/{org_id}/search',
|
|
15
|
+
'GET /people/orgs/{org_id}/{person_id}',
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
export interface Location {
|
|
19
|
+
city?: string;
|
|
20
|
+
region?: string;
|
|
21
|
+
country?: string; // ISO 3166-1 alpha-2
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Goldfox-sourced person row. The data model is crawl-derived signals over
|
|
25
|
+
// scraped contact pages; rich on quality tiers and behavioral booleans,
|
|
26
|
+
// thin on legacy CRM fields (no title / function / industry as response
|
|
27
|
+
// columns — many of those moved to filterable inputs only).
|
|
28
|
+
export interface Person {
|
|
29
|
+
id: string;
|
|
30
|
+
full_name: string;
|
|
31
|
+
first_name?: string;
|
|
32
|
+
last_name?: string;
|
|
33
|
+
email?: string;
|
|
34
|
+
email_type?: string; // corporate | freemail | role_based | other_corporate
|
|
35
|
+
link_confidence?: number; // 0..1 — 1.0 = email-domain match (definitive)
|
|
36
|
+
location: Location;
|
|
37
|
+
company_id: string;
|
|
38
|
+
company: PersonCompany;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Person.company embeds the same shape returned by /company/search results.
|
|
42
|
+
// PersonCompany is an alias for Company — the company sub-object on a person
|
|
43
|
+
// row is identical to a standalone company row.
|
|
44
|
+
export interface PersonCompany {
|
|
45
|
+
id: string;
|
|
46
|
+
domain?: string;
|
|
47
|
+
name: string;
|
|
48
|
+
general_phone?: string;
|
|
49
|
+
address?: string;
|
|
50
|
+
is_registered_entity: boolean;
|
|
51
|
+
confidence: 'high' | 'low' | 'very_low';
|
|
52
|
+
country?: string;
|
|
53
|
+
country_consistent: boolean;
|
|
54
|
+
tld_class?: string; // cctld | generic | vanity | low_trust | other
|
|
55
|
+
has_careers_page: boolean;
|
|
56
|
+
has_investors_page: boolean;
|
|
57
|
+
has_shop_page: boolean;
|
|
58
|
+
has_blog: boolean;
|
|
59
|
+
has_c_level: boolean;
|
|
60
|
+
has_decision_maker: boolean;
|
|
61
|
+
headcount_lower_bound: number;
|
|
62
|
+
org_breadth: number;
|
|
63
|
+
source_count: number;
|
|
64
|
+
subdomain_variety: number;
|
|
65
|
+
multilingual: boolean;
|
|
66
|
+
language_count: number;
|
|
67
|
+
location?: Location;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface PeopleSearchResult {
|
|
71
|
+
people: Person[];
|
|
72
|
+
total: number;
|
|
73
|
+
limit: number;
|
|
74
|
+
offset: number;
|
|
75
|
+
has_more: boolean;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export async function searchPeople(apiKey: string, orgId: string, filter: SearchFilter): Promise<PeopleSearchResult> {
|
|
79
|
+
return request('POST', `${BASE_URL}/people/orgs/${encodeURIComponent(orgId)}/search`, apiKey, filter);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export async function getPerson(apiKey: string, orgId: string, personId: string): Promise<Person> {
|
|
83
|
+
return request('GET', `${BASE_URL}/people/orgs/${encodeURIComponent(orgId)}/${encodeURIComponent(personId)}`, apiKey);
|
|
84
|
+
}
|
package/src/pixel.ts
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import { request } from './client';
|
|
2
2
|
import { PIXEL_BASE as BASE_URL } from './config';
|
|
3
|
+
import type { Exposes } from './exposes';
|
|
4
|
+
|
|
5
|
+
export const EXPOSES: Exposes = [
|
|
6
|
+
'GET /pixel/orgs/{org_id}/interactions',
|
|
7
|
+
'GET /pixel/orgs/{org_id}/visits',
|
|
8
|
+
'GET /pixel/orgs/{org_id}/events',
|
|
9
|
+
'GET /pixel/orgs/{org_id}/identity/{pixel_id}',
|
|
10
|
+
'GET /pixel/orgs/{org_id}/audience/get_geo_sample',
|
|
11
|
+
];
|
|
3
12
|
|
|
4
13
|
|
|
5
14
|
|
|
@@ -60,3 +69,10 @@ export async function getEvents(apiKey: string, orgId: string, params: { campaig
|
|
|
60
69
|
export async function getIdentity(apiKey: string, orgId: string, pixelId: string): Promise<{ uuid: string; is_resolved: boolean; nodes: Record<string, { type: string; probability: number }>; latency_ms: number }> {
|
|
61
70
|
return request('GET', `${BASE_URL}/pixel/orgs/${encodeURIComponent(orgId)}/identity/${encodeURIComponent(pixelId)}`, apiKey);
|
|
62
71
|
}
|
|
72
|
+
|
|
73
|
+
// Sample of geographic distribution of the org's pixel audience. Backend
|
|
74
|
+
// returns whatever shape it wants; we type as record-of-unknowns and let
|
|
75
|
+
// callers print or destructure as needed.
|
|
76
|
+
export async function getGeoSample(apiKey: string, orgId: string): Promise<Record<string, unknown>> {
|
|
77
|
+
return request('GET', `${BASE_URL}/pixel/orgs/${encodeURIComponent(orgId)}/audience/get_geo_sample`, apiKey);
|
|
78
|
+
}
|
package/src/services.ts
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
// Canonical service registry — the single source of truth for everything
|
|
2
|
+
// downstream (skill plugin.json generators, mirror-repo publisher, docs site,
|
|
3
|
+
// scaffolders, etc.).
|
|
4
|
+
//
|
|
5
|
+
// To add a service: append an entry here. To rename, change description, or
|
|
6
|
+
// re-categorize: edit here. Run `npm run canonical-sync` to propagate to
|
|
7
|
+
// every rendered artifact (plugin.json files today; npm/PyPI metadata,
|
|
8
|
+
// GitHub repo descriptions, docs site landing pages tomorrow).
|
|
9
|
+
//
|
|
10
|
+
// CI enforces no drift: `services-sync.test.ts` runs `canonical-sync
|
|
11
|
+
// --check` and fails on any difference.
|
|
12
|
+
//
|
|
13
|
+
// Skill names MUST match the directory names under skills/<name>/ and the
|
|
14
|
+
// repo names we want to claim on GitHub/npm. Don't paraphrase.
|
|
15
|
+
|
|
16
|
+
export type ServiceStatus = 'ga' | 'preview' | 'planned';
|
|
17
|
+
|
|
18
|
+
export type ServiceCategory =
|
|
19
|
+
| 'send' // outbound: email, funnel, url, image-render
|
|
20
|
+
| 'capture' // inbound: webhook, pixel
|
|
21
|
+
| 'data' // read/filter the data layer: people, company, audience, crm
|
|
22
|
+
| 'store' // persist bytes/JSON: storage, database
|
|
23
|
+
| 'compute' // run code or inference: llm, workflow
|
|
24
|
+
| 'identity' // auth/billing/account: hq
|
|
25
|
+
| 'infra'; // platform glue: domain
|
|
26
|
+
|
|
27
|
+
export interface ServiceMeta {
|
|
28
|
+
/** SDK namespace (also OpenAPI tag and CLI top-level command). */
|
|
29
|
+
module: string;
|
|
30
|
+
/** Skill name — used for: GitHub repo name, npm package name, plugin.json `name`, README headings. */
|
|
31
|
+
skill: string;
|
|
32
|
+
/** Brand domain we own (or want to own). Used for canonical links + npm/GitHub homepage. */
|
|
33
|
+
domain: string;
|
|
34
|
+
/** One-line description — used verbatim in npm description, GitHub repo description, plugin.json. */
|
|
35
|
+
description: string;
|
|
36
|
+
category: ServiceCategory;
|
|
37
|
+
status: ServiceStatus;
|
|
38
|
+
/** npm keywords + GitHub topics + PyPI classifiers. The first five are shared boilerplate. */
|
|
39
|
+
keywords: string[];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const SHARED_KEYWORDS = ['mcp', 'claude-skill', 'ai-agent', 'cli', 'myapi'] as const;
|
|
43
|
+
const k = (...extra: string[]): string[] => [...SHARED_KEYWORDS, ...extra];
|
|
44
|
+
|
|
45
|
+
export const SERVICES: readonly ServiceMeta[] = [
|
|
46
|
+
// ── identity / infra ────────────────────────────────────────────────
|
|
47
|
+
{
|
|
48
|
+
module: 'hq',
|
|
49
|
+
skill: 'my-api-hq',
|
|
50
|
+
domain: 'myapihq.com',
|
|
51
|
+
description: 'Core identity and billing hub. Manage auth, organizations, and billing.',
|
|
52
|
+
category: 'identity',
|
|
53
|
+
status: 'ga',
|
|
54
|
+
keywords: k('auth', 'identity', 'billing', 'organization'),
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
module: 'domain',
|
|
58
|
+
skill: 'my-domain-api',
|
|
59
|
+
domain: 'mydomainapi.com',
|
|
60
|
+
description: 'Domain registration and check with automated DNS and email infrastructure.',
|
|
61
|
+
category: 'infra',
|
|
62
|
+
status: 'ga',
|
|
63
|
+
keywords: k('domain', 'dns', 'registration'),
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
// ── send ────────────────────────────────────────────────────────────
|
|
67
|
+
{
|
|
68
|
+
// Customer-facing email surface (mailboxes, campaigns, templates,
|
|
69
|
+
// warmup) is gated pre-launch — 503 SERVICE_NOT_LAUNCHED. Sibling
|
|
70
|
+
// `my-email-verify-api` stays GA and remains the discoverable entry
|
|
71
|
+
// point for the email primitive today.
|
|
72
|
+
module: 'email',
|
|
73
|
+
skill: 'my-email-api',
|
|
74
|
+
domain: 'myemailapi.com',
|
|
75
|
+
description: 'Send transactional and bulk email from your own domain. Mailboxes, AI templates, drip campaigns, and warmup.',
|
|
76
|
+
category: 'send',
|
|
77
|
+
status: 'preview',
|
|
78
|
+
keywords: k('email', 'transactional', 'campaign', 'smtp'),
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
module: 'email',
|
|
82
|
+
skill: 'my-email-verify-api',
|
|
83
|
+
domain: 'myemailapi.com',
|
|
84
|
+
description: 'Sync single-address email verification — syntax + DNS + Microsoft probe. Pre-send quality gate for campaigns.',
|
|
85
|
+
category: 'send',
|
|
86
|
+
status: 'ga',
|
|
87
|
+
keywords: k('email', 'verification', 'deliverability', 'syntax', 'dns'),
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
module: 'funnel',
|
|
91
|
+
skill: 'my-funnel-api',
|
|
92
|
+
domain: 'myfunnelapi.com',
|
|
93
|
+
description: 'Build multi-page sites and funnels with headless HTML upload.',
|
|
94
|
+
category: 'send',
|
|
95
|
+
status: 'ga',
|
|
96
|
+
keywords: k('funnel', 'landing-page', 'website', 'static-site'),
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
module: 'url',
|
|
100
|
+
skill: 'my-url-to',
|
|
101
|
+
domain: 'myurlto.com',
|
|
102
|
+
description: 'Stateless link routing and URL shortening for the MyAPI ecosystem.',
|
|
103
|
+
category: 'send',
|
|
104
|
+
status: 'preview',
|
|
105
|
+
keywords: k('url', 'shortener', 'redirect', 'link'),
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
module: 'image',
|
|
109
|
+
skill: 'my-image-api',
|
|
110
|
+
domain: 'myimageapi.com',
|
|
111
|
+
description: 'Generate AI images from a text prompt. Async, polls until ready, returns a public CDN URL.',
|
|
112
|
+
category: 'compute',
|
|
113
|
+
status: 'ga',
|
|
114
|
+
keywords: k('image', 'ai-image', 'gemini', 'text-to-image'),
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
// ── capture ─────────────────────────────────────────────────────────
|
|
118
|
+
{
|
|
119
|
+
module: 'webhook',
|
|
120
|
+
skill: 'my-webhook-api',
|
|
121
|
+
domain: 'mywebhookapi.com',
|
|
122
|
+
description: 'Receive inbound HTTP webhooks. Per-org endpoints with full delivery history.',
|
|
123
|
+
category: 'capture',
|
|
124
|
+
status: 'ga',
|
|
125
|
+
keywords: k('webhook', 'inbound', 'event'),
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
module: 'pixel',
|
|
129
|
+
skill: 'my-pixel-api',
|
|
130
|
+
domain: 'mypixelapi.com',
|
|
131
|
+
description: 'Tracking pixel + identity resolution. Capture visits, events, and stitch known users to anonymous sessions.',
|
|
132
|
+
category: 'capture',
|
|
133
|
+
status: 'planned',
|
|
134
|
+
keywords: k('pixel', 'analytics', 'tracking', 'visit', 'identity'),
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
// ── data ────────────────────────────────────────────────────────────
|
|
138
|
+
{
|
|
139
|
+
// Goldfox-backed people search is gated pre-launch — 503 SERVICE_NOT_LAUNCHED.
|
|
140
|
+
// Internal Goldfox lookups still work (`crm contacts promote` resolves a
|
|
141
|
+
// goldfox_person_id server-side), but the agent-facing search/get path
|
|
142
|
+
// is hidden until backend lifts the gate.
|
|
143
|
+
module: 'people',
|
|
144
|
+
skill: 'my-people-api',
|
|
145
|
+
domain: 'mypeopleapi.com',
|
|
146
|
+
description: 'Contact database backed by the Goldfox crawl. Filter people by confidence tier, seniority, email type, country, link confidence, plus rich behavioral company signals (has_c_level, has_careers_page, has_decision_maker). The targeting layer for outbound campaigns.',
|
|
147
|
+
category: 'data',
|
|
148
|
+
status: 'preview',
|
|
149
|
+
keywords: k('people', 'contact', 'b2b', 'targeting', 'goldfox'),
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
// Goldfox-backed company search gated pre-launch (same reason as people).
|
|
153
|
+
module: 'company',
|
|
154
|
+
skill: 'my-company-api',
|
|
155
|
+
domain: 'mycompanyapi.com',
|
|
156
|
+
description: 'Company database backed by the Goldfox crawl. Filter companies by 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.',
|
|
157
|
+
category: 'data',
|
|
158
|
+
status: 'preview',
|
|
159
|
+
keywords: k('company', 'firmographics', 'b2b', 'goldfox'),
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
// Saved audiences sit on top of people/company — gated together with them.
|
|
163
|
+
module: 'audience',
|
|
164
|
+
skill: 'my-audience-api',
|
|
165
|
+
domain: 'myaudienceapi.com',
|
|
166
|
+
description: 'Saved audiences = named filter snapshots over people/company database. Reuse across campaigns; refresh re-evaluates against current data.',
|
|
167
|
+
category: 'data',
|
|
168
|
+
status: 'preview',
|
|
169
|
+
keywords: k('audience', 'segment', 'filter'),
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
module: 'crm',
|
|
173
|
+
skill: 'my-crm-api',
|
|
174
|
+
domain: 'mycrmapi.com',
|
|
175
|
+
description: 'The canonical store of engaged people + companies. Auto-ingest from inbound webhooks (configurable dot-path). Fixed lifecycle_stage enum, soft delete, event timeline.',
|
|
176
|
+
category: 'data',
|
|
177
|
+
status: 'ga',
|
|
178
|
+
keywords: k('crm', 'contact', 'pipeline', 'engagement'),
|
|
179
|
+
},
|
|
180
|
+
|
|
181
|
+
// ── store ───────────────────────────────────────────────────────────
|
|
182
|
+
{
|
|
183
|
+
module: 'storage',
|
|
184
|
+
skill: 'my-storage-api',
|
|
185
|
+
domain: 'mystorageapi.com',
|
|
186
|
+
description: 'Edge-hosted asset storage. Upload local files or ingest from URLs, each gets a stable public CDN URL.',
|
|
187
|
+
category: 'store',
|
|
188
|
+
status: 'ga',
|
|
189
|
+
keywords: k('storage', 'cdn', 'asset', 'upload'),
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
module: 'database',
|
|
193
|
+
skill: 'my-database-api',
|
|
194
|
+
domain: 'mydatabaseapi.com',
|
|
195
|
+
description: 'Per-org KV store with namespaces + compare-and-swap. JSON values up to 256 KB. The substrate for stateful agent-built apps.',
|
|
196
|
+
category: 'store',
|
|
197
|
+
status: 'ga',
|
|
198
|
+
keywords: k('kv-store', 'database', 'state'),
|
|
199
|
+
},
|
|
200
|
+
|
|
201
|
+
// ── compute ─────────────────────────────────────────────────────────
|
|
202
|
+
{
|
|
203
|
+
module: 'workflow',
|
|
204
|
+
skill: 'my-workflow-api',
|
|
205
|
+
domain: 'myworkflowapi.com',
|
|
206
|
+
description: 'React to inbound webhooks with step chains: send email, post to Slack, call HTTP URLs.',
|
|
207
|
+
category: 'compute',
|
|
208
|
+
status: 'ga',
|
|
209
|
+
keywords: k('workflow', 'automation', 'orchestration'),
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
module: 'llm',
|
|
213
|
+
skill: 'my-llm-api',
|
|
214
|
+
domain: 'myllmapi.com',
|
|
215
|
+
description: 'Provider-agnostic LLM completions + embeddings via MyAPI. Routes to managed models (Gemini today, more soon) at upstream cost. Use in workflow steps, not for your own reasoning.',
|
|
216
|
+
category: 'compute',
|
|
217
|
+
status: 'ga',
|
|
218
|
+
keywords: k('llm', 'completion', 'embedding', 'gemini'),
|
|
219
|
+
},
|
|
220
|
+
] as const;
|
package/src/storage.ts
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { request, MyApiError } from './client';
|
|
2
2
|
import { ApiResponse } from './types';
|
|
3
3
|
import { STORAGE_BASE as BASE_URL } from './config';
|
|
4
|
+
import type { Exposes } from './exposes';
|
|
5
|
+
|
|
6
|
+
export const EXPOSES: Exposes = [
|
|
7
|
+
'POST /storage/orgs/{org_id}/assets/ingest',
|
|
8
|
+
'POST /storage/orgs/{org_id}/assets/upload',
|
|
9
|
+
'GET /storage/orgs/{org_id}/assets',
|
|
10
|
+
'DELETE /storage/orgs/{org_id}/assets/{asset_id}',
|
|
11
|
+
];
|
|
4
12
|
|
|
5
13
|
|
|
6
14
|
|
|
@@ -10,16 +18,17 @@ export async function ingestAsset(apiKey: string, orgId: string, url: string, na
|
|
|
10
18
|
return request('POST', `${BASE_URL}/storage/orgs/${encodeURIComponent(orgId)}/assets/ingest`, apiKey, { url, name });
|
|
11
19
|
}
|
|
12
20
|
|
|
13
|
-
//
|
|
14
|
-
// detectAsset() allowlist (routes/org/org.go)
|
|
15
|
-
//
|
|
16
|
-
// (
|
|
17
|
-
// upload use case from the CLI.
|
|
21
|
+
// Content types accepted by uploadAsset. Mirrors the backend's
|
|
22
|
+
// detectAsset() allowlist (routes/org/org.go). Images go up to a few MB;
|
|
23
|
+
// videos cap at 200 MB. PDFs/SVGs and other types still need to go through
|
|
24
|
+
// `ingestAsset` (URL fetch) — they're not in the upload allowlist yet.
|
|
18
25
|
export type UploadContentType =
|
|
19
26
|
| 'image/jpeg'
|
|
20
27
|
| 'image/png'
|
|
21
28
|
| 'image/gif'
|
|
22
|
-
| 'image/webp'
|
|
29
|
+
| 'image/webp'
|
|
30
|
+
| 'video/mp4'
|
|
31
|
+
| 'video/webm';
|
|
23
32
|
|
|
24
33
|
export async function uploadAsset(apiKey: string, orgId: string, file: Blob | Buffer, contentType: UploadContentType, name?: string): Promise<Asset> {
|
|
25
34
|
const headers: Record<string, string> = {
|
package/src/url.ts
CHANGED
package/src/webhook.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { request } from './client';
|
|
2
2
|
import { WEBHOOK_BASE as BASE_URL } from './config';
|
|
3
|
+
import type { Exposes } from './exposes';
|
|
4
|
+
|
|
5
|
+
export const EXPOSES: Exposes = [
|
|
6
|
+
'POST /webhook/orgs/{org_id}/endpoints',
|
|
7
|
+
'GET /webhook/orgs/{org_id}/endpoints',
|
|
8
|
+
'DELETE /webhook/orgs/{org_id}/endpoints/{endpoint_id}',
|
|
9
|
+
'GET /webhook/orgs/{org_id}/deliveries/{delivery_id}',
|
|
10
|
+
];
|
|
3
11
|
|
|
4
12
|
export interface WebhookEndpoint {
|
|
5
13
|
id: string;
|
|
@@ -8,6 +16,10 @@ export interface WebhookEndpoint {
|
|
|
8
16
|
description?: string;
|
|
9
17
|
slug: string;
|
|
10
18
|
url: string;
|
|
19
|
+
// Dot-path into the webhook body whose value (an email) gets ingested
|
|
20
|
+
// into CRM as a contact + webhook_received event on each delivery.
|
|
21
|
+
// Default 'email' (top-level). Empty string disables CRM ingest.
|
|
22
|
+
crm_email_path?: string;
|
|
11
23
|
created_at: string;
|
|
12
24
|
}
|
|
13
25
|
|
|
@@ -18,8 +30,19 @@ export interface Delivery {
|
|
|
18
30
|
received_at: string;
|
|
19
31
|
}
|
|
20
32
|
|
|
21
|
-
export
|
|
22
|
-
|
|
33
|
+
export interface CreateEndpointOptions {
|
|
34
|
+
description?: string;
|
|
35
|
+
// CRM auto-ingest config. Empty string disables; undefined defaults to
|
|
36
|
+
// 'email' (top-level). For nested shapes pass the dot-path (e.g.
|
|
37
|
+
// 'data.object.customer_email' for Stripe, 'sender.email' for GitHub).
|
|
38
|
+
crm_email_path?: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export async function createEndpoint(apiKey: string, orgId: string, name: string, opts: CreateEndpointOptions = {}): Promise<WebhookEndpoint> {
|
|
42
|
+
const body: Record<string, unknown> = { name };
|
|
43
|
+
if (opts.description !== undefined) body.description = opts.description;
|
|
44
|
+
if (opts.crm_email_path !== undefined) body.crm_email_path = opts.crm_email_path;
|
|
45
|
+
return request('POST', `${BASE_URL}/webhook/orgs/${encodeURIComponent(orgId)}/endpoints`, apiKey, body);
|
|
23
46
|
}
|
|
24
47
|
|
|
25
48
|
export async function listEndpoints(apiKey: string, orgId: string): Promise<WebhookEndpoint[]> {
|
package/src/workflow.ts
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
import { request } from './client';
|
|
2
2
|
import { WORKFLOW_BASE as BASE_URL } from './config';
|
|
3
|
+
import type { Exposes } from './exposes';
|
|
4
|
+
|
|
5
|
+
export const EXPOSES: Exposes = [
|
|
6
|
+
'POST /workflow/orgs/{org_id}/workflows',
|
|
7
|
+
'GET /workflow/orgs/{org_id}/workflows',
|
|
8
|
+
'GET /workflow/orgs/{org_id}/workflows/{workflow_id}',
|
|
9
|
+
'PATCH /workflow/orgs/{org_id}/workflows/{workflow_id}',
|
|
10
|
+
'DELETE /workflow/orgs/{org_id}/workflows/{workflow_id}',
|
|
11
|
+
'POST /workflow/orgs/{org_id}/workflows/{workflow_id}/enable',
|
|
12
|
+
'POST /workflow/orgs/{org_id}/workflows/{workflow_id}/disable',
|
|
13
|
+
'GET /workflow/orgs/{org_id}/workflows/{workflow_id}/runs',
|
|
14
|
+
'GET /workflow/orgs/{org_id}/runs/{run_id}',
|
|
15
|
+
];
|
|
3
16
|
|
|
4
17
|
|
|
5
18
|
|