@medalsocial/sdk 0.1.2 → 1.0.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/README.md +261 -86
- package/SECURITY.md +15 -0
- package/dist/index.d.mts +583 -78
- package/dist/index.d.ts +583 -78
- package/dist/index.js +348 -100
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +338 -100
- package/dist/index.mjs.map +1 -1
- package/package.json +26 -24
package/dist/index.d.ts
CHANGED
|
@@ -1,48 +1,393 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
clientId: string;
|
|
4
|
-
clientSecret: string;
|
|
5
|
-
} | {
|
|
6
|
-
kind: "bearer";
|
|
1
|
+
interface ClientConfig {
|
|
2
|
+
baseUrl: string;
|
|
7
3
|
token: string;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
auth: AuthOptions;
|
|
12
|
-
timeoutMs?: number;
|
|
13
|
-
userAgent?: string;
|
|
4
|
+
workspaceId?: string;
|
|
5
|
+
timeout: number;
|
|
6
|
+
userAgent: string;
|
|
14
7
|
}
|
|
15
|
-
|
|
16
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Low-level HTTP client used by all resource classes.
|
|
10
|
+
* Handles authentication, retries, timeout, and error parsing.
|
|
11
|
+
*/
|
|
12
|
+
declare class BaseClient {
|
|
13
|
+
readonly config: ClientConfig;
|
|
14
|
+
constructor(config: ClientConfig);
|
|
15
|
+
get<T>(path: string, params?: Record<string, string | undefined>): Promise<T>;
|
|
16
|
+
post<T>(path: string, body?: unknown): Promise<T>;
|
|
17
|
+
patch<T>(path: string, body: unknown): Promise<T>;
|
|
18
|
+
delete<T>(path: string): Promise<T>;
|
|
19
|
+
private buildUrl;
|
|
20
|
+
private request;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Successful API response wrapper */
|
|
24
|
+
interface ApiResponse<T> {
|
|
25
|
+
data: T;
|
|
26
|
+
}
|
|
27
|
+
/** Paginated API response */
|
|
28
|
+
interface PaginatedResponse<T> {
|
|
29
|
+
data: T[];
|
|
30
|
+
pagination: {
|
|
31
|
+
has_more: boolean;
|
|
32
|
+
next_cursor: string | null;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/** API error thrown by the client */
|
|
36
|
+
declare class MedalApiError extends Error {
|
|
37
|
+
readonly status: number;
|
|
38
|
+
readonly code: string;
|
|
39
|
+
readonly details?: unknown;
|
|
40
|
+
constructor(status: number, code: string, message: string, details?: unknown);
|
|
41
|
+
}
|
|
42
|
+
/** Pagination options for list endpoints */
|
|
43
|
+
interface PaginationOptions {
|
|
44
|
+
limit?: number;
|
|
45
|
+
cursor?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
interface Contact {
|
|
49
|
+
id: string;
|
|
17
50
|
email: string;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
51
|
+
first_name: string | null;
|
|
52
|
+
last_name: string | null;
|
|
53
|
+
phone: string | null;
|
|
54
|
+
company: string | null;
|
|
55
|
+
job_title: string | null;
|
|
56
|
+
address: Record<string, string> | null;
|
|
57
|
+
status: ContactStatus;
|
|
58
|
+
email_status: EmailStatus;
|
|
59
|
+
label_ids: string[];
|
|
60
|
+
source: string | null;
|
|
61
|
+
custom_fields: Record<string, unknown> | null;
|
|
62
|
+
created_at: string | null;
|
|
63
|
+
updated_at: string | null;
|
|
21
64
|
}
|
|
22
|
-
interface
|
|
23
|
-
|
|
24
|
-
note: string;
|
|
25
|
-
[key: string]: unknown;
|
|
65
|
+
interface ContactCreateResult {
|
|
66
|
+
id: string;
|
|
26
67
|
}
|
|
27
|
-
interface
|
|
28
|
-
|
|
68
|
+
interface ContactUpdateResult {
|
|
69
|
+
success: true;
|
|
70
|
+
}
|
|
71
|
+
interface ContactRemoveResult {
|
|
72
|
+
success: true;
|
|
73
|
+
}
|
|
74
|
+
interface ContactNoteResult {
|
|
75
|
+
id: string;
|
|
76
|
+
}
|
|
77
|
+
type ContactStatus = "lead" | "prospect" | "customer" | "churned" | "archived";
|
|
78
|
+
type EmailStatus = "subscribed" | "unsubscribed" | "bounced" | "complained";
|
|
79
|
+
interface CreateContactInput {
|
|
29
80
|
email: string;
|
|
30
|
-
|
|
31
|
-
|
|
81
|
+
first_name?: string;
|
|
82
|
+
last_name?: string;
|
|
83
|
+
phone?: string;
|
|
32
84
|
company?: string;
|
|
85
|
+
job_title?: string;
|
|
86
|
+
address?: Record<string, string>;
|
|
87
|
+
status?: ContactStatus;
|
|
88
|
+
email_status?: EmailStatus;
|
|
89
|
+
label_ids?: string[];
|
|
90
|
+
/** Label names — auto-created if they don't exist in the workspace. */
|
|
91
|
+
labels?: string[];
|
|
92
|
+
custom_fields?: Record<string, unknown>;
|
|
93
|
+
notes?: string | {
|
|
94
|
+
content: string;
|
|
95
|
+
attachments?: {
|
|
96
|
+
url: string;
|
|
97
|
+
name: string;
|
|
98
|
+
type?: string;
|
|
99
|
+
size?: number;
|
|
100
|
+
}[];
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
interface UpdateContactInput {
|
|
104
|
+
email?: string;
|
|
105
|
+
first_name?: string;
|
|
106
|
+
last_name?: string;
|
|
33
107
|
phone?: string;
|
|
34
|
-
|
|
35
|
-
|
|
108
|
+
company?: string;
|
|
109
|
+
job_title?: string;
|
|
110
|
+
status?: ContactStatus;
|
|
111
|
+
email_status?: EmailStatus;
|
|
112
|
+
label_ids?: string[];
|
|
113
|
+
/** Label names — auto-created if they don't exist in the workspace. */
|
|
114
|
+
labels?: string[];
|
|
115
|
+
custom_fields?: Record<string, unknown>;
|
|
36
116
|
}
|
|
37
|
-
interface
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
117
|
+
interface ListContactsOptions extends PaginationOptions {
|
|
118
|
+
status?: ContactStatus;
|
|
119
|
+
email_status?: EmailStatus;
|
|
120
|
+
label_ids?: string[];
|
|
121
|
+
search?: string;
|
|
41
122
|
}
|
|
42
|
-
interface
|
|
43
|
-
|
|
44
|
-
|
|
123
|
+
interface ImportContactInput {
|
|
124
|
+
email: string;
|
|
125
|
+
first_name?: string;
|
|
126
|
+
last_name?: string;
|
|
127
|
+
phone?: string;
|
|
128
|
+
company?: string;
|
|
129
|
+
job_title?: string;
|
|
130
|
+
label_ids?: string[];
|
|
131
|
+
status?: string;
|
|
132
|
+
}
|
|
133
|
+
interface ImportContactsResult {
|
|
134
|
+
added: number;
|
|
135
|
+
skipped: number;
|
|
136
|
+
total: number;
|
|
137
|
+
}
|
|
138
|
+
interface Activity {
|
|
139
|
+
id: string;
|
|
140
|
+
type: string;
|
|
141
|
+
title: string | null;
|
|
142
|
+
content: string | null;
|
|
143
|
+
actor_name: string | null;
|
|
144
|
+
actor_type: string | null;
|
|
145
|
+
metadata: unknown;
|
|
146
|
+
created_at: string | null;
|
|
147
|
+
}
|
|
148
|
+
interface AddNoteInput {
|
|
149
|
+
content: string;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
declare class Contacts {
|
|
153
|
+
private client;
|
|
154
|
+
constructor(client: BaseClient);
|
|
155
|
+
/** List contacts with cursor-based pagination and optional filters. */
|
|
156
|
+
list(options?: ListContactsOptions): Promise<PaginatedResponse<Contact>>;
|
|
157
|
+
/** Create a new contact. Email must be unique in the workspace. */
|
|
158
|
+
create(input: CreateContactInput): Promise<ApiResponse<ContactCreateResult>>;
|
|
159
|
+
/** Get a contact by ID. */
|
|
160
|
+
get(id: string): Promise<ApiResponse<Contact>>;
|
|
161
|
+
/** Update one or more fields on a contact. */
|
|
162
|
+
update(id: string, input: UpdateContactInput): Promise<ApiResponse<ContactUpdateResult>>;
|
|
163
|
+
/** Permanently delete a contact. */
|
|
164
|
+
remove(id: string): Promise<ApiResponse<ContactRemoveResult>>;
|
|
165
|
+
/** Get the activity timeline for a contact. */
|
|
166
|
+
activities(id: string, options?: PaginationOptions): Promise<PaginatedResponse<Activity>>;
|
|
167
|
+
/** Add a note to a contact's timeline. */
|
|
168
|
+
addNote(id: string, input: AddNoteInput): Promise<ApiResponse<ContactNoteResult>>;
|
|
169
|
+
/** Bulk import contacts (max 500). Duplicates are skipped. */
|
|
170
|
+
import(contacts: ImportContactInput[]): Promise<ApiResponse<ImportContactsResult>>;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
interface Deal {
|
|
174
|
+
id: string;
|
|
175
|
+
title: string;
|
|
176
|
+
description: string | null;
|
|
177
|
+
value: number | null;
|
|
178
|
+
currency: string | null;
|
|
179
|
+
status: DealStatus;
|
|
180
|
+
brand_name: string | null;
|
|
181
|
+
brand_website: string | null;
|
|
182
|
+
contact_id: string | null;
|
|
183
|
+
contact_name: string | null;
|
|
184
|
+
contact_email: string | null;
|
|
185
|
+
start_date: string | null;
|
|
186
|
+
end_date: string | null;
|
|
187
|
+
notes: string | null;
|
|
188
|
+
created_at: string | null;
|
|
189
|
+
updated_at: string | null;
|
|
190
|
+
}
|
|
191
|
+
interface DealCreateResult {
|
|
192
|
+
id: string;
|
|
45
193
|
}
|
|
194
|
+
interface DealUpdateResult {
|
|
195
|
+
success: true;
|
|
196
|
+
}
|
|
197
|
+
interface DealRemoveResult {
|
|
198
|
+
success: true;
|
|
199
|
+
}
|
|
200
|
+
type DealStatus = "draft" | "open" | "won" | "lost" | "negotiating" | "proposal_sent" | "on_hold" | "churned";
|
|
201
|
+
interface CreateDealInput {
|
|
202
|
+
title: string;
|
|
203
|
+
description?: string;
|
|
204
|
+
value?: number;
|
|
205
|
+
currency?: string;
|
|
206
|
+
brand_name?: string;
|
|
207
|
+
brand_website?: string;
|
|
208
|
+
contact_id?: string;
|
|
209
|
+
contact_name?: string;
|
|
210
|
+
contact_email?: string;
|
|
211
|
+
start_date?: string;
|
|
212
|
+
end_date?: string;
|
|
213
|
+
notes?: string;
|
|
214
|
+
}
|
|
215
|
+
interface UpdateDealInput {
|
|
216
|
+
title?: string;
|
|
217
|
+
description?: string;
|
|
218
|
+
value?: number;
|
|
219
|
+
currency?: string;
|
|
220
|
+
status?: DealStatus;
|
|
221
|
+
brand_name?: string;
|
|
222
|
+
brand_website?: string;
|
|
223
|
+
contact_id?: string | null;
|
|
224
|
+
contact_name?: string;
|
|
225
|
+
contact_email?: string;
|
|
226
|
+
start_date?: string;
|
|
227
|
+
end_date?: string;
|
|
228
|
+
notes?: string;
|
|
229
|
+
}
|
|
230
|
+
interface ListDealsOptions extends PaginationOptions {
|
|
231
|
+
status?: DealStatus;
|
|
232
|
+
search?: string;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
declare class Deals {
|
|
236
|
+
private client;
|
|
237
|
+
constructor(client: BaseClient);
|
|
238
|
+
/** List deals with cursor-based pagination and optional filters. */
|
|
239
|
+
list(options?: ListDealsOptions): Promise<PaginatedResponse<Deal>>;
|
|
240
|
+
/** Create a new deal. */
|
|
241
|
+
create(input: CreateDealInput): Promise<ApiResponse<DealCreateResult>>;
|
|
242
|
+
/** Get a deal by ID. */
|
|
243
|
+
get(id: string): Promise<ApiResponse<Deal>>;
|
|
244
|
+
/** Update one or more fields on a deal. Set contact_id to null to unlink. */
|
|
245
|
+
update(id: string, input: UpdateDealInput): Promise<ApiResponse<DealUpdateResult>>;
|
|
246
|
+
/** Permanently delete a deal. */
|
|
247
|
+
remove(id: string): Promise<ApiResponse<DealRemoveResult>>;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
interface SendEmailInput {
|
|
251
|
+
template_slug: string;
|
|
252
|
+
to: string;
|
|
253
|
+
name?: string;
|
|
254
|
+
locale?: string;
|
|
255
|
+
fallback_locale?: string;
|
|
256
|
+
variables?: Record<string, string>;
|
|
257
|
+
contact_id?: string;
|
|
258
|
+
}
|
|
259
|
+
interface EmailSendResult {
|
|
260
|
+
id: string;
|
|
261
|
+
status: string;
|
|
262
|
+
}
|
|
263
|
+
interface EmailSend {
|
|
264
|
+
id: string;
|
|
265
|
+
status: string;
|
|
266
|
+
recipient_email: string;
|
|
267
|
+
recipient_name: string | null;
|
|
268
|
+
subject: string | null;
|
|
269
|
+
template_id: string | null;
|
|
270
|
+
contact_id: string | null;
|
|
271
|
+
queued_at: string | null;
|
|
272
|
+
sent_at: string | null;
|
|
273
|
+
delivered_at: string | null;
|
|
274
|
+
opened_at: string | null;
|
|
275
|
+
clicked_at: string | null;
|
|
276
|
+
error_message: string | null;
|
|
277
|
+
}
|
|
278
|
+
interface BatchSendInput {
|
|
279
|
+
template_slug: string;
|
|
280
|
+
default_locale?: string;
|
|
281
|
+
recipients: {
|
|
282
|
+
email: string;
|
|
283
|
+
name?: string;
|
|
284
|
+
locale?: string;
|
|
285
|
+
variables?: Record<string, string>;
|
|
286
|
+
}[];
|
|
287
|
+
}
|
|
288
|
+
interface BatchSendSummary {
|
|
289
|
+
batch_id: string;
|
|
290
|
+
total: number;
|
|
291
|
+
queued: number;
|
|
292
|
+
failed: number;
|
|
293
|
+
}
|
|
294
|
+
/** @deprecated Use `BatchSendSummary` for `emails.batch()` responses. */
|
|
295
|
+
type BatchSendResult = BatchSendSummary;
|
|
296
|
+
interface EmailTemplate {
|
|
297
|
+
id: string;
|
|
298
|
+
name: string;
|
|
299
|
+
slug: string;
|
|
300
|
+
type: string | null;
|
|
301
|
+
subject: string | null;
|
|
302
|
+
default_locale: string;
|
|
303
|
+
available_locales: string[];
|
|
304
|
+
description: string | null;
|
|
305
|
+
category: string | null;
|
|
306
|
+
label_ids: string[];
|
|
307
|
+
is_active: boolean;
|
|
308
|
+
is_archived: boolean;
|
|
309
|
+
version: number;
|
|
310
|
+
created_at: string | null;
|
|
311
|
+
updated_at: string | null;
|
|
312
|
+
}
|
|
313
|
+
interface EmailTemplateDetail extends EmailTemplate {
|
|
314
|
+
html_content: string | null;
|
|
315
|
+
text_content: string | null;
|
|
316
|
+
preview_text: string | null;
|
|
317
|
+
from_name: string | null;
|
|
318
|
+
from_email: string | null;
|
|
319
|
+
reply_to: string | null;
|
|
320
|
+
requested_locale: string | null;
|
|
321
|
+
resolved_locale: string;
|
|
322
|
+
content_source: string;
|
|
323
|
+
localizations: {
|
|
324
|
+
locale: string | null;
|
|
325
|
+
subject: string | null;
|
|
326
|
+
html_content: string | null;
|
|
327
|
+
text_content: string | null;
|
|
328
|
+
preview_text: string | null;
|
|
329
|
+
}[];
|
|
330
|
+
}
|
|
331
|
+
interface GetTemplateOptions {
|
|
332
|
+
locale?: string;
|
|
333
|
+
fallback_locale?: string;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
declare class EmailTemplates {
|
|
337
|
+
private client;
|
|
338
|
+
constructor(client: BaseClient);
|
|
339
|
+
/** List all active email templates in the workspace. */
|
|
340
|
+
list(): Promise<ApiResponse<EmailTemplate[]>>;
|
|
341
|
+
/** Get a specific email template by slug, optionally with locale resolution. */
|
|
342
|
+
get(slug: string, options?: GetTemplateOptions): Promise<ApiResponse<EmailTemplateDetail>>;
|
|
343
|
+
}
|
|
344
|
+
declare class Emails {
|
|
345
|
+
private client;
|
|
346
|
+
readonly templates: EmailTemplates;
|
|
347
|
+
constructor(client: BaseClient);
|
|
348
|
+
/** Send a transactional email using a template. Returns a queued job ID (HTTP 202). */
|
|
349
|
+
send(input: SendEmailInput): Promise<ApiResponse<EmailSendResult>>;
|
|
350
|
+
/** Get the delivery status of a sent email. */
|
|
351
|
+
get(id: string): Promise<ApiResponse<EmailSend>>;
|
|
352
|
+
/** Send the same template to multiple recipients (max 100). Returns HTTP 202. */
|
|
353
|
+
batch(input: BatchSendInput): Promise<ApiResponse<BatchSendSummary>>;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
interface GdprExport {
|
|
357
|
+
id: string;
|
|
358
|
+
request_type: string;
|
|
359
|
+
status: "pending" | "in_progress" | "completed" | "failed" | string;
|
|
360
|
+
submitted_at: string | null;
|
|
361
|
+
completed_at: string | null;
|
|
362
|
+
due_date?: string | null;
|
|
363
|
+
download_url?: string | null;
|
|
364
|
+
expires_at?: string | null;
|
|
365
|
+
}
|
|
366
|
+
type ConsentType = "marketing_email" | "analytics_tracking" | "third_party_sharing";
|
|
367
|
+
interface RecordConsentInput {
|
|
368
|
+
email: string;
|
|
369
|
+
consent_type: ConsentType;
|
|
370
|
+
granted: boolean;
|
|
371
|
+
source?: string;
|
|
372
|
+
ip_address?: string;
|
|
373
|
+
consent_text?: string;
|
|
374
|
+
version?: string;
|
|
375
|
+
}
|
|
376
|
+
interface ConsentRecord {
|
|
377
|
+
id: string;
|
|
378
|
+
email: string;
|
|
379
|
+
consent_type: ConsentType;
|
|
380
|
+
granted: boolean;
|
|
381
|
+
granted_at: string | null;
|
|
382
|
+
revoked_at: string | null;
|
|
383
|
+
source?: string;
|
|
384
|
+
version?: string;
|
|
385
|
+
}
|
|
386
|
+
interface ConsentResult {
|
|
387
|
+
id: string;
|
|
388
|
+
}
|
|
389
|
+
/** @deprecated Use `ConsentRecord[]` for `gdpr.getConsent()` responses. */
|
|
390
|
+
type ContactConsents = ConsentRecord[];
|
|
46
391
|
interface CookieConsentInput {
|
|
47
392
|
domain: string;
|
|
48
393
|
consentStatus: "granted" | "denied" | "partial" | string;
|
|
@@ -57,52 +402,212 @@ interface CookieConsentInput {
|
|
|
57
402
|
[key: string]: CookieCategoryConsent | undefined;
|
|
58
403
|
};
|
|
59
404
|
}
|
|
60
|
-
interface
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
externalId: string;
|
|
68
|
-
name: string;
|
|
69
|
-
description?: string;
|
|
70
|
-
time: string;
|
|
71
|
-
location?: string;
|
|
72
|
-
thumbnail?: string;
|
|
73
|
-
};
|
|
405
|
+
interface CookieCategoryConsent {
|
|
406
|
+
allowed: boolean;
|
|
407
|
+
cookieRecords?: {
|
|
408
|
+
cookie: string;
|
|
409
|
+
duration: string;
|
|
410
|
+
description: string;
|
|
411
|
+
}[];
|
|
74
412
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
413
|
+
|
|
414
|
+
declare class Gdpr {
|
|
415
|
+
private client;
|
|
416
|
+
constructor(client: BaseClient);
|
|
417
|
+
/** Request a workspace data export. Runs asynchronously. */
|
|
418
|
+
requestExport(): Promise<ApiResponse<{
|
|
419
|
+
request_id: string;
|
|
420
|
+
status: string;
|
|
421
|
+
}>>;
|
|
422
|
+
/** List all workspace export requests. */
|
|
423
|
+
listExports(): Promise<ApiResponse<GdprExport[]>>;
|
|
424
|
+
/** Get the status of a specific export. */
|
|
425
|
+
getExport(id: string): Promise<ApiResponse<GdprExport>>;
|
|
426
|
+
/** Record a GDPR consent decision for a contact by email. */
|
|
427
|
+
recordConsent(input: RecordConsentInput): Promise<ApiResponse<ConsentResult>>;
|
|
428
|
+
/** Get all consent records for a contact by email. */
|
|
429
|
+
getConsent(email: string): Promise<ApiResponse<ConsentRecord[]>>;
|
|
430
|
+
/** Record cookie consent from an external site (legacy endpoint). */
|
|
431
|
+
cookieConsent(input: CookieConsentInput): Promise<{
|
|
432
|
+
success: boolean;
|
|
433
|
+
logId?: string;
|
|
434
|
+
}>;
|
|
79
435
|
}
|
|
80
|
-
|
|
81
|
-
|
|
436
|
+
|
|
437
|
+
interface Post {
|
|
438
|
+
id: string;
|
|
439
|
+
type: PostType;
|
|
440
|
+
title: string | null;
|
|
441
|
+
content: string;
|
|
442
|
+
status: string;
|
|
443
|
+
channel_ids: string[];
|
|
444
|
+
variant_count: number;
|
|
445
|
+
published_count: number;
|
|
446
|
+
failed_count: number;
|
|
447
|
+
scheduled_at: string | null;
|
|
448
|
+
published_at: string | null;
|
|
449
|
+
created_at: string | null;
|
|
450
|
+
updated_at: string | null;
|
|
451
|
+
}
|
|
452
|
+
type PostType = "social" | "newsletter" | "blog";
|
|
453
|
+
interface PostVariant {
|
|
454
|
+
id: string;
|
|
455
|
+
channel_id: string;
|
|
456
|
+
content: string;
|
|
457
|
+
status: string;
|
|
458
|
+
platform: string | null;
|
|
459
|
+
channel_display_name: string | null;
|
|
460
|
+
scheduled_at: string | null;
|
|
461
|
+
published_at: string | null;
|
|
462
|
+
platform_post_id: string | null;
|
|
463
|
+
permalink: string | null;
|
|
464
|
+
error: string | null;
|
|
465
|
+
}
|
|
466
|
+
interface PostDetail extends Post {
|
|
467
|
+
variants: PostVariant[];
|
|
468
|
+
}
|
|
469
|
+
interface Channel {
|
|
470
|
+
id: string;
|
|
471
|
+
platform: string | null;
|
|
472
|
+
display_name: string | null;
|
|
473
|
+
platform_username: string | null;
|
|
474
|
+
state: string;
|
|
475
|
+
connected_at: string | null;
|
|
476
|
+
}
|
|
477
|
+
interface CreatePostInput {
|
|
478
|
+
type?: PostType;
|
|
479
|
+
title?: string;
|
|
480
|
+
content: string;
|
|
481
|
+
channel_ids: string[];
|
|
482
|
+
}
|
|
483
|
+
interface UpdatePostInput {
|
|
484
|
+
title?: string;
|
|
485
|
+
content?: string;
|
|
486
|
+
}
|
|
487
|
+
interface SchedulePostInput {
|
|
488
|
+
/** Unix timestamp (ms) or ISO datetime string. */
|
|
489
|
+
scheduled_at: number | string;
|
|
490
|
+
}
|
|
491
|
+
interface ListPostsOptions extends PaginationOptions {
|
|
492
|
+
status?: string;
|
|
493
|
+
type?: PostType;
|
|
494
|
+
}
|
|
495
|
+
interface ScheduleResult {
|
|
496
|
+
success: boolean;
|
|
497
|
+
workflow_id: string;
|
|
498
|
+
}
|
|
499
|
+
interface PublishResult {
|
|
500
|
+
success: boolean;
|
|
501
|
+
workflow_id: string;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
declare class Posts {
|
|
505
|
+
private client;
|
|
506
|
+
constructor(client: BaseClient);
|
|
507
|
+
/** List posts with cursor-based pagination and optional filters. */
|
|
508
|
+
list(options?: ListPostsOptions): Promise<PaginatedResponse<Post>>;
|
|
509
|
+
/** Create a new post with content and target channels. */
|
|
510
|
+
create(input: CreatePostInput): Promise<ApiResponse<{
|
|
511
|
+
id: string;
|
|
512
|
+
}>>;
|
|
513
|
+
/** Get a post by ID, including its per-channel variants. */
|
|
514
|
+
get(id: string): Promise<ApiResponse<PostDetail>>;
|
|
515
|
+
/** Update a draft post's title or content. */
|
|
516
|
+
update(id: string, input: UpdatePostInput): Promise<ApiResponse<{
|
|
517
|
+
success: boolean;
|
|
518
|
+
}>>;
|
|
519
|
+
/** Delete a post. */
|
|
520
|
+
remove(id: string): Promise<ApiResponse<{
|
|
521
|
+
success: boolean;
|
|
522
|
+
}>>;
|
|
523
|
+
/** Schedule a post for future publication. */
|
|
524
|
+
schedule(id: string, input: SchedulePostInput): Promise<ApiResponse<ScheduleResult>>;
|
|
525
|
+
/** Publish a post immediately to all target channels. */
|
|
526
|
+
publish(id: string): Promise<ApiResponse<PublishResult>>;
|
|
527
|
+
/** List connected publishing channels for this workspace. */
|
|
528
|
+
channels(): Promise<ApiResponse<Channel[]>>;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
interface Workspace {
|
|
532
|
+
id: string;
|
|
533
|
+
name: string;
|
|
82
534
|
slug: string;
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
private
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
535
|
+
[key: string]: unknown;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
declare class Workspaces {
|
|
539
|
+
private client;
|
|
540
|
+
constructor(client: BaseClient);
|
|
541
|
+
/** List workspaces accessible to the current API key or OAuth token. */
|
|
542
|
+
list(): Promise<ApiResponse<Workspace[]>>;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
interface MedalOptions {
|
|
546
|
+
/** Override the base URL (defaults to https://api.medalsocial.com). */
|
|
547
|
+
baseUrl?: string;
|
|
548
|
+
/** Request timeout in ms (default 30000). */
|
|
549
|
+
timeout?: number;
|
|
550
|
+
/**
|
|
551
|
+
* Workspace ID — required for OAuth access tokens, ignored for API keys.
|
|
552
|
+
* API keys are scoped to a single workspace, so the workspace is inferred.
|
|
553
|
+
* OAuth tokens can access multiple workspaces, so you must specify which one.
|
|
554
|
+
*/
|
|
555
|
+
workspaceId?: string;
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* Medal Social SDK client.
|
|
559
|
+
*
|
|
560
|
+
* Supports both API key and OAuth access token authentication:
|
|
561
|
+
*
|
|
562
|
+
* @example API Key (recommended for server-side)
|
|
563
|
+
* ```ts
|
|
564
|
+
* import { Medal } from '@medalsocial/sdk';
|
|
565
|
+
*
|
|
566
|
+
* // API keys start with medal_ and are scoped to one workspace
|
|
567
|
+
* const medal = new Medal('medal_xxx');
|
|
568
|
+
* ```
|
|
569
|
+
*
|
|
570
|
+
* @example OAuth Access Token
|
|
571
|
+
* ```ts
|
|
572
|
+
* // OAuth tokens require a workspaceId
|
|
573
|
+
* const medal = new Medal('oauth_access_token', {
|
|
574
|
+
* workspaceId: 'workspace_id_here',
|
|
575
|
+
* });
|
|
576
|
+
* ```
|
|
577
|
+
*
|
|
578
|
+
* @example Full usage
|
|
579
|
+
* ```ts
|
|
580
|
+
* const medal = new Medal('medal_xxx');
|
|
581
|
+
*
|
|
582
|
+
* // Posts — create, schedule, publish
|
|
583
|
+
* const { data: post } = await medal.posts.create({
|
|
584
|
+
* content: 'Hello world!',
|
|
585
|
+
* channel_ids: ['ch_1'],
|
|
586
|
+
* });
|
|
587
|
+
* await medal.posts.schedule(post.id, { scheduled_at: '2026-03-15T10:00:00Z' });
|
|
588
|
+
*
|
|
589
|
+
* // Emails — send transactional emails
|
|
590
|
+
* await medal.emails.send({
|
|
591
|
+
* template_slug: 'welcome',
|
|
592
|
+
* to: 'user@example.com',
|
|
593
|
+
* variables: { name: 'John' },
|
|
594
|
+
* });
|
|
595
|
+
*
|
|
596
|
+
* // Contacts, Deals, GDPR, Workspaces
|
|
597
|
+
* const contacts = await medal.contacts.list({ status: 'lead' });
|
|
598
|
+
* const { data: deal } = await medal.deals.create({ title: 'Acme', value: 50000 });
|
|
599
|
+
* await medal.gdpr.recordConsent({ email: 'u@x.com', consent_type: 'marketing_email', granted: true });
|
|
600
|
+
* const { data: workspaces } = await medal.workspaces.list();
|
|
601
|
+
* ```
|
|
602
|
+
*/
|
|
603
|
+
declare class Medal {
|
|
604
|
+
readonly emails: Emails;
|
|
605
|
+
readonly contacts: Contacts;
|
|
606
|
+
readonly deals: Deals;
|
|
607
|
+
readonly gdpr: Gdpr;
|
|
608
|
+
readonly posts: Posts;
|
|
609
|
+
readonly workspaces: Workspaces;
|
|
610
|
+
constructor(token: string, options?: MedalOptions);
|
|
106
611
|
}
|
|
107
612
|
|
|
108
|
-
export { type ApiResponse, type
|
|
613
|
+
export { type Activity, type AddNoteInput, type ApiResponse, BaseClient, type BatchSendInput, type BatchSendResult, type BatchSendSummary, type Channel, type ConsentRecord, type ConsentResult, type ConsentType, type Contact, type ContactConsents, type ContactCreateResult, type ContactNoteResult, type ContactRemoveResult, type ContactStatus, type ContactUpdateResult, Contacts, type CookieCategoryConsent, type CookieConsentInput, type CreateContactInput, type CreateDealInput, type CreatePostInput, type Deal, type DealCreateResult, type DealRemoveResult, type DealStatus, type DealUpdateResult, Deals, type EmailSend, type EmailSendResult, type EmailStatus, type EmailTemplate, type EmailTemplateDetail, Emails, Gdpr, type GdprExport, type GetTemplateOptions, type ImportContactInput, type ImportContactsResult, type ListContactsOptions, type ListDealsOptions, type ListPostsOptions, Medal, MedalApiError, type MedalOptions, type PaginatedResponse, type PaginationOptions, type Post, type PostDetail, type PostType, type PostVariant, Posts, type PublishResult, type RecordConsentInput, type SchedulePostInput, type ScheduleResult, type SendEmailInput, type UpdateContactInput, type UpdateDealInput, type UpdatePostInput, type Workspace, Workspaces, Medal as default };
|