@myapihq/sdk 2.4.0 → 2.4.2
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/client.d.ts +23 -2
- package/dist/client.js +174 -22
- package/dist/crm.d.ts +2 -0
- package/dist/crm.js +15 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +11 -0
- package/package.json +11 -2
- package/scripts/scaffold-sdk.js +0 -501
- package/src/audience.ts +0 -162
- package/src/auth.ts +0 -161
- package/src/client.ts +0 -121
- package/src/company.ts +0 -48
- package/src/config.ts +0 -39
- package/src/container.ts +0 -187
- package/src/crm.ts +0 -239
- package/src/database.ts +0 -106
- package/src/domain.ts +0 -246
- package/src/email.ts +0 -247
- package/src/exposes.ts +0 -16
- package/src/function.ts +0 -141
- package/src/funds.ts +0 -66
- package/src/funnel.ts +0 -203
- package/src/git.ts +0 -171
- package/src/hq.ts +0 -393
- package/src/image.ts +0 -67
- package/src/index.ts +0 -32
- package/src/llm.ts +0 -189
- package/src/payments.ts +0 -98
- package/src/people.ts +0 -84
- package/src/pixel.ts +0 -80
- package/src/queue.ts +0 -115
- package/src/services.ts +0 -323
- package/src/storage.ts +0 -80
- package/src/task.ts +0 -198
- package/src/types.ts +0 -15
- package/src/url.ts +0 -18
- package/src/webhook.ts +0 -88
- package/src/workflow.ts +0 -162
- package/tsconfig.json +0 -14
package/src/crm.ts
DELETED
|
@@ -1,239 +0,0 @@
|
|
|
1
|
-
import { request, requestPage } from './client';
|
|
2
|
-
import { CRM_BASE as BASE_URL } from './config';
|
|
3
|
-
import type { Exposes } from './exposes';
|
|
4
|
-
|
|
5
|
-
export const EXPOSES: Exposes = [
|
|
6
|
-
'POST /crm/orgs/{org_id}/contacts',
|
|
7
|
-
'POST /crm/orgs/{org_id}/contacts/promote',
|
|
8
|
-
'POST /crm/orgs/{org_id}/contacts/search',
|
|
9
|
-
'GET /crm/orgs/{org_id}/contacts/{id}',
|
|
10
|
-
'PATCH /crm/orgs/{org_id}/contacts/{id}',
|
|
11
|
-
'DELETE /crm/orgs/{org_id}/contacts/{id}',
|
|
12
|
-
'GET /crm/orgs/{org_id}/contacts/{id}/events',
|
|
13
|
-
'POST /crm/orgs/{org_id}/companies',
|
|
14
|
-
'POST /crm/orgs/{org_id}/companies/promote',
|
|
15
|
-
'POST /crm/orgs/{org_id}/companies/search',
|
|
16
|
-
'GET /crm/orgs/{org_id}/companies/{id}',
|
|
17
|
-
'PATCH /crm/orgs/{org_id}/companies/{id}',
|
|
18
|
-
'DELETE /crm/orgs/{org_id}/companies/{id}',
|
|
19
|
-
];
|
|
20
|
-
|
|
21
|
-
// Shared enums — fixed sets. Lifecycle stage is the same enum for contacts
|
|
22
|
-
// and companies (Simon's call: keep it simple, easier for agents).
|
|
23
|
-
export type LifecycleStage =
|
|
24
|
-
| 'cold'
|
|
25
|
-
| 'warm'
|
|
26
|
-
| 'qualified'
|
|
27
|
-
| 'customer'
|
|
28
|
-
| 'churned';
|
|
29
|
-
|
|
30
|
-
export type ContactSource =
|
|
31
|
-
| 'goldfox'
|
|
32
|
-
| 'email'
|
|
33
|
-
| 'pixel'
|
|
34
|
-
| 'webhook'
|
|
35
|
-
| 'manual';
|
|
36
|
-
|
|
37
|
-
// Reserved set of event kinds. Agents cannot write these directly — they
|
|
38
|
-
// are emitted by the platform when state changes (stage_changed) or the
|
|
39
|
-
// underlying service completes (email_sent, webhook_received, etc.).
|
|
40
|
-
export type EventKind =
|
|
41
|
-
| 'created'
|
|
42
|
-
| 'promoted'
|
|
43
|
-
| 'stage_changed'
|
|
44
|
-
| 'email_sent'
|
|
45
|
-
| 'email_opened'
|
|
46
|
-
| 'email_clicked'
|
|
47
|
-
| 'email_replied'
|
|
48
|
-
| 'pixel_visit'
|
|
49
|
-
| 'webhook_received'
|
|
50
|
-
| 'payment';
|
|
51
|
-
|
|
52
|
-
// Goldfox enrichment is a live join — the response embeds the current
|
|
53
|
-
// Goldfox row when goldfox_person_id is set. v1: returns null until the
|
|
54
|
-
// BQ get-by-id helper lands backend-side. The field shape will become
|
|
55
|
-
// the existing Person from people.ts once enabled.
|
|
56
|
-
export interface Contact {
|
|
57
|
-
id: string;
|
|
58
|
-
org_id: string;
|
|
59
|
-
email: string | null;
|
|
60
|
-
first_name: string | null;
|
|
61
|
-
last_name: string | null;
|
|
62
|
-
company_id: string | null;
|
|
63
|
-
lifecycle_stage: LifecycleStage;
|
|
64
|
-
custom: Record<string, unknown>;
|
|
65
|
-
source: ContactSource;
|
|
66
|
-
goldfox_person_id: string | null;
|
|
67
|
-
goldfox_person?: unknown | null; // deferred until BQ helper lands
|
|
68
|
-
created_at: string;
|
|
69
|
-
updated_at: string;
|
|
70
|
-
last_engagement_at?: string | null; // only set after engagement events (email/pixel/webhook)
|
|
71
|
-
deleted_at?: string | null; // soft-delete marker
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export interface Company {
|
|
75
|
-
id: string;
|
|
76
|
-
org_id: string;
|
|
77
|
-
domain: string | null;
|
|
78
|
-
name: string | null;
|
|
79
|
-
lifecycle_stage: LifecycleStage;
|
|
80
|
-
custom: Record<string, unknown>;
|
|
81
|
-
source: ContactSource;
|
|
82
|
-
goldfox_company_id: string | null; // for Goldfox-sourced rows this equals the domain
|
|
83
|
-
goldfox_company?: unknown | null;
|
|
84
|
-
created_at: string;
|
|
85
|
-
updated_at: string;
|
|
86
|
-
deleted_at?: string | null;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export interface ContactEvent {
|
|
90
|
-
id: string;
|
|
91
|
-
contact_id: string;
|
|
92
|
-
kind: EventKind;
|
|
93
|
-
payload: Record<string, unknown>;
|
|
94
|
-
at: string;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// ── Inputs ────────────────────────────────────────────────────────────────
|
|
98
|
-
|
|
99
|
-
export interface CreateContactInput {
|
|
100
|
-
email?: string | null;
|
|
101
|
-
first_name?: string;
|
|
102
|
-
last_name?: string;
|
|
103
|
-
company_id?: string; // override the auto-link by domain
|
|
104
|
-
lifecycle_stage?: LifecycleStage;
|
|
105
|
-
custom?: Record<string, unknown>;
|
|
106
|
-
source?: ContactSource; // defaults to 'manual' server-side
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export interface UpdateContactInput {
|
|
110
|
-
first_name?: string | null;
|
|
111
|
-
last_name?: string | null;
|
|
112
|
-
company_id?: string | null;
|
|
113
|
-
lifecycle_stage?: LifecycleStage;
|
|
114
|
-
custom?: Record<string, unknown>;
|
|
115
|
-
deleted_at?: null; // pass explicit null to restore a soft-deleted contact
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
export interface ContactSearchFilter {
|
|
119
|
-
lifecycle_stage?: LifecycleStage[];
|
|
120
|
-
source?: ContactSource[];
|
|
121
|
-
email?: string;
|
|
122
|
-
company_id?: string;
|
|
123
|
-
min_last_engagement_days?: number; // engaged within N days
|
|
124
|
-
max_last_engagement_days?: number; // last engaged > N days ago — re-engagement filter
|
|
125
|
-
include_deleted?: boolean; // default false
|
|
126
|
-
limit?: number;
|
|
127
|
-
offset?: number;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
export interface ContactSearchResult {
|
|
131
|
-
contacts: Contact[];
|
|
132
|
-
total: number;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
export interface CreateCompanyInput {
|
|
136
|
-
domain?: string | null;
|
|
137
|
-
name?: string;
|
|
138
|
-
lifecycle_stage?: LifecycleStage;
|
|
139
|
-
custom?: Record<string, unknown>;
|
|
140
|
-
source?: ContactSource;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
export interface UpdateCompanyInput {
|
|
144
|
-
name?: string | null;
|
|
145
|
-
lifecycle_stage?: LifecycleStage;
|
|
146
|
-
custom?: Record<string, unknown>;
|
|
147
|
-
deleted_at?: null;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
export interface CompanySearchFilter {
|
|
151
|
-
lifecycle_stage?: LifecycleStage[];
|
|
152
|
-
source?: ContactSource[];
|
|
153
|
-
domain?: string;
|
|
154
|
-
include_deleted?: boolean;
|
|
155
|
-
limit?: number;
|
|
156
|
-
offset?: number;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
export interface CompanySearchResult {
|
|
160
|
-
companies: Company[];
|
|
161
|
-
total: number;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
export interface EventsResponse {
|
|
165
|
-
events: ContactEvent[];
|
|
166
|
-
next_cursor?: string;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
export interface ListEventsOptions {
|
|
170
|
-
limit?: number; // 1-200, default 50
|
|
171
|
-
cursor?: string;
|
|
172
|
-
kind?: EventKind;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// ── Contacts ──────────────────────────────────────────────────────────────
|
|
176
|
-
|
|
177
|
-
export async function createContact(apiKey: string, orgId: string, input: CreateContactInput): Promise<Contact> {
|
|
178
|
-
return request('POST', `${BASE_URL}/crm/orgs/${encodeURIComponent(orgId)}/contacts`, apiKey, input);
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
export async function getContact(apiKey: string, orgId: string, id: string): Promise<Contact> {
|
|
182
|
-
return request('GET', `${BASE_URL}/crm/orgs/${encodeURIComponent(orgId)}/contacts/${encodeURIComponent(id)}`, apiKey);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
export async function updateContact(apiKey: string, orgId: string, id: string, patch: UpdateContactInput): Promise<Contact> {
|
|
186
|
-
return request('PATCH', `${BASE_URL}/crm/orgs/${encodeURIComponent(orgId)}/contacts/${encodeURIComponent(id)}`, apiKey, patch);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
export async function deleteContact(apiKey: string, orgId: string, id: string): Promise<void> {
|
|
190
|
-
return request('DELETE', `${BASE_URL}/crm/orgs/${encodeURIComponent(orgId)}/contacts/${encodeURIComponent(id)}`, apiKey);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
export async function searchContacts(apiKey: string, orgId: string, filter: ContactSearchFilter = {}): Promise<ContactSearchResult> {
|
|
194
|
-
return request('POST', `${BASE_URL}/crm/orgs/${encodeURIComponent(orgId)}/contacts/search`, apiKey, filter);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
export async function promoteContact(apiKey: string, orgId: string, goldfoxPersonId: string): Promise<Contact> {
|
|
198
|
-
return request('POST', `${BASE_URL}/crm/orgs/${encodeURIComponent(orgId)}/contacts/promote`, apiKey, { goldfox_person_id: goldfoxPersonId });
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
export async function getContactEvents(apiKey: string, orgId: string, id: string, opts: ListEventsOptions = {}): Promise<EventsResponse> {
|
|
202
|
-
const qs = new URLSearchParams();
|
|
203
|
-
if (opts.limit != null) qs.append('limit', String(opts.limit));
|
|
204
|
-
if (opts.cursor != null) qs.append('cursor', opts.cursor);
|
|
205
|
-
if (opts.kind != null) qs.append('kind', opts.kind);
|
|
206
|
-
const q = qs.toString();
|
|
207
|
-
const url = `${BASE_URL}/crm/orgs/${encodeURIComponent(orgId)}/contacts/${encodeURIComponent(id)}/events${q ? `?${q}` : ''}`;
|
|
208
|
-
// Paginated (WrapPage): events are the bare `data` array with the cursor
|
|
209
|
-
// under `meta` — use requestPage so `next_cursor` survives.
|
|
210
|
-
const page = await requestPage<ContactEvent>('GET', url, apiKey);
|
|
211
|
-
return { events: page.data, next_cursor: page.next_cursor };
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// ── Companies ─────────────────────────────────────────────────────────────
|
|
215
|
-
|
|
216
|
-
export async function createCompany(apiKey: string, orgId: string, input: CreateCompanyInput): Promise<Company> {
|
|
217
|
-
return request('POST', `${BASE_URL}/crm/orgs/${encodeURIComponent(orgId)}/companies`, apiKey, input);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
export async function getCompany(apiKey: string, orgId: string, id: string): Promise<Company> {
|
|
221
|
-
return request('GET', `${BASE_URL}/crm/orgs/${encodeURIComponent(orgId)}/companies/${encodeURIComponent(id)}`, apiKey);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
export async function updateCompany(apiKey: string, orgId: string, id: string, patch: UpdateCompanyInput): Promise<Company> {
|
|
225
|
-
return request('PATCH', `${BASE_URL}/crm/orgs/${encodeURIComponent(orgId)}/companies/${encodeURIComponent(id)}`, apiKey, patch);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
export async function deleteCompany(apiKey: string, orgId: string, id: string): Promise<void> {
|
|
229
|
-
return request('DELETE', `${BASE_URL}/crm/orgs/${encodeURIComponent(orgId)}/companies/${encodeURIComponent(id)}`, apiKey);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
export async function searchCompanies(apiKey: string, orgId: string, filter: CompanySearchFilter = {}): Promise<CompanySearchResult> {
|
|
233
|
-
return request('POST', `${BASE_URL}/crm/orgs/${encodeURIComponent(orgId)}/companies/search`, apiKey, filter);
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
// Goldfox company id IS its domain (Simon's note in routes.md).
|
|
237
|
-
export async function promoteCompany(apiKey: string, orgId: string, domain: string): Promise<Company> {
|
|
238
|
-
return request('POST', `${BASE_URL}/crm/orgs/${encodeURIComponent(orgId)}/companies/promote`, apiKey, { goldfox_company_id: domain });
|
|
239
|
-
}
|
package/src/database.ts
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import { request, requestPage } from './client';
|
|
2
|
-
import { DATABASE_BASE as BASE_URL } from './config';
|
|
3
|
-
import type { Exposes } from './exposes';
|
|
4
|
-
|
|
5
|
-
export const EXPOSES: Exposes = [
|
|
6
|
-
'GET /database/orgs/{org_id}/namespaces',
|
|
7
|
-
'POST /database/orgs/{org_id}/namespaces',
|
|
8
|
-
'GET /database/orgs/{org_id}/namespaces/{ns}',
|
|
9
|
-
'DELETE /database/orgs/{org_id}/namespaces/{ns}',
|
|
10
|
-
'GET /database/orgs/{org_id}/namespaces/{ns}/keys',
|
|
11
|
-
'GET /database/orgs/{org_id}/namespaces/{ns}/keys/{key}',
|
|
12
|
-
'PUT /database/orgs/{org_id}/namespaces/{ns}/keys/{key}',
|
|
13
|
-
'DELETE /database/orgs/{org_id}/namespaces/{ns}/keys/{key}',
|
|
14
|
-
];
|
|
15
|
-
|
|
16
|
-
// Per-value JSON size cap. Mirrored server-side. Surfaced here so the CLI
|
|
17
|
-
// can fail fast before round-trip.
|
|
18
|
-
export const MAX_VALUE_BYTES = 256 * 1024;
|
|
19
|
-
|
|
20
|
-
export interface Namespace {
|
|
21
|
-
name: string;
|
|
22
|
-
org_id: string;
|
|
23
|
-
key_count: number; // approximate; eventually consistent
|
|
24
|
-
created_at: string;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export interface KeyEntry {
|
|
28
|
-
key: string;
|
|
29
|
-
value?: unknown; // present when values=true was requested or on get
|
|
30
|
-
etag: string;
|
|
31
|
-
updated_at: string;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export interface ListKeysOptions {
|
|
35
|
-
prefix?: string;
|
|
36
|
-
limit?: number; // 1-1000, default 50
|
|
37
|
-
cursor?: string; // opaque from previous response
|
|
38
|
-
values?: boolean; // default false
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export interface ListKeysResponse {
|
|
42
|
-
keys: KeyEntry[];
|
|
43
|
-
next_cursor?: string; // present when more results exist
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export interface ListNamespacesResponse {
|
|
47
|
-
namespaces: Namespace[];
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export async function listNamespaces(apiKey: string, orgId: string): Promise<ListNamespacesResponse> {
|
|
51
|
-
return request('GET', `${BASE_URL}/database/orgs/${encodeURIComponent(orgId)}/namespaces`, apiKey);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export async function createNamespace(apiKey: string, orgId: string, name: string): Promise<Namespace> {
|
|
55
|
-
return request('POST', `${BASE_URL}/database/orgs/${encodeURIComponent(orgId)}/namespaces`, apiKey, { name });
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export async function getNamespace(apiKey: string, orgId: string, name: string): Promise<Namespace> {
|
|
59
|
-
return request('GET', `${BASE_URL}/database/orgs/${encodeURIComponent(orgId)}/namespaces/${encodeURIComponent(name)}`, apiKey);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export async function deleteNamespace(apiKey: string, orgId: string, name: string): Promise<void> {
|
|
63
|
-
return request('DELETE', `${BASE_URL}/database/orgs/${encodeURIComponent(orgId)}/namespaces/${encodeURIComponent(name)}`, apiKey);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export async function listKeys(apiKey: string, orgId: string, ns: string, opts: ListKeysOptions = {}): Promise<ListKeysResponse> {
|
|
67
|
-
const qs = new URLSearchParams();
|
|
68
|
-
if (opts.prefix != null) qs.append('prefix', opts.prefix);
|
|
69
|
-
if (opts.limit != null) qs.append('limit', String(opts.limit));
|
|
70
|
-
if (opts.cursor != null) qs.append('cursor', opts.cursor);
|
|
71
|
-
if (opts.values) qs.append('values', 'true');
|
|
72
|
-
const q = qs.toString();
|
|
73
|
-
const url = `${BASE_URL}/database/orgs/${encodeURIComponent(orgId)}/namespaces/${encodeURIComponent(ns)}/keys${q ? `?${q}` : ''}`;
|
|
74
|
-
// Paginated (WrapPage): keys come back as the bare `data` array with the
|
|
75
|
-
// cursor under `meta` — must use requestPage or the cursor is lost.
|
|
76
|
-
const page = await requestPage<KeyEntry>('GET', url, apiKey);
|
|
77
|
-
return { keys: page.data, next_cursor: page.next_cursor };
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export async function getKey(apiKey: string, orgId: string, ns: string, key: string): Promise<KeyEntry> {
|
|
81
|
-
return request('GET', `${BASE_URL}/database/orgs/${encodeURIComponent(orgId)}/namespaces/${encodeURIComponent(ns)}/keys/${encodeURIComponent(key)}`, apiKey);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// `ifMatch` enables compare-and-swap: server returns 412 ETAG_MISMATCH when
|
|
85
|
-
// the stored etag differs. Omit for last-write-wins.
|
|
86
|
-
export async function putKey(apiKey: string, orgId: string, ns: string, key: string, value: unknown, ifMatch?: string): Promise<KeyEntry> {
|
|
87
|
-
const headers = ifMatch ? { 'If-Match': ifMatch } : undefined;
|
|
88
|
-
return request(
|
|
89
|
-
'PUT',
|
|
90
|
-
`${BASE_URL}/database/orgs/${encodeURIComponent(orgId)}/namespaces/${encodeURIComponent(ns)}/keys/${encodeURIComponent(key)}`,
|
|
91
|
-
apiKey,
|
|
92
|
-
{ value },
|
|
93
|
-
headers,
|
|
94
|
-
);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export async function deleteKey(apiKey: string, orgId: string, ns: string, key: string, ifMatch?: string): Promise<void> {
|
|
98
|
-
const headers = ifMatch ? { 'If-Match': ifMatch } : undefined;
|
|
99
|
-
return request(
|
|
100
|
-
'DELETE',
|
|
101
|
-
`${BASE_URL}/database/orgs/${encodeURIComponent(orgId)}/namespaces/${encodeURIComponent(ns)}/keys/${encodeURIComponent(key)}`,
|
|
102
|
-
apiKey,
|
|
103
|
-
undefined,
|
|
104
|
-
headers,
|
|
105
|
-
);
|
|
106
|
-
}
|
package/src/domain.ts
DELETED
|
@@ -1,246 +0,0 @@
|
|
|
1
|
-
import { request } from './client';
|
|
2
|
-
import { DOMAIN_BASE as BASE_URL } from './config';
|
|
3
|
-
import type { Exposes } from './exposes';
|
|
4
|
-
|
|
5
|
-
export const EXPOSES: Exposes = [
|
|
6
|
-
'GET /domain/orgs/{org_id}/list',
|
|
7
|
-
'GET /domain/orgs/{org_id}/check/available/{name}',
|
|
8
|
-
'POST /domain/orgs/{org_id}/register',
|
|
9
|
-
'POST /domain/orgs/{org_id}/import',
|
|
10
|
-
'POST /domain/orgs/{org_id}/{domain}/assign',
|
|
11
|
-
'POST /domain/orgs/{org_id}/{domain}/renew',
|
|
12
|
-
'GET /domain/orgs/{org_id}/{domain}/settings',
|
|
13
|
-
'POST /domain/orgs/{org_id}/{domain}/settings',
|
|
14
|
-
'GET /domain/orgs/{org_id}/{domain}/status',
|
|
15
|
-
'GET /domain/orgs/{org_id}/{domain}/records',
|
|
16
|
-
'GET /domain/orgs/{org_id}/{domain}/records/{record_id}',
|
|
17
|
-
'POST /domain/orgs/{org_id}/{domain}/records',
|
|
18
|
-
'PATCH /domain/orgs/{org_id}/{domain}/records/{record_id}',
|
|
19
|
-
'DELETE /domain/orgs/{org_id}/{domain}/records/{record_id}',
|
|
20
|
-
'POST /domain/orgs/{org_id}/{domain}/email-infra',
|
|
21
|
-
'POST /domain/orgs/{org_id}/{domain}/retry-provisioning',
|
|
22
|
-
];
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
export interface DomainRecord {
|
|
27
|
-
domain: string;
|
|
28
|
-
status: string;
|
|
29
|
-
expires_at?: string;
|
|
30
|
-
days_until_expiry?: number;
|
|
31
|
-
email_infra_ready?: boolean;
|
|
32
|
-
// New status surface (post-2026-05-14 backend). Email infra is opt-in and
|
|
33
|
-
// always lives on a subdomain — apex is never touched.
|
|
34
|
-
email_infra?: 'skipped' | 'pending' | 'ready' | 'error';
|
|
35
|
-
email_subdomain?: string; // Only set when email_infra ∈ {pending, ready, error}.
|
|
36
|
-
dns_active?: boolean;
|
|
37
|
-
steps_completed?: string[];
|
|
38
|
-
error_detail?: {
|
|
39
|
-
failed_step: string;
|
|
40
|
-
message: string;
|
|
41
|
-
retryable: boolean;
|
|
42
|
-
attempt_count?: number;
|
|
43
|
-
last_attempt_at?: string;
|
|
44
|
-
};
|
|
45
|
-
org_id?: string | null;
|
|
46
|
-
created_at: string;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export interface DomainSettings {
|
|
50
|
-
domain: string;
|
|
51
|
-
security_level: string;
|
|
52
|
-
browser_check: string;
|
|
53
|
-
ai_bots_protection: string;
|
|
54
|
-
is_robots_txt_managed: boolean;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// ICANN-required WHOIS contact info for domain registration. Sent in the
|
|
58
|
-
// register-domain request body when REGISTRAR_PROVIDER=cloudflare is set
|
|
59
|
-
// server-side; ignored (but accepted) under the legacy OpenProvider path.
|
|
60
|
-
// The CF account holds the zone; this is the WHOIS registrant.
|
|
61
|
-
export interface Registrant {
|
|
62
|
-
name: string;
|
|
63
|
-
email: string;
|
|
64
|
-
phone: string; // E.164 format recommended (e.g. "+33612345678")
|
|
65
|
-
street: string;
|
|
66
|
-
city: string;
|
|
67
|
-
state?: string; // Required for US / CA registrants; optional elsewhere.
|
|
68
|
-
postal_code: string;
|
|
69
|
-
country_code: string; // ISO 3166-1 alpha-2 (e.g. "US", "DE", "FR")
|
|
70
|
-
organization?: string; // Optional organization name (WHOIS "Registrant Organization" field).
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export interface RegisterDomainInput {
|
|
74
|
-
years?: number;
|
|
75
|
-
// Required only when the server runs REGISTRAR_PROVIDER=cloudflare (the CF
|
|
76
|
-
// account holds the zone; this is the WHOIS registrant). Under the legacy
|
|
77
|
-
// OpenProvider path it is ignored-but-accepted, so it's optional here and the
|
|
78
|
-
// backend enforces its presence when it actually needs it.
|
|
79
|
-
registrant?: Registrant;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export async function checkDomain(apiKey: string, orgId: string, domain: string): Promise<{ available: boolean; price_cents: number }> {
|
|
83
|
-
return request('GET', `${BASE_URL}/domain/orgs/${encodeURIComponent(orgId)}/check/available/${encodeURIComponent(domain)}`, apiKey);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export async function registerDomain(apiKey: string, orgId: string, domain: string, input: RegisterDomainInput): Promise<DomainRecord> {
|
|
87
|
-
return request('POST', `${BASE_URL}/domain/orgs/${encodeURIComponent(orgId)}/register`, apiKey, {
|
|
88
|
-
domain,
|
|
89
|
-
years: input.years,
|
|
90
|
-
registrant: input.registrant,
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
export async function renewDomain(apiKey: string, orgId: string, domain: string): Promise<DomainRecord> {
|
|
95
|
-
return request('POST', `${BASE_URL}/domain/orgs/${encodeURIComponent(orgId)}/${encodeURIComponent(domain)}/renew`, apiKey);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// BYOD import — registrar-agnostic. Backend uses CF zone creation + best-effort
|
|
99
|
-
// public DNS probe to snapshot existing records before the NS swap. Customer's
|
|
100
|
-
// next action is changing NS at their current registrar to the returned values.
|
|
101
|
-
export interface PreservedRecord {
|
|
102
|
-
type: string;
|
|
103
|
-
name: string;
|
|
104
|
-
content: string;
|
|
105
|
-
ttl: number;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
export interface ImportDomainResponse {
|
|
109
|
-
domain: string;
|
|
110
|
-
domain_id: string;
|
|
111
|
-
status: string; // 'pending_ns_change' initially
|
|
112
|
-
nameservers: string[];
|
|
113
|
-
preserved_records: PreservedRecord[];
|
|
114
|
-
preserved_count: number;
|
|
115
|
-
probe_warning: string;
|
|
116
|
-
next_step: string;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export async function importDomain(apiKey: string, orgId: string, domain: string): Promise<ImportDomainResponse> {
|
|
120
|
-
return request('POST', `${BASE_URL}/domain/orgs/${encodeURIComponent(orgId)}/import`, apiKey, { domain });
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
export async function listDomains(apiKey: string, orgId: string, filter?: string): Promise<DomainRecord[]> {
|
|
124
|
-
const query = filter ? `?filter=${encodeURIComponent(filter)}` : '';
|
|
125
|
-
return request('GET', `${BASE_URL}/domain/orgs/${encodeURIComponent(orgId)}/list${query}`, apiKey);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
export async function getDomainStatus(apiKey: string, orgId: string, domain: string): Promise<DomainRecord> {
|
|
129
|
-
return request('GET', `${BASE_URL}/domain/orgs/${encodeURIComponent(orgId)}/${encodeURIComponent(domain)}/status`, apiKey);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Assign returns the bound Worker routes so the CLI can show users what's
|
|
133
|
-
// live without hardcoding "apex + www" (which would skew if backend changes
|
|
134
|
-
// the default convention). `include_www` defaults to true at the backend.
|
|
135
|
-
export interface AssignDomainResponse {
|
|
136
|
-
domain: string;
|
|
137
|
-
org_id: string | null;
|
|
138
|
-
include_www: boolean;
|
|
139
|
-
routes_bound: string[];
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
export async function assignDomain(apiKey: string, orgId: string, domain: string, opts?: { includeWww?: boolean; funnelId?: string }): Promise<AssignDomainResponse> {
|
|
143
|
-
const body: Record<string, unknown> = { org_id: orgId };
|
|
144
|
-
if (opts?.includeWww === false) body.include_www = false;
|
|
145
|
-
// Backend (2026-05-15): optional funnel_id picks which funnel the domain
|
|
146
|
-
// is bound to. Defaults server-side to the org's only funnel (or first
|
|
147
|
-
// when ambiguous, today; will become required once N-funnels-per-org lands
|
|
148
|
-
// for real). Pre-emptively threading it through gives agents a way to be
|
|
149
|
-
// explicit when the migration completes without an SDK shape change.
|
|
150
|
-
if (opts?.funnelId) body.funnel_id = opts.funnelId;
|
|
151
|
-
return request('POST', `${BASE_URL}/domain/orgs/${encodeURIComponent(orgId)}/${encodeURIComponent(domain)}/assign`, apiKey, body);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
export async function unassignDomain(apiKey: string, orgId: string, domain: string): Promise<AssignDomainResponse> {
|
|
155
|
-
return request('POST', `${BASE_URL}/domain/orgs/${encodeURIComponent(orgId)}/${encodeURIComponent(domain)}/assign`, apiKey, { org_id: null });
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
export async function getDomainSettings(apiKey: string, orgId: string, domain: string): Promise<DomainSettings> {
|
|
159
|
-
return request('GET', `${BASE_URL}/domain/orgs/${encodeURIComponent(orgId)}/${encodeURIComponent(domain)}/settings`, apiKey);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// ── DNS records ──────────────────────────────────────────────────────────────
|
|
163
|
-
// Per-zone CRUD on the Cloudflare zone the backend manages for this domain.
|
|
164
|
-
// v1 supports A / AAAA / CNAME / MX / TXT. `priority` is non-null only for MX,
|
|
165
|
-
// `proxied` is non-null only for A/AAAA/CNAME. `ttl: 1` is CF's "automatic"
|
|
166
|
-
// sentinel.
|
|
167
|
-
|
|
168
|
-
export type DnsRecordType = 'A' | 'AAAA' | 'CNAME' | 'MX' | 'TXT';
|
|
169
|
-
|
|
170
|
-
export interface DnsRecord {
|
|
171
|
-
id: string;
|
|
172
|
-
type: DnsRecordType;
|
|
173
|
-
name: string; // FQDN as stored by CF
|
|
174
|
-
content: string;
|
|
175
|
-
ttl: number;
|
|
176
|
-
priority: number | null;
|
|
177
|
-
proxied: boolean | null;
|
|
178
|
-
created_on: string;
|
|
179
|
-
modified_on: string;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
export interface DnsRecordInput {
|
|
183
|
-
type: DnsRecordType;
|
|
184
|
-
name: string; // Accepts FQDN, host-only, or apex tokens (`@`, `""`).
|
|
185
|
-
content: string;
|
|
186
|
-
ttl?: number; // Default 1 (CF auto). Range [60, 86400] otherwise.
|
|
187
|
-
priority?: number; // Required for MX.
|
|
188
|
-
proxied?: boolean; // A/AAAA/CNAME only. Defaults false.
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
export async function listDnsRecords(apiKey: string, orgId: string, domain: string, type?: DnsRecordType): Promise<DnsRecord[]> {
|
|
192
|
-
const query = type ? `?type=${encodeURIComponent(type)}` : '';
|
|
193
|
-
return request('GET', `${BASE_URL}/domain/orgs/${encodeURIComponent(orgId)}/${encodeURIComponent(domain)}/records${query}`, apiKey);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
export async function getDnsRecord(apiKey: string, orgId: string, domain: string, recordId: string): Promise<DnsRecord> {
|
|
197
|
-
return request('GET', `${BASE_URL}/domain/orgs/${encodeURIComponent(orgId)}/${encodeURIComponent(domain)}/records/${encodeURIComponent(recordId)}`, apiKey);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
export async function createDnsRecord(apiKey: string, orgId: string, domain: string, input: DnsRecordInput): Promise<DnsRecord> {
|
|
201
|
-
return request('POST', `${BASE_URL}/domain/orgs/${encodeURIComponent(orgId)}/${encodeURIComponent(domain)}/records`, apiKey, input);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
export async function updateDnsRecord(apiKey: string, orgId: string, domain: string, recordId: string, input: Partial<Omit<DnsRecordInput, 'type'>>): Promise<DnsRecord> {
|
|
205
|
-
return request('PATCH', `${BASE_URL}/domain/orgs/${encodeURIComponent(orgId)}/${encodeURIComponent(domain)}/records/${encodeURIComponent(recordId)}`, apiKey, input);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
export async function deleteDnsRecord(apiKey: string, orgId: string, domain: string, recordId: string): Promise<void> {
|
|
209
|
-
return request('DELETE', `${BASE_URL}/domain/orgs/${encodeURIComponent(orgId)}/${encodeURIComponent(domain)}/records/${encodeURIComponent(recordId)}`, apiKey);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
// Opt in to MyAPI-managed email on a subdomain. Apex is never touched; the
|
|
213
|
-
// backend provisions an SES identity on <subdomain>.<domain> and writes
|
|
214
|
-
// DKIM/SPF/DMARC records there. Default subdomain is `mail`.
|
|
215
|
-
export interface EmailInfraResponse {
|
|
216
|
-
domain: string;
|
|
217
|
-
email_infra: 'pending' | 'ready' | 'error';
|
|
218
|
-
subdomain: string;
|
|
219
|
-
next_step?: string;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
export async function setupEmailInfra(apiKey: string, orgId: string, domain: string, subdomain?: string): Promise<EmailInfraResponse> {
|
|
223
|
-
const body = subdomain ? { subdomain } : {};
|
|
224
|
-
return request('POST', `${BASE_URL}/domain/orgs/${encodeURIComponent(orgId)}/${encodeURIComponent(domain)}/email-infra`, apiKey, body);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
// Re-run provisioning from the failed step when status=infra_error and the
|
|
228
|
-
// error is retryable. Returns a transient `{ email_infra: 'pending', next_step }`
|
|
229
|
-
// shape; caller polls `getDomainStatus` until status flips off `infra_error`.
|
|
230
|
-
export interface RetryProvisioningResponse {
|
|
231
|
-
domain: string;
|
|
232
|
-
email_infra?: string;
|
|
233
|
-
next_step?: string;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
export async function retryProvisioning(apiKey: string, orgId: string, domain: string): Promise<RetryProvisioningResponse> {
|
|
237
|
-
return request('POST', `${BASE_URL}/domain/orgs/${encodeURIComponent(orgId)}/${encodeURIComponent(domain)}/retry-provisioning`, apiKey);
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
export async function updateDomainSettings(apiKey: string, orgId: string, domain: string, payload: {
|
|
241
|
-
security_level?: 'essentially_off' | 'medium' | 'high' | 'under_attack';
|
|
242
|
-
browser_check?: 'on' | 'off';
|
|
243
|
-
purge_cache?: boolean;
|
|
244
|
-
}): Promise<DomainSettings> {
|
|
245
|
-
return request('POST', `${BASE_URL}/domain/orgs/${encodeURIComponent(orgId)}/${encodeURIComponent(domain)}/settings`, apiKey, payload);
|
|
246
|
-
}
|