@meridesk/node-sdk 0.1.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.
@@ -0,0 +1,303 @@
1
+ interface HttpClientOptions {
2
+ apiKey: string;
3
+ baseUrl: string;
4
+ timeoutMs?: number;
5
+ }
6
+ interface RequestOptions {
7
+ query?: Record<string, string | number | boolean | undefined | null>;
8
+ body?: unknown;
9
+ }
10
+ /**
11
+ * Thin wrapper around the global `fetch` for talking to the Meridesk SDK API.
12
+ * Handles auth headers, JSON encoding/decoding, timeouts, and translating
13
+ * non-2xx responses into `MerideskAPIError`.
14
+ */
15
+ declare class HttpClient {
16
+ private readonly apiKey;
17
+ private readonly baseUrl;
18
+ private readonly timeoutMs;
19
+ constructor(options: HttpClientOptions);
20
+ private buildUrl;
21
+ private request;
22
+ get<T>(path: string, query?: RequestOptions['query']): Promise<T>;
23
+ post<T>(path: string, body?: unknown): Promise<T>;
24
+ patch<T>(path: string, body?: unknown): Promise<T>;
25
+ }
26
+
27
+ /**
28
+ * Configuration accepted by `new Meridesk(config)`.
29
+ */
30
+ interface MerideskConfig {
31
+ /**
32
+ * Your Meridesk API key (starts with `mdk_live_`). Create one from
33
+ * Settings > API Keys in your Meridesk dashboard.
34
+ */
35
+ apiKey: string;
36
+ /**
37
+ * Your Meridesk identity verification secret, returned once alongside
38
+ * your API key when it was created/regenerated. Required only to use
39
+ * `meridesk.identity.generateUserHash()` for secure widget mode.
40
+ */
41
+ identitySecret?: string;
42
+ /**
43
+ * Override the Meridesk API base URL. Defaults to the production SDK API.
44
+ * Mainly useful for testing against a local/staging backend.
45
+ */
46
+ baseUrl?: string;
47
+ /** Request timeout in milliseconds. Defaults to 15000. */
48
+ timeoutMs?: number;
49
+ }
50
+ interface MerideskWebsite {
51
+ id: string;
52
+ name: string;
53
+ subdomain: string;
54
+ accountId: string;
55
+ }
56
+ interface MerideskApiKeyInfo {
57
+ id: string;
58
+ name: string;
59
+ prefix: string;
60
+ last4: string;
61
+ }
62
+ interface MeResponse {
63
+ website: MerideskWebsite;
64
+ apiKey: MerideskApiKeyInfo;
65
+ }
66
+ interface Customer {
67
+ id?: string;
68
+ _id?: string;
69
+ name: string;
70
+ email: string;
71
+ phone?: string;
72
+ company?: string;
73
+ position?: string;
74
+ status?: 'active' | 'inactive' | 'lead' | 'prospect' | 'customer';
75
+ timezone?: string;
76
+ address?: string;
77
+ externalIds?: Record<string, string>;
78
+ createdAt?: string;
79
+ updatedAt?: string;
80
+ }
81
+ interface UpsertCustomerInput {
82
+ email: string;
83
+ name?: string;
84
+ phone?: string;
85
+ company?: string;
86
+ position?: string;
87
+ externalIds?: Record<string, string>;
88
+ }
89
+ interface UpdateCustomerInput {
90
+ name?: string;
91
+ phone?: string;
92
+ company?: string;
93
+ position?: string;
94
+ status?: Customer['status'];
95
+ externalIds?: Record<string, string>;
96
+ }
97
+ type TicketStatus = 'open' | 'pending' | 'closed' | 'resolved';
98
+ type TicketPriority = 'low' | 'medium' | 'high' | 'urgent';
99
+ interface TicketMessage {
100
+ id: string;
101
+ message: string;
102
+ user: string;
103
+ attachments?: string[];
104
+ createdOn: string;
105
+ sender: 'support' | 'customer' | 'system' | 'assistant' | 'user';
106
+ }
107
+ interface Ticket {
108
+ id: string;
109
+ _id?: string;
110
+ ticketNumber: string;
111
+ name: string;
112
+ email: string;
113
+ title: string;
114
+ message: string;
115
+ status: TicketStatus;
116
+ priority: TicketPriority;
117
+ assignee?: string | null;
118
+ createdOn: string;
119
+ updatedOn: string;
120
+ chat?: TicketMessage[];
121
+ }
122
+ interface CreateTicketInput {
123
+ /** Email of the customer this ticket belongs to. Created if it doesn't exist yet. */
124
+ email: string;
125
+ /** Display name for the customer, used if they need to be created. */
126
+ name?: string;
127
+ title: string;
128
+ message: string;
129
+ priority?: TicketPriority;
130
+ }
131
+ interface ListTicketsParams {
132
+ email?: string;
133
+ status?: TicketStatus;
134
+ }
135
+ interface ReplyToTicketInput {
136
+ message: string;
137
+ /** Defaults to 'support' (i.e. a reply sent from your backend). */
138
+ sender?: 'support' | 'customer';
139
+ }
140
+ interface ArticleTopic {
141
+ _id?: string;
142
+ title: string;
143
+ content: string;
144
+ coverImage?: string;
145
+ helpfulCount?: number;
146
+ notHelpfulCount?: number;
147
+ }
148
+ interface Article {
149
+ _id?: string;
150
+ title: string;
151
+ description?: string;
152
+ icon?: string;
153
+ iconBg?: string;
154
+ topics: ArticleTopic[];
155
+ }
156
+ interface ArticleCategory {
157
+ _id?: string;
158
+ name: string;
159
+ articles: Article[];
160
+ }
161
+ interface ArticleSearchResult {
162
+ _id: string;
163
+ article: Article;
164
+ category: {
165
+ id: string;
166
+ name: string;
167
+ };
168
+ }
169
+
170
+ declare class ArticlesResource {
171
+ private readonly http;
172
+ constructor(http: HttpClient);
173
+ /** Lists all knowledge base categories (with their nested articles/topics) for this website. */
174
+ listCategories(): Promise<ArticleCategory[]>;
175
+ /** Full-text searches article titles/topics for this website. */
176
+ search(query: string): Promise<ArticleSearchResult[]>;
177
+ }
178
+
179
+ declare class CustomersResource {
180
+ private readonly http;
181
+ constructor(http: HttpClient);
182
+ /**
183
+ * Creates a customer if one doesn't exist for this email yet, or updates
184
+ * the provided fields on the existing one.
185
+ */
186
+ upsert(input: UpsertCustomerInput): Promise<Customer>;
187
+ /** Fetches a customer by email. */
188
+ get(email: string): Promise<Customer>;
189
+ /** Updates one or more fields on an existing customer. */
190
+ update(email: string, input: UpdateCustomerInput): Promise<Customer>;
191
+ }
192
+
193
+ /**
194
+ * Generates HMAC-SHA256 identity verification hashes for the Meridesk
195
+ * widget's "secure mode", entirely locally — no network call is made.
196
+ *
197
+ * This mirrors the identity verification pattern used by Intercom/Zendesk:
198
+ * your backend signs a stable identifier for the logged-in user (their
199
+ * email or internal user id) with the `identitySecret` from your Meridesk
200
+ * API key, and passes the resulting hash to the widget alongside that
201
+ * identifier. Meridesk recomputes the hash server-side to confirm the
202
+ * request really came from your backend.
203
+ */
204
+ declare class IdentityResource {
205
+ private readonly identitySecret?;
206
+ constructor(identitySecret?: string | undefined);
207
+ /**
208
+ * Computes the identity hash for a given user identifier (typically the
209
+ * customer's email address).
210
+ *
211
+ * @throws {MerideskConfigError} if no `identitySecret` was provided when
212
+ * constructing the `Meridesk` client, or if `userId` is empty.
213
+ */
214
+ generateUserHash(userId: string): string;
215
+ }
216
+
217
+ declare class TicketsResource {
218
+ private readonly http;
219
+ constructor(http: HttpClient);
220
+ /**
221
+ * Creates a support ticket on behalf of a customer, identified by email.
222
+ * The customer is created automatically if they don't already exist.
223
+ */
224
+ create(input: CreateTicketInput): Promise<Ticket>;
225
+ /** Lists tickets for this website, optionally filtered by customer email and/or status. */
226
+ list(params?: ListTicketsParams): Promise<Ticket[]>;
227
+ /** Fetches a single ticket by id. */
228
+ get(ticketId: string): Promise<Ticket>;
229
+ /** Adds a reply to a ticket (defaults to a 'support' reply from your backend). */
230
+ reply(ticketId: string, input: ReplyToTicketInput): Promise<Ticket>;
231
+ }
232
+
233
+ declare const DEFAULT_BASE_URL = "https://api.north-america.meridesk.live/sdk/v1";
234
+ /**
235
+ * Official Meridesk Node.js SDK client for backend integrations.
236
+ *
237
+ * @example
238
+ * ```ts
239
+ * import { Meridesk } from '@meridesk/node-sdk';
240
+ *
241
+ * const meridesk = new Meridesk({
242
+ * apiKey: process.env.MERIDESK_API_KEY!,
243
+ * identitySecret: process.env.MERIDESK_IDENTITY_SECRET, // optional, for secure widget mode
244
+ * });
245
+ *
246
+ * const ticket = await meridesk.tickets.create({
247
+ * email: 'jane@example.com',
248
+ * name: 'Jane Doe',
249
+ * title: 'Refund request',
250
+ * message: 'I would like a refund for order #1234.',
251
+ * });
252
+ * ```
253
+ */
254
+ declare class Meridesk {
255
+ /** Generate secure widget identity verification hashes, computed locally. */
256
+ readonly identity: IdentityResource;
257
+ /** Create, fetch, and update customers. */
258
+ readonly customers: CustomersResource;
259
+ /** Create, list, fetch, and reply to support tickets. */
260
+ readonly tickets: TicketsResource;
261
+ /** List and search knowledge base articles. */
262
+ readonly articles: ArticlesResource;
263
+ private readonly http;
264
+ constructor(config: MerideskConfig);
265
+ /** Verifies the configured API key is valid and returns basic website/account info. */
266
+ me(): Promise<MeResponse>;
267
+ }
268
+
269
+ /**
270
+ * Base class for all errors thrown by the Meridesk SDK.
271
+ */
272
+ declare class MerideskError extends Error {
273
+ constructor(message: string);
274
+ }
275
+ /**
276
+ * Thrown when the Meridesk client is misconfigured (missing/invalid
277
+ * credentials, missing required arguments, etc.) — always a local,
278
+ * pre-request error.
279
+ */
280
+ declare class MerideskConfigError extends MerideskError {
281
+ constructor(message: string);
282
+ }
283
+ /**
284
+ * Thrown when the Meridesk API responds with a non-2xx status code.
285
+ */
286
+ declare class MerideskAPIError extends MerideskError {
287
+ /** HTTP status code returned by the API. */
288
+ readonly status: number;
289
+ /** Parsed JSON response body, if any. */
290
+ readonly body: unknown;
291
+ constructor(message: string, status: number, body?: unknown);
292
+ }
293
+ /**
294
+ * Thrown when a request to the Meridesk API fails for network reasons
295
+ * (timeout, DNS failure, connection reset, etc.) rather than an API error
296
+ * response.
297
+ */
298
+ declare class MerideskConnectionError extends MerideskError {
299
+ readonly cause?: unknown;
300
+ constructor(message: string, cause?: unknown);
301
+ }
302
+
303
+ export { type Article, type ArticleCategory, type ArticleSearchResult, type ArticleTopic, type CreateTicketInput, type Customer, DEFAULT_BASE_URL, type ListTicketsParams, type MeResponse, Meridesk, MerideskAPIError, type MerideskApiKeyInfo, type MerideskConfig, MerideskConfigError, MerideskConnectionError, MerideskError, type MerideskWebsite, type ReplyToTicketInput, type Ticket, type TicketMessage, type TicketPriority, type TicketStatus, type UpdateCustomerInput, type UpsertCustomerInput, Meridesk as default };
@@ -0,0 +1,303 @@
1
+ interface HttpClientOptions {
2
+ apiKey: string;
3
+ baseUrl: string;
4
+ timeoutMs?: number;
5
+ }
6
+ interface RequestOptions {
7
+ query?: Record<string, string | number | boolean | undefined | null>;
8
+ body?: unknown;
9
+ }
10
+ /**
11
+ * Thin wrapper around the global `fetch` for talking to the Meridesk SDK API.
12
+ * Handles auth headers, JSON encoding/decoding, timeouts, and translating
13
+ * non-2xx responses into `MerideskAPIError`.
14
+ */
15
+ declare class HttpClient {
16
+ private readonly apiKey;
17
+ private readonly baseUrl;
18
+ private readonly timeoutMs;
19
+ constructor(options: HttpClientOptions);
20
+ private buildUrl;
21
+ private request;
22
+ get<T>(path: string, query?: RequestOptions['query']): Promise<T>;
23
+ post<T>(path: string, body?: unknown): Promise<T>;
24
+ patch<T>(path: string, body?: unknown): Promise<T>;
25
+ }
26
+
27
+ /**
28
+ * Configuration accepted by `new Meridesk(config)`.
29
+ */
30
+ interface MerideskConfig {
31
+ /**
32
+ * Your Meridesk API key (starts with `mdk_live_`). Create one from
33
+ * Settings > API Keys in your Meridesk dashboard.
34
+ */
35
+ apiKey: string;
36
+ /**
37
+ * Your Meridesk identity verification secret, returned once alongside
38
+ * your API key when it was created/regenerated. Required only to use
39
+ * `meridesk.identity.generateUserHash()` for secure widget mode.
40
+ */
41
+ identitySecret?: string;
42
+ /**
43
+ * Override the Meridesk API base URL. Defaults to the production SDK API.
44
+ * Mainly useful for testing against a local/staging backend.
45
+ */
46
+ baseUrl?: string;
47
+ /** Request timeout in milliseconds. Defaults to 15000. */
48
+ timeoutMs?: number;
49
+ }
50
+ interface MerideskWebsite {
51
+ id: string;
52
+ name: string;
53
+ subdomain: string;
54
+ accountId: string;
55
+ }
56
+ interface MerideskApiKeyInfo {
57
+ id: string;
58
+ name: string;
59
+ prefix: string;
60
+ last4: string;
61
+ }
62
+ interface MeResponse {
63
+ website: MerideskWebsite;
64
+ apiKey: MerideskApiKeyInfo;
65
+ }
66
+ interface Customer {
67
+ id?: string;
68
+ _id?: string;
69
+ name: string;
70
+ email: string;
71
+ phone?: string;
72
+ company?: string;
73
+ position?: string;
74
+ status?: 'active' | 'inactive' | 'lead' | 'prospect' | 'customer';
75
+ timezone?: string;
76
+ address?: string;
77
+ externalIds?: Record<string, string>;
78
+ createdAt?: string;
79
+ updatedAt?: string;
80
+ }
81
+ interface UpsertCustomerInput {
82
+ email: string;
83
+ name?: string;
84
+ phone?: string;
85
+ company?: string;
86
+ position?: string;
87
+ externalIds?: Record<string, string>;
88
+ }
89
+ interface UpdateCustomerInput {
90
+ name?: string;
91
+ phone?: string;
92
+ company?: string;
93
+ position?: string;
94
+ status?: Customer['status'];
95
+ externalIds?: Record<string, string>;
96
+ }
97
+ type TicketStatus = 'open' | 'pending' | 'closed' | 'resolved';
98
+ type TicketPriority = 'low' | 'medium' | 'high' | 'urgent';
99
+ interface TicketMessage {
100
+ id: string;
101
+ message: string;
102
+ user: string;
103
+ attachments?: string[];
104
+ createdOn: string;
105
+ sender: 'support' | 'customer' | 'system' | 'assistant' | 'user';
106
+ }
107
+ interface Ticket {
108
+ id: string;
109
+ _id?: string;
110
+ ticketNumber: string;
111
+ name: string;
112
+ email: string;
113
+ title: string;
114
+ message: string;
115
+ status: TicketStatus;
116
+ priority: TicketPriority;
117
+ assignee?: string | null;
118
+ createdOn: string;
119
+ updatedOn: string;
120
+ chat?: TicketMessage[];
121
+ }
122
+ interface CreateTicketInput {
123
+ /** Email of the customer this ticket belongs to. Created if it doesn't exist yet. */
124
+ email: string;
125
+ /** Display name for the customer, used if they need to be created. */
126
+ name?: string;
127
+ title: string;
128
+ message: string;
129
+ priority?: TicketPriority;
130
+ }
131
+ interface ListTicketsParams {
132
+ email?: string;
133
+ status?: TicketStatus;
134
+ }
135
+ interface ReplyToTicketInput {
136
+ message: string;
137
+ /** Defaults to 'support' (i.e. a reply sent from your backend). */
138
+ sender?: 'support' | 'customer';
139
+ }
140
+ interface ArticleTopic {
141
+ _id?: string;
142
+ title: string;
143
+ content: string;
144
+ coverImage?: string;
145
+ helpfulCount?: number;
146
+ notHelpfulCount?: number;
147
+ }
148
+ interface Article {
149
+ _id?: string;
150
+ title: string;
151
+ description?: string;
152
+ icon?: string;
153
+ iconBg?: string;
154
+ topics: ArticleTopic[];
155
+ }
156
+ interface ArticleCategory {
157
+ _id?: string;
158
+ name: string;
159
+ articles: Article[];
160
+ }
161
+ interface ArticleSearchResult {
162
+ _id: string;
163
+ article: Article;
164
+ category: {
165
+ id: string;
166
+ name: string;
167
+ };
168
+ }
169
+
170
+ declare class ArticlesResource {
171
+ private readonly http;
172
+ constructor(http: HttpClient);
173
+ /** Lists all knowledge base categories (with their nested articles/topics) for this website. */
174
+ listCategories(): Promise<ArticleCategory[]>;
175
+ /** Full-text searches article titles/topics for this website. */
176
+ search(query: string): Promise<ArticleSearchResult[]>;
177
+ }
178
+
179
+ declare class CustomersResource {
180
+ private readonly http;
181
+ constructor(http: HttpClient);
182
+ /**
183
+ * Creates a customer if one doesn't exist for this email yet, or updates
184
+ * the provided fields on the existing one.
185
+ */
186
+ upsert(input: UpsertCustomerInput): Promise<Customer>;
187
+ /** Fetches a customer by email. */
188
+ get(email: string): Promise<Customer>;
189
+ /** Updates one or more fields on an existing customer. */
190
+ update(email: string, input: UpdateCustomerInput): Promise<Customer>;
191
+ }
192
+
193
+ /**
194
+ * Generates HMAC-SHA256 identity verification hashes for the Meridesk
195
+ * widget's "secure mode", entirely locally — no network call is made.
196
+ *
197
+ * This mirrors the identity verification pattern used by Intercom/Zendesk:
198
+ * your backend signs a stable identifier for the logged-in user (their
199
+ * email or internal user id) with the `identitySecret` from your Meridesk
200
+ * API key, and passes the resulting hash to the widget alongside that
201
+ * identifier. Meridesk recomputes the hash server-side to confirm the
202
+ * request really came from your backend.
203
+ */
204
+ declare class IdentityResource {
205
+ private readonly identitySecret?;
206
+ constructor(identitySecret?: string | undefined);
207
+ /**
208
+ * Computes the identity hash for a given user identifier (typically the
209
+ * customer's email address).
210
+ *
211
+ * @throws {MerideskConfigError} if no `identitySecret` was provided when
212
+ * constructing the `Meridesk` client, or if `userId` is empty.
213
+ */
214
+ generateUserHash(userId: string): string;
215
+ }
216
+
217
+ declare class TicketsResource {
218
+ private readonly http;
219
+ constructor(http: HttpClient);
220
+ /**
221
+ * Creates a support ticket on behalf of a customer, identified by email.
222
+ * The customer is created automatically if they don't already exist.
223
+ */
224
+ create(input: CreateTicketInput): Promise<Ticket>;
225
+ /** Lists tickets for this website, optionally filtered by customer email and/or status. */
226
+ list(params?: ListTicketsParams): Promise<Ticket[]>;
227
+ /** Fetches a single ticket by id. */
228
+ get(ticketId: string): Promise<Ticket>;
229
+ /** Adds a reply to a ticket (defaults to a 'support' reply from your backend). */
230
+ reply(ticketId: string, input: ReplyToTicketInput): Promise<Ticket>;
231
+ }
232
+
233
+ declare const DEFAULT_BASE_URL = "https://api.north-america.meridesk.live/sdk/v1";
234
+ /**
235
+ * Official Meridesk Node.js SDK client for backend integrations.
236
+ *
237
+ * @example
238
+ * ```ts
239
+ * import { Meridesk } from '@meridesk/node-sdk';
240
+ *
241
+ * const meridesk = new Meridesk({
242
+ * apiKey: process.env.MERIDESK_API_KEY!,
243
+ * identitySecret: process.env.MERIDESK_IDENTITY_SECRET, // optional, for secure widget mode
244
+ * });
245
+ *
246
+ * const ticket = await meridesk.tickets.create({
247
+ * email: 'jane@example.com',
248
+ * name: 'Jane Doe',
249
+ * title: 'Refund request',
250
+ * message: 'I would like a refund for order #1234.',
251
+ * });
252
+ * ```
253
+ */
254
+ declare class Meridesk {
255
+ /** Generate secure widget identity verification hashes, computed locally. */
256
+ readonly identity: IdentityResource;
257
+ /** Create, fetch, and update customers. */
258
+ readonly customers: CustomersResource;
259
+ /** Create, list, fetch, and reply to support tickets. */
260
+ readonly tickets: TicketsResource;
261
+ /** List and search knowledge base articles. */
262
+ readonly articles: ArticlesResource;
263
+ private readonly http;
264
+ constructor(config: MerideskConfig);
265
+ /** Verifies the configured API key is valid and returns basic website/account info. */
266
+ me(): Promise<MeResponse>;
267
+ }
268
+
269
+ /**
270
+ * Base class for all errors thrown by the Meridesk SDK.
271
+ */
272
+ declare class MerideskError extends Error {
273
+ constructor(message: string);
274
+ }
275
+ /**
276
+ * Thrown when the Meridesk client is misconfigured (missing/invalid
277
+ * credentials, missing required arguments, etc.) — always a local,
278
+ * pre-request error.
279
+ */
280
+ declare class MerideskConfigError extends MerideskError {
281
+ constructor(message: string);
282
+ }
283
+ /**
284
+ * Thrown when the Meridesk API responds with a non-2xx status code.
285
+ */
286
+ declare class MerideskAPIError extends MerideskError {
287
+ /** HTTP status code returned by the API. */
288
+ readonly status: number;
289
+ /** Parsed JSON response body, if any. */
290
+ readonly body: unknown;
291
+ constructor(message: string, status: number, body?: unknown);
292
+ }
293
+ /**
294
+ * Thrown when a request to the Meridesk API fails for network reasons
295
+ * (timeout, DNS failure, connection reset, etc.) rather than an API error
296
+ * response.
297
+ */
298
+ declare class MerideskConnectionError extends MerideskError {
299
+ readonly cause?: unknown;
300
+ constructor(message: string, cause?: unknown);
301
+ }
302
+
303
+ export { type Article, type ArticleCategory, type ArticleSearchResult, type ArticleTopic, type CreateTicketInput, type Customer, DEFAULT_BASE_URL, type ListTicketsParams, type MeResponse, Meridesk, MerideskAPIError, type MerideskApiKeyInfo, type MerideskConfig, MerideskConfigError, MerideskConnectionError, MerideskError, type MerideskWebsite, type ReplyToTicketInput, type Ticket, type TicketMessage, type TicketPriority, type TicketStatus, type UpdateCustomerInput, type UpsertCustomerInput, Meridesk as default };