@myapihq/sdk 2.21.1 → 2.23.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/crm.d.ts +37 -0
- package/dist/crm.js +35 -0
- package/dist/email.d.ts +74 -0
- package/dist/email.js +67 -0
- package/dist/hq.d.ts +24 -0
- package/dist/hq.js +11 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/crm.d.ts
CHANGED
|
@@ -116,6 +116,43 @@ export declare function deleteContact(apiKey: string, orgId: string, id: string)
|
|
|
116
116
|
export declare function restoreContact(apiKey: string, orgId: string, id: string): Promise<Contact>;
|
|
117
117
|
export declare function searchContacts(apiKey: string, orgId: string, filter?: ContactSearchFilter): Promise<ContactSearchResult>;
|
|
118
118
|
export declare function promoteContact(apiKey: string, orgId: string, goldfoxPersonId: string): Promise<Contact>;
|
|
119
|
+
/** One page of a bulk promotion: what it did, and where to resume. */
|
|
120
|
+
export interface PromoteAudienceResult {
|
|
121
|
+
audience_id: string;
|
|
122
|
+
created: number;
|
|
123
|
+
matched: number;
|
|
124
|
+
/** Goldfox rows with no address — the usual reason 400 becomes 260. */
|
|
125
|
+
skipped_no_email: number;
|
|
126
|
+
failed: number;
|
|
127
|
+
processed: number;
|
|
128
|
+
offset: number;
|
|
129
|
+
total: number;
|
|
130
|
+
has_more: boolean;
|
|
131
|
+
next_offset: number;
|
|
132
|
+
note: string;
|
|
133
|
+
}
|
|
134
|
+
export declare function promoteAudience(apiKey: string, orgId: string, audienceId: string, opts?: {
|
|
135
|
+
limit?: number;
|
|
136
|
+
offset?: number;
|
|
137
|
+
}): Promise<PromoteAudienceResult>;
|
|
138
|
+
/** A row the import could not use, with the reason and the line it was on. */
|
|
139
|
+
export interface SkippedImportRow {
|
|
140
|
+
line: number;
|
|
141
|
+
email?: string;
|
|
142
|
+
/** e.g. "no email", "not an address", "previously deleted". */
|
|
143
|
+
reason: string;
|
|
144
|
+
}
|
|
145
|
+
export interface ImportContactsResult {
|
|
146
|
+
created: number;
|
|
147
|
+
/** Already in CRM: matched, never overwritten. A soft-deleted address is
|
|
148
|
+
* NOT counted here — it comes back as a skipped row, since nothing was
|
|
149
|
+
* imported and the person is not present. */
|
|
150
|
+
matched: number;
|
|
151
|
+
skipped: number;
|
|
152
|
+
skipped_rows: SkippedImportRow[];
|
|
153
|
+
note: string;
|
|
154
|
+
}
|
|
155
|
+
export declare function importContacts(apiKey: string, orgId: string, csv: Blob | Buffer | string, filename?: string): Promise<ImportContactsResult>;
|
|
119
156
|
export declare function getContactEvents(apiKey: string, orgId: string, id: string, opts?: ListEventsOptions): Promise<EventsResponse>;
|
|
120
157
|
export declare function createCompany(apiKey: string, orgId: string, input: CreateCompanyInput): Promise<Company>;
|
|
121
158
|
export declare function getCompany(apiKey: string, orgId: string, id: string): Promise<Company>;
|
package/dist/crm.js
CHANGED
|
@@ -8,6 +8,8 @@ exports.deleteContact = deleteContact;
|
|
|
8
8
|
exports.restoreContact = restoreContact;
|
|
9
9
|
exports.searchContacts = searchContacts;
|
|
10
10
|
exports.promoteContact = promoteContact;
|
|
11
|
+
exports.promoteAudience = promoteAudience;
|
|
12
|
+
exports.importContacts = importContacts;
|
|
11
13
|
exports.getContactEvents = getContactEvents;
|
|
12
14
|
exports.createCompany = createCompany;
|
|
13
15
|
exports.getCompany = getCompany;
|
|
@@ -21,6 +23,8 @@ const config_1 = require("./config");
|
|
|
21
23
|
exports.EXPOSES = [
|
|
22
24
|
'POST /crm/orgs/{org_id}/contacts',
|
|
23
25
|
'POST /crm/orgs/{org_id}/contacts/promote',
|
|
26
|
+
'POST /crm/orgs/{org_id}/contacts/promote-audience',
|
|
27
|
+
'POST /crm/orgs/{org_id}/contacts/import',
|
|
24
28
|
'POST /crm/orgs/{org_id}/contacts/search',
|
|
25
29
|
'GET /crm/orgs/{org_id}/contacts/{id}',
|
|
26
30
|
'PATCH /crm/orgs/{org_id}/contacts/{id}',
|
|
@@ -61,6 +65,37 @@ async function searchContacts(apiKey, orgId, filter = {}) {
|
|
|
61
65
|
async function promoteContact(apiKey, orgId, goldfoxPersonId) {
|
|
62
66
|
return (0, client_1.request)('POST', `${config_1.CRM_BASE}/crm/orgs/${encodeURIComponent(orgId)}/contacts/promote`, apiKey, { goldfox_person_id: goldfoxPersonId });
|
|
63
67
|
}
|
|
68
|
+
// Promotes ONE page. Idempotent, so resuming or repeating a page costs a
|
|
69
|
+
// match rather than a duplicate of somebody with the same address.
|
|
70
|
+
async function promoteAudience(apiKey, orgId, audienceId, opts) {
|
|
71
|
+
return (0, client_1.request)('POST', `${config_1.CRM_BASE}/crm/orgs/${encodeURIComponent(orgId)}/contacts/promote-audience`, apiKey, {
|
|
72
|
+
audience_id: audienceId, limit: opts?.limit, offset: opts?.offset,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
// Multipart, mirroring the container source upload. The server needs a `file`
|
|
76
|
+
// part; a raw CSV body is rejected with FILE_REQUIRED.
|
|
77
|
+
async function importContacts(apiKey, orgId, csv, filename = 'contacts.csv') {
|
|
78
|
+
const formData = new FormData();
|
|
79
|
+
const blob = typeof csv === 'string'
|
|
80
|
+
? new Blob([csv], { type: 'text/csv' })
|
|
81
|
+
: new Blob([csv], { type: 'text/csv' });
|
|
82
|
+
formData.append('file', blob, filename);
|
|
83
|
+
const response = await fetch(`${config_1.CRM_BASE}/crm/orgs/${encodeURIComponent(orgId)}/contacts/import`, { method: 'POST', headers: { Authorization: `Bearer ${apiKey}` }, body: formData });
|
|
84
|
+
let result;
|
|
85
|
+
try {
|
|
86
|
+
result = await response.json();
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
throw new client_1.MyApiError('invalid_json_response', response.status);
|
|
90
|
+
}
|
|
91
|
+
if (!response.ok || !result?.success) {
|
|
92
|
+
const err = result?.error;
|
|
93
|
+
const code = typeof err === 'object' ? (err?.code || 'unknown_error') : (err || 'unknown_error');
|
|
94
|
+
const detail = typeof err === 'object' ? err?.message : undefined;
|
|
95
|
+
throw new client_1.MyApiError(code, response.status, detail, typeof err === 'object' ? err : undefined);
|
|
96
|
+
}
|
|
97
|
+
return result.data;
|
|
98
|
+
}
|
|
64
99
|
async function getContactEvents(apiKey, orgId, id, opts = {}) {
|
|
65
100
|
const qs = new URLSearchParams();
|
|
66
101
|
if (opts.limit != null)
|
package/dist/email.d.ts
CHANGED
|
@@ -155,3 +155,77 @@ export declare function sendTestEmail(apiKey: string, orgId: string, templateId:
|
|
|
155
155
|
}>;
|
|
156
156
|
export declare function listTemplates(apiKey: string, orgId: string): Promise<EmailTemplate[]>;
|
|
157
157
|
export declare function deleteTemplate(apiKey: string, orgId: string, templateId: string): Promise<void>;
|
|
158
|
+
export type CampaignSourceKind = 'crm_query' | 'list';
|
|
159
|
+
/** A CRM contact filter, mirroring `crm contacts search`. */
|
|
160
|
+
export interface CampaignCRMQuery {
|
|
161
|
+
stage?: string;
|
|
162
|
+
origin?: string;
|
|
163
|
+
company_id?: string;
|
|
164
|
+
/** Engaged MORE than N days ago — includes contacts never engaged at all. */
|
|
165
|
+
max_last_engagement_days?: number;
|
|
166
|
+
/** Engaged within the last N days. */
|
|
167
|
+
min_last_engagement_days?: number;
|
|
168
|
+
}
|
|
169
|
+
export interface CampaignListSource {
|
|
170
|
+
addresses: string[];
|
|
171
|
+
}
|
|
172
|
+
export interface CreateCampaignInput {
|
|
173
|
+
name: string;
|
|
174
|
+
template_id: string;
|
|
175
|
+
from_address: string;
|
|
176
|
+
source_kind: CampaignSourceKind;
|
|
177
|
+
source_ref?: CampaignCRMQuery | CampaignListSource;
|
|
178
|
+
}
|
|
179
|
+
export interface Campaign {
|
|
180
|
+
id: string;
|
|
181
|
+
org_id: string;
|
|
182
|
+
name: string;
|
|
183
|
+
template_id: string;
|
|
184
|
+
from_address: string;
|
|
185
|
+
source_kind: CampaignSourceKind;
|
|
186
|
+
source_ref: unknown;
|
|
187
|
+
/** draft | ready | active | paused | paused_insufficient_funds | completed | cancelled */
|
|
188
|
+
status: string;
|
|
189
|
+
resolved_at: string | null;
|
|
190
|
+
recipient_count: number | null;
|
|
191
|
+
estimated_cost_cents: number | null;
|
|
192
|
+
created_at: string;
|
|
193
|
+
updated_at: string;
|
|
194
|
+
}
|
|
195
|
+
export interface CampaignResolution {
|
|
196
|
+
status: string;
|
|
197
|
+
recipients: number;
|
|
198
|
+
/** Counts by reason: suppressed, duplicate, invalid. */
|
|
199
|
+
excluded: Record<string, number>;
|
|
200
|
+
source_rows: number;
|
|
201
|
+
estimated_cost_cents: number;
|
|
202
|
+
note: string;
|
|
203
|
+
}
|
|
204
|
+
export interface CampaignRecipient {
|
|
205
|
+
id: string;
|
|
206
|
+
address: string;
|
|
207
|
+
contact_id: string | null;
|
|
208
|
+
state: string;
|
|
209
|
+
excluded_reason: string | null;
|
|
210
|
+
message_id: string | null;
|
|
211
|
+
error: string | null;
|
|
212
|
+
sent_at: string | null;
|
|
213
|
+
}
|
|
214
|
+
export interface CampaignStats {
|
|
215
|
+
status: string;
|
|
216
|
+
by_state: Record<string, number>;
|
|
217
|
+
sent_today: number;
|
|
218
|
+
per_day_limit: number;
|
|
219
|
+
}
|
|
220
|
+
export declare function createCampaign(apiKey: string, orgId: string, input: CreateCampaignInput): Promise<Campaign>;
|
|
221
|
+
export declare function listCampaigns(apiKey: string, orgId: string): Promise<Campaign[]>;
|
|
222
|
+
export declare function getCampaign(apiKey: string, orgId: string, id: string): Promise<Campaign>;
|
|
223
|
+
export declare function updateCampaign(apiKey: string, orgId: string, id: string, patch: Partial<CreateCampaignInput>): Promise<Campaign>;
|
|
224
|
+
/** Freezes the recipient set and reports who it reaches and what it would cost. Sends nothing. */
|
|
225
|
+
export declare function resolveCampaign(apiKey: string, orgId: string, id: string): Promise<CampaignResolution>;
|
|
226
|
+
export declare function startCampaign(apiKey: string, orgId: string, id: string): Promise<Campaign>;
|
|
227
|
+
export declare function pauseCampaign(apiKey: string, orgId: string, id: string): Promise<Campaign>;
|
|
228
|
+
export declare function resumeCampaign(apiKey: string, orgId: string, id: string): Promise<Campaign>;
|
|
229
|
+
export declare function cancelCampaign(apiKey: string, orgId: string, id: string): Promise<Campaign>;
|
|
230
|
+
export declare function listCampaignRecipients(apiKey: string, orgId: string, id: string, state?: string): Promise<CampaignRecipient[]>;
|
|
231
|
+
export declare function getCampaignStats(apiKey: string, orgId: string, id: string): Promise<CampaignStats>;
|
package/dist/email.js
CHANGED
|
@@ -30,6 +30,17 @@ exports.editTemplate = editTemplate;
|
|
|
30
30
|
exports.sendTestEmail = sendTestEmail;
|
|
31
31
|
exports.listTemplates = listTemplates;
|
|
32
32
|
exports.deleteTemplate = deleteTemplate;
|
|
33
|
+
exports.createCampaign = createCampaign;
|
|
34
|
+
exports.listCampaigns = listCampaigns;
|
|
35
|
+
exports.getCampaign = getCampaign;
|
|
36
|
+
exports.updateCampaign = updateCampaign;
|
|
37
|
+
exports.resolveCampaign = resolveCampaign;
|
|
38
|
+
exports.startCampaign = startCampaign;
|
|
39
|
+
exports.pauseCampaign = pauseCampaign;
|
|
40
|
+
exports.resumeCampaign = resumeCampaign;
|
|
41
|
+
exports.cancelCampaign = cancelCampaign;
|
|
42
|
+
exports.listCampaignRecipients = listCampaignRecipients;
|
|
43
|
+
exports.getCampaignStats = getCampaignStats;
|
|
33
44
|
const client_1 = require("./client");
|
|
34
45
|
const config_1 = require("./config");
|
|
35
46
|
exports.EXPOSES = [
|
|
@@ -67,6 +78,18 @@ exports.EXPOSES = [
|
|
|
67
78
|
'POST /email/orgs/{org_id}/verify',
|
|
68
79
|
'POST /email/orgs/{org_id}/verify-bulk',
|
|
69
80
|
'GET /email/orgs/{org_id}/verify-jobs/{id}',
|
|
81
|
+
// Campaigns — scheduling on top of send
|
|
82
|
+
'POST /email/orgs/{org_id}/campaigns',
|
|
83
|
+
'GET /email/orgs/{org_id}/campaigns',
|
|
84
|
+
'GET /email/orgs/{org_id}/campaigns/{campaign_id}',
|
|
85
|
+
'PATCH /email/orgs/{org_id}/campaigns/{campaign_id}',
|
|
86
|
+
'POST /email/orgs/{org_id}/campaigns/{campaign_id}/resolve',
|
|
87
|
+
'POST /email/orgs/{org_id}/campaigns/{campaign_id}/start',
|
|
88
|
+
'POST /email/orgs/{org_id}/campaigns/{campaign_id}/pause',
|
|
89
|
+
'POST /email/orgs/{org_id}/campaigns/{campaign_id}/resume',
|
|
90
|
+
'POST /email/orgs/{org_id}/campaigns/{campaign_id}/cancel',
|
|
91
|
+
'GET /email/orgs/{org_id}/campaigns/{campaign_id}/recipients',
|
|
92
|
+
'GET /email/orgs/{org_id}/campaigns/{campaign_id}/stats',
|
|
70
93
|
];
|
|
71
94
|
async function verifyEmail(apiKey, orgId, email) {
|
|
72
95
|
return (0, client_1.request)('POST', `${config_1.EMAIL_BASE}/email/orgs/${encodeURIComponent(orgId)}/verify`, apiKey, { email });
|
|
@@ -197,3 +220,47 @@ async function listTemplates(apiKey, orgId) {
|
|
|
197
220
|
async function deleteTemplate(apiKey, orgId, templateId) {
|
|
198
221
|
return (0, client_1.request)('DELETE', `${config_1.EMAIL_BASE}/email/orgs/${encodeURIComponent(orgId)}/templates/${encodeURIComponent(templateId)}`, apiKey);
|
|
199
222
|
}
|
|
223
|
+
function campaignsUrl(orgId) {
|
|
224
|
+
return `${config_1.EMAIL_BASE}/email/orgs/${encodeURIComponent(orgId)}/campaigns`;
|
|
225
|
+
}
|
|
226
|
+
function campaignUrl(orgId, id) {
|
|
227
|
+
return `${campaignsUrl(orgId)}/${encodeURIComponent(id)}`;
|
|
228
|
+
}
|
|
229
|
+
async function createCampaign(apiKey, orgId, input) {
|
|
230
|
+
return (0, client_1.request)('POST', campaignsUrl(orgId), apiKey, input);
|
|
231
|
+
}
|
|
232
|
+
// Walks the cursor: one page is not the whole list.
|
|
233
|
+
async function listCampaigns(apiKey, orgId) {
|
|
234
|
+
return (0, client_1.requestAll)(campaignsUrl(orgId), apiKey);
|
|
235
|
+
}
|
|
236
|
+
async function getCampaign(apiKey, orgId, id) {
|
|
237
|
+
return (0, client_1.request)('GET', campaignUrl(orgId, id), apiKey);
|
|
238
|
+
}
|
|
239
|
+
async function updateCampaign(apiKey, orgId, id, patch) {
|
|
240
|
+
return (0, client_1.request)('PATCH', campaignUrl(orgId, id), apiKey, patch);
|
|
241
|
+
}
|
|
242
|
+
/** Freezes the recipient set and reports who it reaches and what it would cost. Sends nothing. */
|
|
243
|
+
async function resolveCampaign(apiKey, orgId, id) {
|
|
244
|
+
return (0, client_1.request)('POST', `${campaignUrl(orgId, id)}/resolve`, apiKey);
|
|
245
|
+
}
|
|
246
|
+
async function startCampaign(apiKey, orgId, id) {
|
|
247
|
+
return (0, client_1.request)('POST', `${campaignUrl(orgId, id)}/start`, apiKey);
|
|
248
|
+
}
|
|
249
|
+
async function pauseCampaign(apiKey, orgId, id) {
|
|
250
|
+
return (0, client_1.request)('POST', `${campaignUrl(orgId, id)}/pause`, apiKey);
|
|
251
|
+
}
|
|
252
|
+
async function resumeCampaign(apiKey, orgId, id) {
|
|
253
|
+
return (0, client_1.request)('POST', `${campaignUrl(orgId, id)}/resume`, apiKey);
|
|
254
|
+
}
|
|
255
|
+
async function cancelCampaign(apiKey, orgId, id) {
|
|
256
|
+
return (0, client_1.request)('POST', `${campaignUrl(orgId, id)}/cancel`, apiKey);
|
|
257
|
+
}
|
|
258
|
+
async function listCampaignRecipients(apiKey, orgId, id, state) {
|
|
259
|
+
const url = state
|
|
260
|
+
? `${campaignUrl(orgId, id)}/recipients?state=${encodeURIComponent(state)}`
|
|
261
|
+
: `${campaignUrl(orgId, id)}/recipients`;
|
|
262
|
+
return (0, client_1.requestAll)(url, apiKey);
|
|
263
|
+
}
|
|
264
|
+
async function getCampaignStats(apiKey, orgId, id) {
|
|
265
|
+
return (0, client_1.request)('GET', `${campaignUrl(orgId, id)}/stats`, apiKey);
|
|
266
|
+
}
|
package/dist/hq.d.ts
CHANGED
|
@@ -76,6 +76,30 @@ export type FreeTierEntry = {
|
|
|
76
76
|
reset_at?: string;
|
|
77
77
|
};
|
|
78
78
|
export declare function getFreeTier(apiKey: string): Promise<FreeTierEntry[] | null>;
|
|
79
|
+
export interface SendingStatus {
|
|
80
|
+
sending_paused: boolean;
|
|
81
|
+
sends_24h: number;
|
|
82
|
+
bounces_24h: number;
|
|
83
|
+
complaints_24h: number;
|
|
84
|
+
bounce_threshold: number;
|
|
85
|
+
complaint_threshold: number;
|
|
86
|
+
within_limits: boolean;
|
|
87
|
+
/** Why it was paused, as recorded THEN — not whether it would pause now. */
|
|
88
|
+
paused_reason_when_paused?: string;
|
|
89
|
+
/** Present only while paused: whether a resume would be accepted today. */
|
|
90
|
+
can_resume_now?: boolean;
|
|
91
|
+
/** Set when under 100 sends in 24h, where the ratios are not judged. */
|
|
92
|
+
note?: string;
|
|
93
|
+
}
|
|
94
|
+
export interface ResumeSendingResult {
|
|
95
|
+
sending_paused: boolean;
|
|
96
|
+
resumed: boolean;
|
|
97
|
+
sends: number;
|
|
98
|
+
bounces: number;
|
|
99
|
+
message: string;
|
|
100
|
+
}
|
|
101
|
+
export declare function getSendingStatus(apiKey: string): Promise<SendingStatus>;
|
|
102
|
+
export declare function resumeSending(apiKey: string): Promise<ResumeSendingResult>;
|
|
79
103
|
export declare function getAccount(apiKey: string): Promise<AccountInfo>;
|
|
80
104
|
export declare function getMailingAddress(apiKey: string): Promise<{
|
|
81
105
|
mailing_address: string | null;
|
package/dist/hq.js
CHANGED
|
@@ -6,6 +6,8 @@ exports.sendCode = sendCode;
|
|
|
6
6
|
exports.verifyCode = verifyCode;
|
|
7
7
|
exports.upgradeAccount = upgradeAccount;
|
|
8
8
|
exports.getFreeTier = getFreeTier;
|
|
9
|
+
exports.getSendingStatus = getSendingStatus;
|
|
10
|
+
exports.resumeSending = resumeSending;
|
|
9
11
|
exports.getAccount = getAccount;
|
|
10
12
|
exports.getMailingAddress = getMailingAddress;
|
|
11
13
|
exports.setMailingAddress = setMailingAddress;
|
|
@@ -42,6 +44,8 @@ exports.EXPOSES = [
|
|
|
42
44
|
'PATCH /hq/account/upgrade',
|
|
43
45
|
'GET /hq/account/me',
|
|
44
46
|
'GET /hq/account/free-tier',
|
|
47
|
+
'GET /hq/account/sending',
|
|
48
|
+
'POST /hq/account/resume-sending',
|
|
45
49
|
'POST /hq/account/create/key',
|
|
46
50
|
'GET /hq/account/keys',
|
|
47
51
|
'POST /hq/account/keys/revoke-all',
|
|
@@ -92,6 +96,13 @@ async function upgradeAccount(apiKey, email) {
|
|
|
92
96
|
async function getFreeTier(apiKey) {
|
|
93
97
|
return (0, client_1.request)('GET', `${config_1.HQ_BASE}/hq/account/free-tier`, apiKey);
|
|
94
98
|
}
|
|
99
|
+
async function getSendingStatus(apiKey) {
|
|
100
|
+
return (0, client_1.request)('GET', `${config_1.HQ_BASE}/hq/account/sending`, apiKey);
|
|
101
|
+
}
|
|
102
|
+
// Rejected with STILL_OVER_THRESHOLD while the last 24h remain over the limit.
|
|
103
|
+
async function resumeSending(apiKey) {
|
|
104
|
+
return (0, client_1.request)('POST', `${config_1.HQ_BASE}/hq/account/resume-sending`, apiKey);
|
|
105
|
+
}
|
|
95
106
|
async function getAccount(apiKey) {
|
|
96
107
|
return (0, client_1.request)('GET', `${config_1.HQ_BASE}/hq/account/me`, apiKey);
|
|
97
108
|
}
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const SDK_VERSION = "2.
|
|
1
|
+
export declare const SDK_VERSION = "2.23.0";
|
package/dist/version.js
CHANGED
|
@@ -8,4 +8,4 @@ exports.SDK_VERSION = void 0;
|
|
|
8
8
|
// Why a constant and not a package.json read: the SDK runs inside edge
|
|
9
9
|
// functions (Cloudflare Workers), so it must not import node:fs. A literal
|
|
10
10
|
// is the only version source that works in every runtime we ship to.
|
|
11
|
-
exports.SDK_VERSION = '2.
|
|
11
|
+
exports.SDK_VERSION = '2.23.0';
|