@scell/sdk 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/dist/index.mjs ADDED
@@ -0,0 +1,1748 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropNames = Object.getOwnPropertyNames;
3
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
4
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
5
+ }) : x)(function(x) {
6
+ if (typeof require !== "undefined") return require.apply(this, arguments);
7
+ throw Error('Dynamic require of "' + x + '" is not supported');
8
+ });
9
+ var __esm = (fn, res) => function __init() {
10
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
11
+ };
12
+ var __export = (target, all) => {
13
+ for (var name in all)
14
+ __defProp(target, name, { get: all[name], enumerable: true });
15
+ };
16
+
17
+ // src/errors.ts
18
+ var errors_exports = {};
19
+ __export(errors_exports, {
20
+ ScellAuthenticationError: () => ScellAuthenticationError,
21
+ ScellAuthorizationError: () => ScellAuthorizationError,
22
+ ScellError: () => ScellError,
23
+ ScellInsufficientBalanceError: () => ScellInsufficientBalanceError,
24
+ ScellNetworkError: () => ScellNetworkError,
25
+ ScellNotFoundError: () => ScellNotFoundError,
26
+ ScellRateLimitError: () => ScellRateLimitError,
27
+ ScellServerError: () => ScellServerError,
28
+ ScellTimeoutError: () => ScellTimeoutError,
29
+ ScellValidationError: () => ScellValidationError,
30
+ parseApiError: () => parseApiError
31
+ });
32
+ function parseApiError(status, body, headers) {
33
+ const errorBody = body;
34
+ const message = errorBody?.message ?? "Unknown error";
35
+ const errors = errorBody?.errors ?? {};
36
+ const code = errorBody?.code;
37
+ switch (status) {
38
+ case 401:
39
+ throw new ScellAuthenticationError(message, body);
40
+ case 402:
41
+ throw new ScellInsufficientBalanceError(message, body);
42
+ case 403:
43
+ throw new ScellAuthorizationError(message, body);
44
+ case 404:
45
+ throw new ScellNotFoundError(message, body);
46
+ case 422:
47
+ throw new ScellValidationError(message, errors, body);
48
+ case 429: {
49
+ const retryAfter = headers?.get("Retry-After");
50
+ throw new ScellRateLimitError(
51
+ message,
52
+ retryAfter ? parseInt(retryAfter, 10) : void 0,
53
+ body
54
+ );
55
+ }
56
+ default:
57
+ if (status >= 500) {
58
+ throw new ScellServerError(message, status, body);
59
+ }
60
+ throw new ScellError(message, status, code, body);
61
+ }
62
+ }
63
+ var ScellError, ScellAuthenticationError, ScellAuthorizationError, ScellValidationError, ScellRateLimitError, ScellNotFoundError, ScellServerError, ScellInsufficientBalanceError, ScellNetworkError, ScellTimeoutError;
64
+ var init_errors = __esm({
65
+ "src/errors.ts"() {
66
+ ScellError = class extends Error {
67
+ /** HTTP status code */
68
+ status;
69
+ /** Error code from API */
70
+ code;
71
+ /** Original response body */
72
+ body;
73
+ constructor(message, status, code, body) {
74
+ super(message);
75
+ this.name = "ScellError";
76
+ this.status = status;
77
+ this.code = code;
78
+ this.body = body;
79
+ if (Error.captureStackTrace) {
80
+ Error.captureStackTrace(this, this.constructor);
81
+ }
82
+ }
83
+ };
84
+ ScellAuthenticationError = class extends ScellError {
85
+ constructor(message = "Authentication failed", body) {
86
+ super(message, 401, "AUTHENTICATION_ERROR", body);
87
+ this.name = "ScellAuthenticationError";
88
+ }
89
+ };
90
+ ScellAuthorizationError = class extends ScellError {
91
+ constructor(message = "Access denied", body) {
92
+ super(message, 403, "AUTHORIZATION_ERROR", body);
93
+ this.name = "ScellAuthorizationError";
94
+ }
95
+ };
96
+ ScellValidationError = class extends ScellError {
97
+ /** Field-level validation errors */
98
+ errors;
99
+ constructor(message, errors = {}, body) {
100
+ super(message, 422, "VALIDATION_ERROR", body);
101
+ this.name = "ScellValidationError";
102
+ this.errors = errors;
103
+ }
104
+ /**
105
+ * Get all error messages as a flat array
106
+ */
107
+ getAllMessages() {
108
+ return Object.values(this.errors).flat();
109
+ }
110
+ /**
111
+ * Get error messages for a specific field
112
+ */
113
+ getFieldErrors(field) {
114
+ return this.errors[field] ?? [];
115
+ }
116
+ /**
117
+ * Check if a specific field has errors
118
+ */
119
+ hasFieldError(field) {
120
+ const fieldErrors = this.errors[field];
121
+ return fieldErrors !== void 0 && fieldErrors.length > 0;
122
+ }
123
+ };
124
+ ScellRateLimitError = class extends ScellError {
125
+ /** Seconds to wait before retrying */
126
+ retryAfter;
127
+ constructor(message = "Rate limit exceeded", retryAfter, body) {
128
+ super(message, 429, "RATE_LIMIT_EXCEEDED", body);
129
+ this.name = "ScellRateLimitError";
130
+ this.retryAfter = retryAfter;
131
+ }
132
+ };
133
+ ScellNotFoundError = class extends ScellError {
134
+ constructor(message = "Resource not found", body) {
135
+ super(message, 404, "NOT_FOUND", body);
136
+ this.name = "ScellNotFoundError";
137
+ }
138
+ };
139
+ ScellServerError = class extends ScellError {
140
+ constructor(message = "Internal server error", status = 500, body) {
141
+ super(message, status, "SERVER_ERROR", body);
142
+ this.name = "ScellServerError";
143
+ }
144
+ };
145
+ ScellInsufficientBalanceError = class extends ScellError {
146
+ constructor(message = "Insufficient balance", body) {
147
+ super(message, 402, "INSUFFICIENT_BALANCE", body);
148
+ this.name = "ScellInsufficientBalanceError";
149
+ }
150
+ };
151
+ ScellNetworkError = class extends ScellError {
152
+ originalError;
153
+ constructor(message, originalError) {
154
+ super(message, 0, "NETWORK_ERROR");
155
+ this.name = "ScellNetworkError";
156
+ this.originalError = originalError;
157
+ }
158
+ };
159
+ ScellTimeoutError = class extends ScellError {
160
+ constructor(message = "Request timed out") {
161
+ super(message, 0, "TIMEOUT");
162
+ this.name = "ScellTimeoutError";
163
+ }
164
+ };
165
+ }
166
+ });
167
+
168
+ // src/client.ts
169
+ init_errors();
170
+
171
+ // src/utils/retry.ts
172
+ init_errors();
173
+ var DEFAULT_RETRY_OPTIONS = {
174
+ maxRetries: 3,
175
+ baseDelay: 1e3,
176
+ maxDelay: 3e4,
177
+ jitterFactor: 0.1
178
+ };
179
+ function isRetryableError(error) {
180
+ if (error instanceof ScellRateLimitError) {
181
+ return true;
182
+ }
183
+ if (error instanceof ScellServerError) {
184
+ return true;
185
+ }
186
+ if (error instanceof Error && error.name === "ScellNetworkError") {
187
+ return true;
188
+ }
189
+ return false;
190
+ }
191
+ function calculateDelay(attempt, baseDelay, maxDelay, jitterFactor, retryAfter) {
192
+ if (retryAfter !== void 0 && retryAfter > 0) {
193
+ return retryAfter * 1e3;
194
+ }
195
+ const exponentialDelay = baseDelay * Math.pow(2, attempt);
196
+ const cappedDelay = Math.min(exponentialDelay, maxDelay);
197
+ const jitter = cappedDelay * jitterFactor * (Math.random() * 2 - 1);
198
+ return Math.floor(cappedDelay + jitter);
199
+ }
200
+ function sleep(ms) {
201
+ return new Promise((resolve) => setTimeout(resolve, ms));
202
+ }
203
+ async function withRetry(fn, options = {}) {
204
+ const maxRetries = options.maxRetries ?? DEFAULT_RETRY_OPTIONS.maxRetries;
205
+ const baseDelay = options.baseDelay ?? DEFAULT_RETRY_OPTIONS.baseDelay;
206
+ const maxDelay = options.maxDelay ?? DEFAULT_RETRY_OPTIONS.maxDelay;
207
+ const jitterFactor = options.jitterFactor ?? DEFAULT_RETRY_OPTIONS.jitterFactor;
208
+ const isRetryable = options.isRetryable ?? isRetryableError;
209
+ let lastError;
210
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
211
+ try {
212
+ return await fn();
213
+ } catch (error) {
214
+ lastError = error;
215
+ if (attempt >= maxRetries || !isRetryable(error)) {
216
+ throw error;
217
+ }
218
+ const retryAfter = error instanceof ScellRateLimitError ? error.retryAfter : void 0;
219
+ const delay = calculateDelay(
220
+ attempt,
221
+ baseDelay,
222
+ maxDelay,
223
+ jitterFactor,
224
+ retryAfter
225
+ );
226
+ await sleep(delay);
227
+ }
228
+ }
229
+ throw lastError;
230
+ }
231
+ function createRetryWrapper(defaultOptions = {}) {
232
+ return (fn, options = {}) => withRetry(fn, { ...defaultOptions, ...options });
233
+ }
234
+
235
+ // src/client.ts
236
+ var HttpClient = class {
237
+ baseUrl;
238
+ timeout;
239
+ retryOptions;
240
+ enableRetry;
241
+ fetchFn;
242
+ authMode;
243
+ authToken;
244
+ constructor(authMode, authToken, config = {}) {
245
+ this.authMode = authMode;
246
+ this.authToken = authToken;
247
+ this.baseUrl = config.baseUrl ?? "https://api.scell.io/api/v1";
248
+ this.timeout = config.timeout ?? 3e4;
249
+ this.retryOptions = config.retry ?? {};
250
+ this.enableRetry = config.enableRetry ?? true;
251
+ this.fetchFn = config.fetch ?? fetch;
252
+ }
253
+ /**
254
+ * Build URL with query parameters
255
+ */
256
+ buildUrl(path, query) {
257
+ const url = new URL(path, this.baseUrl);
258
+ if (query) {
259
+ for (const [key, value] of Object.entries(query)) {
260
+ if (value !== void 0) {
261
+ url.searchParams.set(key, String(value));
262
+ }
263
+ }
264
+ }
265
+ return url.toString();
266
+ }
267
+ /**
268
+ * Build headers for request
269
+ */
270
+ buildHeaders(additionalHeaders) {
271
+ const headers = {
272
+ "Content-Type": "application/json",
273
+ Accept: "application/json",
274
+ ...additionalHeaders
275
+ };
276
+ if (this.authMode === "bearer") {
277
+ headers["Authorization"] = `Bearer ${this.authToken}`;
278
+ } else {
279
+ headers["X-API-Key"] = this.authToken;
280
+ }
281
+ return headers;
282
+ }
283
+ /**
284
+ * Execute HTTP request
285
+ */
286
+ async executeRequest(config) {
287
+ const { method, path, body, query, headers, timeout, signal } = config;
288
+ const url = this.buildUrl(path, query);
289
+ const requestHeaders = this.buildHeaders(headers);
290
+ const requestTimeout = timeout ?? this.timeout;
291
+ const controller = new AbortController();
292
+ const timeoutId = setTimeout(() => controller.abort(), requestTimeout);
293
+ const combinedSignal = signal ? new AbortController().signal : controller.signal;
294
+ if (signal) {
295
+ signal.addEventListener("abort", () => controller.abort());
296
+ }
297
+ try {
298
+ const fetchOptions = {
299
+ method,
300
+ headers: requestHeaders,
301
+ signal: combinedSignal
302
+ };
303
+ if (body !== void 0) {
304
+ fetchOptions.body = JSON.stringify(body);
305
+ }
306
+ const response = await this.fetchFn(url, fetchOptions);
307
+ clearTimeout(timeoutId);
308
+ const contentType = response.headers.get("Content-Type") ?? "";
309
+ let responseBody;
310
+ if (contentType.includes("application/json")) {
311
+ responseBody = await response.json();
312
+ } else {
313
+ responseBody = await response.text();
314
+ }
315
+ if (!response.ok) {
316
+ parseApiError(response.status, responseBody, response.headers);
317
+ }
318
+ return responseBody;
319
+ } catch (error) {
320
+ clearTimeout(timeoutId);
321
+ if (error instanceof Error) {
322
+ if (error.name === "AbortError") {
323
+ throw new ScellTimeoutError(
324
+ `Request timed out after ${requestTimeout}ms`
325
+ );
326
+ }
327
+ if (error.name === "TypeError" && error.message.includes("fetch")) {
328
+ throw new ScellNetworkError("Network request failed", error);
329
+ }
330
+ }
331
+ throw error;
332
+ }
333
+ }
334
+ /**
335
+ * Execute request with optional retry
336
+ */
337
+ async request(config) {
338
+ const shouldRetry = this.enableRetry && !config.skipRetry;
339
+ if (shouldRetry) {
340
+ return withRetry(
341
+ () => this.executeRequest(config),
342
+ this.retryOptions
343
+ );
344
+ }
345
+ return this.executeRequest(config);
346
+ }
347
+ /**
348
+ * GET request
349
+ */
350
+ async get(path, query, options) {
351
+ const config = {
352
+ method: "GET",
353
+ path,
354
+ ...options
355
+ };
356
+ if (query !== void 0) {
357
+ config.query = query;
358
+ }
359
+ return this.request(config);
360
+ }
361
+ /**
362
+ * POST request
363
+ */
364
+ async post(path, body, options) {
365
+ return this.request({
366
+ method: "POST",
367
+ path,
368
+ body,
369
+ ...options
370
+ });
371
+ }
372
+ /**
373
+ * PUT request
374
+ */
375
+ async put(path, body, options) {
376
+ return this.request({
377
+ method: "PUT",
378
+ path,
379
+ body,
380
+ ...options
381
+ });
382
+ }
383
+ /**
384
+ * PATCH request
385
+ */
386
+ async patch(path, body, options) {
387
+ return this.request({
388
+ method: "PATCH",
389
+ path,
390
+ body,
391
+ ...options
392
+ });
393
+ }
394
+ /**
395
+ * DELETE request
396
+ */
397
+ async delete(path, options) {
398
+ return this.request({
399
+ method: "DELETE",
400
+ path,
401
+ ...options
402
+ });
403
+ }
404
+ };
405
+
406
+ // src/resources/api-keys.ts
407
+ var ApiKeysResource = class {
408
+ constructor(http) {
409
+ this.http = http;
410
+ }
411
+ /**
412
+ * List all API keys
413
+ *
414
+ * @param requestOptions - Request options
415
+ * @returns List of API keys (without secrets)
416
+ *
417
+ * @example
418
+ * ```typescript
419
+ * const { data: keys } = await client.apiKeys.list();
420
+ * keys.forEach(key => {
421
+ * console.log(`${key.name}: ${key.key_prefix}...`);
422
+ * });
423
+ * ```
424
+ */
425
+ async list(requestOptions) {
426
+ return this.http.get(
427
+ "/api-keys",
428
+ void 0,
429
+ requestOptions
430
+ );
431
+ }
432
+ /**
433
+ * Get a specific API key
434
+ *
435
+ * @param id - API Key UUID
436
+ * @param requestOptions - Request options
437
+ * @returns API key details (without secret)
438
+ *
439
+ * @example
440
+ * ```typescript
441
+ * const { data: key } = await client.apiKeys.get('key-uuid');
442
+ * console.log(`Last used: ${key.last_used_at}`);
443
+ * ```
444
+ */
445
+ async get(id, requestOptions) {
446
+ return this.http.get(
447
+ `/api-keys/${id}`,
448
+ void 0,
449
+ requestOptions
450
+ );
451
+ }
452
+ /**
453
+ * Create a new API key
454
+ *
455
+ * Important: The full key is only returned once during creation.
456
+ * Store it securely - you won't be able to retrieve it again.
457
+ *
458
+ * @param input - API key configuration
459
+ * @param requestOptions - Request options
460
+ * @returns Created API key with full key value
461
+ *
462
+ * @example
463
+ * ```typescript
464
+ * const { data: apiKey } = await client.apiKeys.create({
465
+ * name: 'Production Integration',
466
+ * company_id: 'company-uuid',
467
+ * environment: 'production',
468
+ * permissions: ['invoices:write', 'signatures:write']
469
+ * });
470
+ *
471
+ * // IMPORTANT: Store this key securely!
472
+ * // You won't be able to see it again.
473
+ * console.log('Save this key:', apiKey.key);
474
+ * ```
475
+ */
476
+ async create(input, requestOptions) {
477
+ return this.http.post(
478
+ "/api-keys",
479
+ input,
480
+ requestOptions
481
+ );
482
+ }
483
+ /**
484
+ * Delete an API key
485
+ *
486
+ * Warning: This will immediately revoke the key and all
487
+ * requests using it will fail.
488
+ *
489
+ * @param id - API Key UUID
490
+ * @param requestOptions - Request options
491
+ * @returns Deletion confirmation
492
+ *
493
+ * @example
494
+ * ```typescript
495
+ * await client.apiKeys.delete('key-uuid');
496
+ * console.log('API key revoked');
497
+ * ```
498
+ */
499
+ async delete(id, requestOptions) {
500
+ return this.http.delete(`/api-keys/${id}`, requestOptions);
501
+ }
502
+ };
503
+
504
+ // src/resources/auth.ts
505
+ var AuthResource = class {
506
+ constructor(http) {
507
+ this.http = http;
508
+ }
509
+ /**
510
+ * Get current authenticated user
511
+ *
512
+ * @param requestOptions - Request options
513
+ * @returns Current user details
514
+ *
515
+ * @example
516
+ * ```typescript
517
+ * const { data: user } = await client.auth.me();
518
+ * console.log(`Logged in as: ${user.name} (${user.email})`);
519
+ * ```
520
+ */
521
+ async me(requestOptions) {
522
+ return this.http.get(
523
+ "/auth/me",
524
+ void 0,
525
+ requestOptions
526
+ );
527
+ }
528
+ /**
529
+ * Logout (revoke current token)
530
+ *
531
+ * @param requestOptions - Request options
532
+ * @returns Logout confirmation
533
+ *
534
+ * @example
535
+ * ```typescript
536
+ * await client.auth.logout();
537
+ * // Token is now invalid
538
+ * ```
539
+ */
540
+ async logout(requestOptions) {
541
+ return this.http.post(
542
+ "/auth/logout",
543
+ void 0,
544
+ requestOptions
545
+ );
546
+ }
547
+ };
548
+ var ScellAuth = {
549
+ /**
550
+ * Default base URL for auth requests
551
+ */
552
+ baseUrl: "https://api.scell.io/api/v1",
553
+ /**
554
+ * Register a new user
555
+ *
556
+ * @param input - Registration data
557
+ * @param baseUrl - Optional base URL override
558
+ * @returns Auth response with token
559
+ *
560
+ * @example
561
+ * ```typescript
562
+ * const auth = await ScellAuth.register({
563
+ * name: 'Jane Doe',
564
+ * email: 'jane@example.com',
565
+ * password: 'MySecurePassword123!',
566
+ * password_confirmation: 'MySecurePassword123!'
567
+ * });
568
+ *
569
+ * console.log('Welcome,', auth.user.name);
570
+ * const client = new ScellClient(auth.token);
571
+ * ```
572
+ */
573
+ async register(input, baseUrl) {
574
+ const url = `${baseUrl ?? this.baseUrl}/auth/register`;
575
+ const response = await fetch(url, {
576
+ method: "POST",
577
+ headers: {
578
+ "Content-Type": "application/json",
579
+ Accept: "application/json"
580
+ },
581
+ body: JSON.stringify(input)
582
+ });
583
+ const body = await response.json();
584
+ if (!response.ok) {
585
+ const { parseApiError: parseApiError2 } = await Promise.resolve().then(() => (init_errors(), errors_exports));
586
+ parseApiError2(response.status, body, response.headers);
587
+ }
588
+ return body;
589
+ },
590
+ /**
591
+ * Login an existing user
592
+ *
593
+ * @param credentials - Login credentials
594
+ * @param baseUrl - Optional base URL override
595
+ * @returns Auth response with token
596
+ *
597
+ * @example
598
+ * ```typescript
599
+ * const auth = await ScellAuth.login({
600
+ * email: 'user@example.com',
601
+ * password: 'password'
602
+ * });
603
+ *
604
+ * // Store the token securely
605
+ * localStorage.setItem('scell_token', auth.token);
606
+ *
607
+ * // Create client
608
+ * const client = new ScellClient(auth.token);
609
+ * ```
610
+ */
611
+ async login(credentials, baseUrl) {
612
+ const url = `${baseUrl ?? this.baseUrl}/auth/login`;
613
+ const response = await fetch(url, {
614
+ method: "POST",
615
+ headers: {
616
+ "Content-Type": "application/json",
617
+ Accept: "application/json"
618
+ },
619
+ body: JSON.stringify(credentials)
620
+ });
621
+ const body = await response.json();
622
+ if (!response.ok) {
623
+ const { parseApiError: parseApiError2 } = await Promise.resolve().then(() => (init_errors(), errors_exports));
624
+ parseApiError2(response.status, body, response.headers);
625
+ }
626
+ return body;
627
+ },
628
+ /**
629
+ * Request password reset email
630
+ *
631
+ * @param input - Email address
632
+ * @param baseUrl - Optional base URL override
633
+ * @returns Confirmation message
634
+ *
635
+ * @example
636
+ * ```typescript
637
+ * await ScellAuth.forgotPassword({
638
+ * email: 'user@example.com'
639
+ * });
640
+ * console.log('Check your email for reset link');
641
+ * ```
642
+ */
643
+ async forgotPassword(input, baseUrl) {
644
+ const url = `${baseUrl ?? this.baseUrl}/auth/forgot-password`;
645
+ const response = await fetch(url, {
646
+ method: "POST",
647
+ headers: {
648
+ "Content-Type": "application/json",
649
+ Accept: "application/json"
650
+ },
651
+ body: JSON.stringify(input)
652
+ });
653
+ const body = await response.json();
654
+ if (!response.ok) {
655
+ const { parseApiError: parseApiError2 } = await Promise.resolve().then(() => (init_errors(), errors_exports));
656
+ parseApiError2(response.status, body, response.headers);
657
+ }
658
+ return body;
659
+ },
660
+ /**
661
+ * Reset password with token from email
662
+ *
663
+ * @param input - Reset password data
664
+ * @param baseUrl - Optional base URL override
665
+ * @returns Confirmation message
666
+ *
667
+ * @example
668
+ * ```typescript
669
+ * await ScellAuth.resetPassword({
670
+ * email: 'user@example.com',
671
+ * token: 'reset-token-from-email',
672
+ * password: 'NewSecurePassword123!',
673
+ * password_confirmation: 'NewSecurePassword123!'
674
+ * });
675
+ * ```
676
+ */
677
+ async resetPassword(input, baseUrl) {
678
+ const url = `${baseUrl ?? this.baseUrl}/auth/reset-password`;
679
+ const response = await fetch(url, {
680
+ method: "POST",
681
+ headers: {
682
+ "Content-Type": "application/json",
683
+ Accept: "application/json"
684
+ },
685
+ body: JSON.stringify(input)
686
+ });
687
+ const body = await response.json();
688
+ if (!response.ok) {
689
+ const { parseApiError: parseApiError2 } = await Promise.resolve().then(() => (init_errors(), errors_exports));
690
+ parseApiError2(response.status, body, response.headers);
691
+ }
692
+ return body;
693
+ }
694
+ };
695
+
696
+ // src/resources/balance.ts
697
+ var BalanceResource = class {
698
+ constructor(http) {
699
+ this.http = http;
700
+ }
701
+ /**
702
+ * Get current balance and settings
703
+ *
704
+ * @param requestOptions - Request options
705
+ * @returns Current balance details
706
+ *
707
+ * @example
708
+ * ```typescript
709
+ * const { data: balance } = await client.balance.get();
710
+ * console.log(`Balance: ${balance.amount} ${balance.currency}`);
711
+ *
712
+ * if (balance.amount < balance.low_balance_alert_threshold) {
713
+ * console.log('Warning: Low balance!');
714
+ * }
715
+ * ```
716
+ */
717
+ async get(requestOptions) {
718
+ return this.http.get(
719
+ "/balance",
720
+ void 0,
721
+ requestOptions
722
+ );
723
+ }
724
+ /**
725
+ * Reload balance
726
+ *
727
+ * Note: This is a simulation endpoint. In production, use Stripe integration.
728
+ *
729
+ * @param input - Reload amount (10-10000 EUR)
730
+ * @param requestOptions - Request options
731
+ * @returns Reload transaction details
732
+ *
733
+ * @example
734
+ * ```typescript
735
+ * const { transaction } = await client.balance.reload({ amount: 100 });
736
+ * console.log(`New balance: ${transaction.balance_after}`);
737
+ * ```
738
+ */
739
+ async reload(input, requestOptions) {
740
+ return this.http.post(
741
+ "/balance/reload",
742
+ input,
743
+ requestOptions
744
+ );
745
+ }
746
+ /**
747
+ * Update balance settings
748
+ *
749
+ * Configure auto-reload and alert thresholds.
750
+ *
751
+ * @param input - Settings to update
752
+ * @param requestOptions - Request options
753
+ * @returns Updated settings
754
+ *
755
+ * @example
756
+ * ```typescript
757
+ * await client.balance.updateSettings({
758
+ * auto_reload_enabled: true,
759
+ * auto_reload_threshold: 50,
760
+ * auto_reload_amount: 200,
761
+ * low_balance_alert_threshold: 100,
762
+ * critical_balance_alert_threshold: 25
763
+ * });
764
+ * ```
765
+ */
766
+ async updateSettings(input, requestOptions) {
767
+ return this.http.put(
768
+ "/balance/settings",
769
+ input,
770
+ requestOptions
771
+ );
772
+ }
773
+ /**
774
+ * List balance transactions
775
+ *
776
+ * @param options - Filter and pagination options
777
+ * @param requestOptions - Request options
778
+ * @returns Paginated list of transactions
779
+ *
780
+ * @example
781
+ * ```typescript
782
+ * // List all invoice debits
783
+ * const { data, meta } = await client.balance.transactions({
784
+ * type: 'debit',
785
+ * service: 'invoice',
786
+ * from: '2024-01-01',
787
+ * to: '2024-01-31'
788
+ * });
789
+ *
790
+ * data.forEach(tx => {
791
+ * console.log(`${tx.description}: -${tx.amount} EUR`);
792
+ * });
793
+ * ```
794
+ */
795
+ async transactions(options = {}, requestOptions) {
796
+ return this.http.get(
797
+ "/balance/transactions",
798
+ options,
799
+ requestOptions
800
+ );
801
+ }
802
+ };
803
+
804
+ // src/resources/companies.ts
805
+ var CompaniesResource = class {
806
+ constructor(http) {
807
+ this.http = http;
808
+ }
809
+ /**
810
+ * List all companies for the authenticated user
811
+ *
812
+ * @param requestOptions - Request options
813
+ * @returns List of companies
814
+ *
815
+ * @example
816
+ * ```typescript
817
+ * const { data: companies } = await client.companies.list();
818
+ * companies.forEach(c => console.log(c.name, c.status));
819
+ * ```
820
+ */
821
+ async list(requestOptions) {
822
+ return this.http.get(
823
+ "/companies",
824
+ void 0,
825
+ requestOptions
826
+ );
827
+ }
828
+ /**
829
+ * Get a specific company by ID
830
+ *
831
+ * @param id - Company UUID
832
+ * @param requestOptions - Request options
833
+ * @returns Company details
834
+ *
835
+ * @example
836
+ * ```typescript
837
+ * const { data: company } = await client.companies.get('uuid');
838
+ * console.log(company.name, company.siret);
839
+ * ```
840
+ */
841
+ async get(id, requestOptions) {
842
+ return this.http.get(
843
+ `/companies/${id}`,
844
+ void 0,
845
+ requestOptions
846
+ );
847
+ }
848
+ /**
849
+ * Create a new company
850
+ *
851
+ * @param input - Company creation data
852
+ * @param requestOptions - Request options
853
+ * @returns Created company
854
+ *
855
+ * @example
856
+ * ```typescript
857
+ * const { data: company } = await client.companies.create({
858
+ * name: 'Acme Corp',
859
+ * siret: '12345678901234',
860
+ * vat_number: 'FR12345678901',
861
+ * legal_form: 'SAS',
862
+ * address_line1: '123 Business Street',
863
+ * postal_code: '75001',
864
+ * city: 'Paris',
865
+ * country: 'FR',
866
+ * email: 'contact@acme.com',
867
+ * phone: '+33 1 23 45 67 89'
868
+ * });
869
+ * ```
870
+ */
871
+ async create(input, requestOptions) {
872
+ return this.http.post(
873
+ "/companies",
874
+ input,
875
+ requestOptions
876
+ );
877
+ }
878
+ /**
879
+ * Update a company
880
+ *
881
+ * @param id - Company UUID
882
+ * @param input - Fields to update
883
+ * @param requestOptions - Request options
884
+ * @returns Updated company
885
+ *
886
+ * @example
887
+ * ```typescript
888
+ * const { data: company } = await client.companies.update('uuid', {
889
+ * email: 'new-email@acme.com',
890
+ * phone: '+33 1 98 76 54 32'
891
+ * });
892
+ * ```
893
+ */
894
+ async update(id, input, requestOptions) {
895
+ return this.http.put(
896
+ `/companies/${id}`,
897
+ input,
898
+ requestOptions
899
+ );
900
+ }
901
+ /**
902
+ * Delete a company
903
+ *
904
+ * @param id - Company UUID
905
+ * @param requestOptions - Request options
906
+ * @returns Deletion confirmation
907
+ *
908
+ * @example
909
+ * ```typescript
910
+ * await client.companies.delete('company-uuid');
911
+ * ```
912
+ */
913
+ async delete(id, requestOptions) {
914
+ return this.http.delete(
915
+ `/companies/${id}`,
916
+ requestOptions
917
+ );
918
+ }
919
+ /**
920
+ * Initiate KYC verification for a company
921
+ *
922
+ * @param id - Company UUID
923
+ * @param requestOptions - Request options
924
+ * @returns KYC reference and redirect URL
925
+ *
926
+ * @example
927
+ * ```typescript
928
+ * const { kyc_reference, redirect_url } = await client.companies.initiateKyc(
929
+ * 'company-uuid'
930
+ * );
931
+ * // Redirect user to redirect_url for KYC verification
932
+ * ```
933
+ */
934
+ async initiateKyc(id, requestOptions) {
935
+ return this.http.post(
936
+ `/companies/${id}/kyc`,
937
+ void 0,
938
+ requestOptions
939
+ );
940
+ }
941
+ /**
942
+ * Get KYC verification status
943
+ *
944
+ * @param id - Company UUID
945
+ * @param requestOptions - Request options
946
+ * @returns Current KYC status
947
+ *
948
+ * @example
949
+ * ```typescript
950
+ * const status = await client.companies.kycStatus('company-uuid');
951
+ * if (status.status === 'active') {
952
+ * console.log('KYC completed at:', status.kyc_completed_at);
953
+ * }
954
+ * ```
955
+ */
956
+ async kycStatus(id, requestOptions) {
957
+ return this.http.get(
958
+ `/companies/${id}/kyc/status`,
959
+ void 0,
960
+ requestOptions
961
+ );
962
+ }
963
+ };
964
+
965
+ // src/resources/invoices.ts
966
+ var InvoicesResource = class {
967
+ constructor(http) {
968
+ this.http = http;
969
+ }
970
+ /**
971
+ * List invoices with optional filtering
972
+ *
973
+ * @param options - Filter and pagination options
974
+ * @param requestOptions - Request options
975
+ * @returns Paginated list of invoices
976
+ *
977
+ * @example
978
+ * ```typescript
979
+ * // List all outgoing invoices
980
+ * const { data, meta } = await client.invoices.list({
981
+ * direction: 'outgoing',
982
+ * per_page: 50
983
+ * });
984
+ * console.log(`Found ${meta.total} invoices`);
985
+ * ```
986
+ */
987
+ async list(options = {}, requestOptions) {
988
+ return this.http.get(
989
+ "/invoices",
990
+ options,
991
+ requestOptions
992
+ );
993
+ }
994
+ /**
995
+ * Get a specific invoice by ID
996
+ *
997
+ * @param id - Invoice UUID
998
+ * @param requestOptions - Request options
999
+ * @returns Invoice details
1000
+ *
1001
+ * @example
1002
+ * ```typescript
1003
+ * const { data: invoice } = await client.invoices.get('uuid-here');
1004
+ * console.log('Invoice number:', invoice.invoice_number);
1005
+ * ```
1006
+ */
1007
+ async get(id, requestOptions) {
1008
+ return this.http.get(
1009
+ `/invoices/${id}`,
1010
+ void 0,
1011
+ requestOptions
1012
+ );
1013
+ }
1014
+ /**
1015
+ * Create a new invoice
1016
+ *
1017
+ * Note: This endpoint requires API key authentication.
1018
+ * Creating an invoice in production mode will debit your balance.
1019
+ *
1020
+ * @param input - Invoice creation data
1021
+ * @param requestOptions - Request options
1022
+ * @returns Created invoice
1023
+ *
1024
+ * @example
1025
+ * ```typescript
1026
+ * const { data: invoice } = await client.invoices.create({
1027
+ * invoice_number: 'FACT-2024-001',
1028
+ * direction: 'outgoing',
1029
+ * output_format: 'facturx',
1030
+ * issue_date: '2024-01-15',
1031
+ * total_ht: 100.00,
1032
+ * total_tax: 20.00,
1033
+ * total_ttc: 120.00,
1034
+ * seller_siret: '12345678901234',
1035
+ * seller_name: 'My Company',
1036
+ * seller_address: {
1037
+ * line1: '1 Rue Example',
1038
+ * postal_code: '75001',
1039
+ * city: 'Paris',
1040
+ * country: 'FR'
1041
+ * },
1042
+ * buyer_siret: '98765432109876',
1043
+ * buyer_name: 'Client Company',
1044
+ * buyer_address: {
1045
+ * line1: '2 Avenue Test',
1046
+ * postal_code: '75002',
1047
+ * city: 'Paris',
1048
+ * country: 'FR'
1049
+ * },
1050
+ * lines: [{
1051
+ * description: 'Service prestation',
1052
+ * quantity: 1,
1053
+ * unit_price: 100.00,
1054
+ * tax_rate: 20.00,
1055
+ * total_ht: 100.00,
1056
+ * total_tax: 20.00,
1057
+ * total_ttc: 120.00
1058
+ * }]
1059
+ * });
1060
+ * ```
1061
+ */
1062
+ async create(input, requestOptions) {
1063
+ return this.http.post(
1064
+ "/invoices",
1065
+ input,
1066
+ requestOptions
1067
+ );
1068
+ }
1069
+ /**
1070
+ * Download invoice file
1071
+ *
1072
+ * @param id - Invoice UUID
1073
+ * @param type - File type to download
1074
+ * @param requestOptions - Request options
1075
+ * @returns Temporary download URL
1076
+ *
1077
+ * @example
1078
+ * ```typescript
1079
+ * // Download PDF version
1080
+ * const { url, expires_at } = await client.invoices.download(
1081
+ * 'invoice-uuid',
1082
+ * 'pdf'
1083
+ * );
1084
+ * console.log('Download before:', expires_at);
1085
+ * ```
1086
+ */
1087
+ async download(id, type, requestOptions) {
1088
+ return this.http.get(
1089
+ `/invoices/${id}/download/${type}`,
1090
+ void 0,
1091
+ requestOptions
1092
+ );
1093
+ }
1094
+ /**
1095
+ * Get invoice audit trail (Piste d'Audit Fiable)
1096
+ *
1097
+ * @param id - Invoice UUID
1098
+ * @param requestOptions - Request options
1099
+ * @returns Audit trail entries with integrity validation
1100
+ *
1101
+ * @example
1102
+ * ```typescript
1103
+ * const { data: entries, integrity_valid } = await client.invoices.auditTrail(
1104
+ * 'invoice-uuid'
1105
+ * );
1106
+ *
1107
+ * if (integrity_valid) {
1108
+ * console.log('Audit trail is valid');
1109
+ * entries.forEach(e => console.log(e.action, e.created_at));
1110
+ * }
1111
+ * ```
1112
+ */
1113
+ async auditTrail(id, requestOptions) {
1114
+ return this.http.get(
1115
+ `/invoices/${id}/audit-trail`,
1116
+ void 0,
1117
+ requestOptions
1118
+ );
1119
+ }
1120
+ /**
1121
+ * Convert invoice to another format
1122
+ *
1123
+ * @param input - Conversion parameters
1124
+ * @param requestOptions - Request options
1125
+ * @returns Conversion status
1126
+ *
1127
+ * @example
1128
+ * ```typescript
1129
+ * await client.invoices.convert({
1130
+ * invoice_id: 'invoice-uuid',
1131
+ * target_format: 'ubl'
1132
+ * });
1133
+ * ```
1134
+ */
1135
+ async convert(input, requestOptions) {
1136
+ return this.http.post("/invoices/convert", input, requestOptions);
1137
+ }
1138
+ };
1139
+
1140
+ // src/resources/signatures.ts
1141
+ var SignaturesResource = class {
1142
+ constructor(http) {
1143
+ this.http = http;
1144
+ }
1145
+ /**
1146
+ * List signature requests with optional filtering
1147
+ *
1148
+ * @param options - Filter and pagination options
1149
+ * @param requestOptions - Request options
1150
+ * @returns Paginated list of signatures
1151
+ *
1152
+ * @example
1153
+ * ```typescript
1154
+ * const { data, meta } = await client.signatures.list({
1155
+ * status: 'pending',
1156
+ * per_page: 25
1157
+ * });
1158
+ * console.log(`${meta.total} pending signatures`);
1159
+ * ```
1160
+ */
1161
+ async list(options = {}, requestOptions) {
1162
+ return this.http.get(
1163
+ "/signatures",
1164
+ options,
1165
+ requestOptions
1166
+ );
1167
+ }
1168
+ /**
1169
+ * Get a specific signature by ID
1170
+ *
1171
+ * @param id - Signature UUID
1172
+ * @param requestOptions - Request options
1173
+ * @returns Signature details with signers
1174
+ *
1175
+ * @example
1176
+ * ```typescript
1177
+ * const { data: signature } = await client.signatures.get('uuid-here');
1178
+ * signature.signers?.forEach(signer => {
1179
+ * console.log(`${signer.full_name}: ${signer.status}`);
1180
+ * });
1181
+ * ```
1182
+ */
1183
+ async get(id, requestOptions) {
1184
+ return this.http.get(
1185
+ `/signatures/${id}`,
1186
+ void 0,
1187
+ requestOptions
1188
+ );
1189
+ }
1190
+ /**
1191
+ * Create a new signature request
1192
+ *
1193
+ * Note: This endpoint requires API key authentication.
1194
+ * Creating a signature in production mode will debit your balance.
1195
+ *
1196
+ * @param input - Signature creation data
1197
+ * @param requestOptions - Request options
1198
+ * @returns Created signature
1199
+ *
1200
+ * @example
1201
+ * ```typescript
1202
+ * import { readFileSync } from 'fs';
1203
+ *
1204
+ * const pdfContent = readFileSync('contract.pdf');
1205
+ * const { data: signature } = await client.signatures.create({
1206
+ * title: 'Service Agreement',
1207
+ * description: 'Annual service contract',
1208
+ * document: pdfContent.toString('base64'),
1209
+ * document_name: 'contract.pdf',
1210
+ * signers: [
1211
+ * {
1212
+ * first_name: 'Alice',
1213
+ * last_name: 'Smith',
1214
+ * email: 'alice@example.com',
1215
+ * auth_method: 'email'
1216
+ * },
1217
+ * {
1218
+ * first_name: 'Bob',
1219
+ * last_name: 'Jones',
1220
+ * phone: '+33612345678',
1221
+ * auth_method: 'sms'
1222
+ * }
1223
+ * ],
1224
+ * ui_config: {
1225
+ * logo_url: 'https://mycompany.com/logo.png',
1226
+ * primary_color: '#3b82f6',
1227
+ * company_name: 'My Company'
1228
+ * },
1229
+ * redirect_complete_url: 'https://myapp.com/signed',
1230
+ * redirect_cancel_url: 'https://myapp.com/cancelled'
1231
+ * });
1232
+ *
1233
+ * // Send signing URLs to signers
1234
+ * signature.signers?.forEach(signer => {
1235
+ * console.log(`${signer.email}: ${signer.signing_url}`);
1236
+ * });
1237
+ * ```
1238
+ */
1239
+ async create(input, requestOptions) {
1240
+ return this.http.post(
1241
+ "/signatures",
1242
+ input,
1243
+ requestOptions
1244
+ );
1245
+ }
1246
+ /**
1247
+ * Download signature files
1248
+ *
1249
+ * @param id - Signature UUID
1250
+ * @param type - File type to download
1251
+ * @param requestOptions - Request options
1252
+ * @returns Temporary download URL
1253
+ *
1254
+ * @example
1255
+ * ```typescript
1256
+ * // Download signed document
1257
+ * const { url } = await client.signatures.download(
1258
+ * 'signature-uuid',
1259
+ * 'signed'
1260
+ * );
1261
+ *
1262
+ * // Download audit trail (proof file)
1263
+ * const { url: auditUrl } = await client.signatures.download(
1264
+ * 'signature-uuid',
1265
+ * 'audit_trail'
1266
+ * );
1267
+ * ```
1268
+ */
1269
+ async download(id, type, requestOptions) {
1270
+ return this.http.get(
1271
+ `/signatures/${id}/download/${type}`,
1272
+ void 0,
1273
+ requestOptions
1274
+ );
1275
+ }
1276
+ /**
1277
+ * Send reminder to pending signers
1278
+ *
1279
+ * @param id - Signature UUID
1280
+ * @param requestOptions - Request options
1281
+ * @returns Number of signers reminded
1282
+ *
1283
+ * @example
1284
+ * ```typescript
1285
+ * const { signers_reminded } = await client.signatures.remind('uuid');
1286
+ * console.log(`Reminded ${signers_reminded} signers`);
1287
+ * ```
1288
+ */
1289
+ async remind(id, requestOptions) {
1290
+ return this.http.post(
1291
+ `/signatures/${id}/remind`,
1292
+ void 0,
1293
+ requestOptions
1294
+ );
1295
+ }
1296
+ /**
1297
+ * Cancel a signature request
1298
+ *
1299
+ * Note: Cannot cancel completed signatures.
1300
+ *
1301
+ * @param id - Signature UUID
1302
+ * @param requestOptions - Request options
1303
+ * @returns Cancellation confirmation
1304
+ *
1305
+ * @example
1306
+ * ```typescript
1307
+ * await client.signatures.cancel('signature-uuid');
1308
+ * console.log('Signature cancelled');
1309
+ * ```
1310
+ */
1311
+ async cancel(id, requestOptions) {
1312
+ return this.http.post(
1313
+ `/signatures/${id}/cancel`,
1314
+ void 0,
1315
+ requestOptions
1316
+ );
1317
+ }
1318
+ };
1319
+
1320
+ // src/resources/webhooks.ts
1321
+ var WebhooksResource = class {
1322
+ constructor(http) {
1323
+ this.http = http;
1324
+ }
1325
+ /**
1326
+ * List all webhooks
1327
+ *
1328
+ * @param options - Filter options
1329
+ * @param requestOptions - Request options
1330
+ * @returns List of webhooks
1331
+ *
1332
+ * @example
1333
+ * ```typescript
1334
+ * const { data: webhooks } = await client.webhooks.list();
1335
+ * webhooks.forEach(wh => {
1336
+ * console.log(`${wh.url}: ${wh.is_active ? 'active' : 'inactive'}`);
1337
+ * });
1338
+ * ```
1339
+ */
1340
+ async list(options = {}, requestOptions) {
1341
+ return this.http.get(
1342
+ "/webhooks",
1343
+ options,
1344
+ requestOptions
1345
+ );
1346
+ }
1347
+ /**
1348
+ * Create a new webhook
1349
+ *
1350
+ * Important: The secret is only returned once during creation.
1351
+ * Store it securely - you'll need it to verify webhook signatures.
1352
+ *
1353
+ * @param input - Webhook configuration
1354
+ * @param requestOptions - Request options
1355
+ * @returns Created webhook with secret
1356
+ *
1357
+ * @example
1358
+ * ```typescript
1359
+ * const { data: webhook } = await client.webhooks.create({
1360
+ * url: 'https://myapp.com/webhooks/scell',
1361
+ * events: [
1362
+ * 'invoice.created',
1363
+ * 'invoice.validated',
1364
+ * 'signature.completed',
1365
+ * 'balance.low'
1366
+ * ],
1367
+ * environment: 'production',
1368
+ * headers: {
1369
+ * 'X-Custom-Auth': 'my-secret-token'
1370
+ * },
1371
+ * retry_count: 5,
1372
+ * timeout_seconds: 30
1373
+ * });
1374
+ *
1375
+ * // IMPORTANT: Store this secret securely!
1376
+ * await saveWebhookSecret(webhook.id, webhook.secret);
1377
+ * ```
1378
+ */
1379
+ async create(input, requestOptions) {
1380
+ return this.http.post(
1381
+ "/webhooks",
1382
+ input,
1383
+ requestOptions
1384
+ );
1385
+ }
1386
+ /**
1387
+ * Update a webhook
1388
+ *
1389
+ * @param id - Webhook UUID
1390
+ * @param input - Fields to update
1391
+ * @param requestOptions - Request options
1392
+ * @returns Updated webhook
1393
+ *
1394
+ * @example
1395
+ * ```typescript
1396
+ * // Disable a webhook temporarily
1397
+ * await client.webhooks.update('webhook-uuid', {
1398
+ * is_active: false
1399
+ * });
1400
+ *
1401
+ * // Update events
1402
+ * await client.webhooks.update('webhook-uuid', {
1403
+ * events: ['invoice.validated', 'signature.completed']
1404
+ * });
1405
+ * ```
1406
+ */
1407
+ async update(id, input, requestOptions) {
1408
+ return this.http.put(
1409
+ `/webhooks/${id}`,
1410
+ input,
1411
+ requestOptions
1412
+ );
1413
+ }
1414
+ /**
1415
+ * Delete a webhook
1416
+ *
1417
+ * @param id - Webhook UUID
1418
+ * @param requestOptions - Request options
1419
+ * @returns Deletion confirmation
1420
+ *
1421
+ * @example
1422
+ * ```typescript
1423
+ * await client.webhooks.delete('webhook-uuid');
1424
+ * ```
1425
+ */
1426
+ async delete(id, requestOptions) {
1427
+ return this.http.delete(`/webhooks/${id}`, requestOptions);
1428
+ }
1429
+ /**
1430
+ * Regenerate webhook secret
1431
+ *
1432
+ * Use this if your secret has been compromised.
1433
+ * The old secret will immediately stop working.
1434
+ *
1435
+ * @param id - Webhook UUID
1436
+ * @param requestOptions - Request options
1437
+ * @returns Webhook with new secret
1438
+ *
1439
+ * @example
1440
+ * ```typescript
1441
+ * const { data: webhook } = await client.webhooks.regenerateSecret(
1442
+ * 'webhook-uuid'
1443
+ * );
1444
+ *
1445
+ * // Update your stored secret
1446
+ * await updateWebhookSecret(webhook.id, webhook.secret);
1447
+ * ```
1448
+ */
1449
+ async regenerateSecret(id, requestOptions) {
1450
+ return this.http.post(
1451
+ `/webhooks/${id}/regenerate-secret`,
1452
+ void 0,
1453
+ requestOptions
1454
+ );
1455
+ }
1456
+ /**
1457
+ * Test webhook by sending a test event
1458
+ *
1459
+ * @param id - Webhook UUID
1460
+ * @param requestOptions - Request options
1461
+ * @returns Test result
1462
+ *
1463
+ * @example
1464
+ * ```typescript
1465
+ * const result = await client.webhooks.test('webhook-uuid');
1466
+ *
1467
+ * if (result.success) {
1468
+ * console.log(`Success! Response time: ${result.response_time_ms}ms`);
1469
+ * } else {
1470
+ * console.log(`Failed: ${result.error}`);
1471
+ * }
1472
+ * ```
1473
+ */
1474
+ async test(id, requestOptions) {
1475
+ return this.http.post(
1476
+ `/webhooks/${id}/test`,
1477
+ void 0,
1478
+ requestOptions
1479
+ );
1480
+ }
1481
+ /**
1482
+ * Get webhook delivery logs
1483
+ *
1484
+ * @param id - Webhook UUID
1485
+ * @param options - Pagination options
1486
+ * @param requestOptions - Request options
1487
+ * @returns Paginated list of logs
1488
+ *
1489
+ * @example
1490
+ * ```typescript
1491
+ * const { data: logs } = await client.webhooks.logs('webhook-uuid', {
1492
+ * per_page: 50
1493
+ * });
1494
+ *
1495
+ * logs.forEach(log => {
1496
+ * const status = log.success ? 'OK' : 'FAILED';
1497
+ * console.log(`${log.event} - ${status} (${log.response_time_ms}ms)`);
1498
+ * });
1499
+ * ```
1500
+ */
1501
+ async logs(id, options = {}, requestOptions) {
1502
+ return this.http.get(
1503
+ `/webhooks/${id}/logs`,
1504
+ options,
1505
+ requestOptions
1506
+ );
1507
+ }
1508
+ };
1509
+
1510
+ // src/utils/webhook-verify.ts
1511
+ function parseSignatureHeader(header) {
1512
+ const parts = header.split(",");
1513
+ let timestamp;
1514
+ let signature;
1515
+ for (const part of parts) {
1516
+ const splitIndex = part.indexOf("=");
1517
+ if (splitIndex === -1) continue;
1518
+ const key = part.substring(0, splitIndex);
1519
+ const value = part.substring(splitIndex + 1);
1520
+ if (key === "t") {
1521
+ timestamp = parseInt(value, 10);
1522
+ } else if (key === "v1") {
1523
+ signature = value;
1524
+ }
1525
+ }
1526
+ if (timestamp === void 0 || signature === void 0) {
1527
+ return null;
1528
+ }
1529
+ return { timestamp, signature };
1530
+ }
1531
+ async function computeSignature(payload, timestamp, secret) {
1532
+ const signedPayload = `${timestamp}.${payload}`;
1533
+ const encoder = new TextEncoder();
1534
+ const keyData = encoder.encode(secret);
1535
+ const messageData = encoder.encode(signedPayload);
1536
+ const cryptoKey = await crypto.subtle.importKey(
1537
+ "raw",
1538
+ keyData,
1539
+ { name: "HMAC", hash: "SHA-256" },
1540
+ false,
1541
+ ["sign"]
1542
+ );
1543
+ const signatureBuffer = await crypto.subtle.sign(
1544
+ "HMAC",
1545
+ cryptoKey,
1546
+ messageData
1547
+ );
1548
+ return Array.from(new Uint8Array(signatureBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
1549
+ }
1550
+ function secureCompare(a, b) {
1551
+ if (a.length !== b.length) {
1552
+ return false;
1553
+ }
1554
+ let result = 0;
1555
+ for (let i = 0; i < a.length; i++) {
1556
+ result |= a.charCodeAt(i) ^ b.charCodeAt(i);
1557
+ }
1558
+ return result === 0;
1559
+ }
1560
+ var ScellWebhooks = {
1561
+ /**
1562
+ * Verify webhook signature
1563
+ *
1564
+ * @param payload - Raw request body as string
1565
+ * @param signature - Value of X-Scell-Signature header
1566
+ * @param secret - Your webhook secret (whsec_...)
1567
+ * @param options - Verification options
1568
+ * @returns True if signature is valid
1569
+ *
1570
+ * @example
1571
+ * ```typescript
1572
+ * const isValid = await ScellWebhooks.verifySignature(
1573
+ * rawBody,
1574
+ * req.headers['x-scell-signature'],
1575
+ * 'whsec_abc123...'
1576
+ * );
1577
+ * ```
1578
+ */
1579
+ async verifySignature(payload, signature, secret, options = {}) {
1580
+ const { tolerance = 300 } = options;
1581
+ const parsed = parseSignatureHeader(signature);
1582
+ if (!parsed) {
1583
+ return false;
1584
+ }
1585
+ const { timestamp, signature: providedSignature } = parsed;
1586
+ const now = Math.floor(Date.now() / 1e3);
1587
+ if (Math.abs(now - timestamp) > tolerance) {
1588
+ return false;
1589
+ }
1590
+ const expectedSignature = await computeSignature(payload, timestamp, secret);
1591
+ return secureCompare(expectedSignature, providedSignature);
1592
+ },
1593
+ /**
1594
+ * Verify webhook signature synchronously using Node.js crypto
1595
+ * (Only works in Node.js environment)
1596
+ *
1597
+ * @param payload - Raw request body as string
1598
+ * @param signature - Value of X-Scell-Signature header
1599
+ * @param secret - Your webhook secret (whsec_...)
1600
+ * @param options - Verification options
1601
+ * @returns True if signature is valid
1602
+ */
1603
+ verifySignatureSync(payload, signature, secret, options = {}) {
1604
+ const { tolerance = 300 } = options;
1605
+ const parsed = parseSignatureHeader(signature);
1606
+ if (!parsed) {
1607
+ return false;
1608
+ }
1609
+ const { timestamp, signature: providedSignature } = parsed;
1610
+ const now = Math.floor(Date.now() / 1e3);
1611
+ if (Math.abs(now - timestamp) > tolerance) {
1612
+ return false;
1613
+ }
1614
+ const crypto2 = __require("crypto");
1615
+ const signedPayload = `${timestamp}.${payload}`;
1616
+ const expectedSignature = crypto2.createHmac("sha256", secret).update(signedPayload).digest("hex");
1617
+ try {
1618
+ return crypto2.timingSafeEqual(
1619
+ Buffer.from(expectedSignature),
1620
+ Buffer.from(providedSignature)
1621
+ );
1622
+ } catch {
1623
+ return false;
1624
+ }
1625
+ },
1626
+ /**
1627
+ * Parse webhook payload
1628
+ *
1629
+ * @param payload - Raw request body as string
1630
+ * @returns Parsed webhook payload
1631
+ *
1632
+ * @example
1633
+ * ```typescript
1634
+ * const event = ScellWebhooks.parsePayload<InvoiceWebhookData>(rawBody);
1635
+ * if (event.event === 'invoice.validated') {
1636
+ * console.log('Invoice validated:', event.data.invoice_number);
1637
+ * }
1638
+ * ```
1639
+ */
1640
+ parsePayload(payload) {
1641
+ return JSON.parse(payload);
1642
+ },
1643
+ /**
1644
+ * Construct a test webhook event for local testing
1645
+ *
1646
+ * @param event - Event type
1647
+ * @param data - Event data
1648
+ * @param secret - Webhook secret for signing
1649
+ * @returns Object with payload and headers for testing
1650
+ */
1651
+ async constructTestEvent(event, data, secret) {
1652
+ const timestamp = Math.floor(Date.now() / 1e3);
1653
+ const webhookPayload = {
1654
+ event,
1655
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1656
+ data
1657
+ };
1658
+ const payload = JSON.stringify(webhookPayload);
1659
+ const signature = await computeSignature(payload, timestamp, secret);
1660
+ return {
1661
+ payload,
1662
+ headers: {
1663
+ "X-Scell-Signature": `t=${timestamp},v1=${signature}`,
1664
+ "X-Scell-Event": event,
1665
+ "X-Scell-Delivery": crypto.randomUUID(),
1666
+ "Content-Type": "application/json"
1667
+ }
1668
+ };
1669
+ }
1670
+ };
1671
+
1672
+ // src/index.ts
1673
+ init_errors();
1674
+ var ScellClient = class {
1675
+ http;
1676
+ /** Authentication operations */
1677
+ auth;
1678
+ /** Company management */
1679
+ companies;
1680
+ /** API key management */
1681
+ apiKeys;
1682
+ /** Balance and transactions */
1683
+ balance;
1684
+ /** Webhook management */
1685
+ webhooks;
1686
+ /** Invoice listing (read-only via dashboard) */
1687
+ invoices;
1688
+ /** Signature listing (read-only via dashboard) */
1689
+ signatures;
1690
+ /**
1691
+ * Create a new Scell Dashboard Client
1692
+ *
1693
+ * @param token - Bearer token from login
1694
+ * @param config - Client configuration
1695
+ *
1696
+ * @example
1697
+ * ```typescript
1698
+ * const client = new ScellClient('your-bearer-token', {
1699
+ * baseUrl: 'https://api.scell.io/api/v1',
1700
+ * timeout: 30000,
1701
+ * retry: { maxRetries: 3 }
1702
+ * });
1703
+ * ```
1704
+ */
1705
+ constructor(token, config = {}) {
1706
+ this.http = new HttpClient("bearer", token, config);
1707
+ this.auth = new AuthResource(this.http);
1708
+ this.companies = new CompaniesResource(this.http);
1709
+ this.apiKeys = new ApiKeysResource(this.http);
1710
+ this.balance = new BalanceResource(this.http);
1711
+ this.webhooks = new WebhooksResource(this.http);
1712
+ this.invoices = new InvoicesResource(this.http);
1713
+ this.signatures = new SignaturesResource(this.http);
1714
+ }
1715
+ };
1716
+ var ScellApiClient = class {
1717
+ http;
1718
+ /** Invoice operations (create, download, convert) */
1719
+ invoices;
1720
+ /** Signature operations (create, download, remind, cancel) */
1721
+ signatures;
1722
+ /**
1723
+ * Create a new Scell API Client
1724
+ *
1725
+ * @param apiKey - Your API key (from dashboard)
1726
+ * @param config - Client configuration
1727
+ *
1728
+ * @example
1729
+ * ```typescript
1730
+ * // Production client
1731
+ * const client = new ScellApiClient('sk_live_xxx');
1732
+ *
1733
+ * // Sandbox client
1734
+ * const sandboxClient = new ScellApiClient('sk_test_xxx', {
1735
+ * baseUrl: 'https://api.scell.io/api/v1/sandbox'
1736
+ * });
1737
+ * ```
1738
+ */
1739
+ constructor(apiKey, config = {}) {
1740
+ this.http = new HttpClient("api-key", apiKey, config);
1741
+ this.invoices = new InvoicesResource(this.http);
1742
+ this.signatures = new SignaturesResource(this.http);
1743
+ }
1744
+ };
1745
+
1746
+ export { ScellApiClient, ScellAuth, ScellAuthenticationError, ScellAuthorizationError, ScellClient, ScellError, ScellInsufficientBalanceError, ScellNetworkError, ScellNotFoundError, ScellRateLimitError, ScellServerError, ScellTimeoutError, ScellValidationError, ScellWebhooks, createRetryWrapper, withRetry };
1747
+ //# sourceMappingURL=index.mjs.map
1748
+ //# sourceMappingURL=index.mjs.map