@beinfi/pulse-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.
package/dist/index.js ADDED
@@ -0,0 +1,712 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ Pulse: () => Pulse,
24
+ PulseApiError: () => PulseApiError,
25
+ PulseAuthenticationError: () => PulseAuthenticationError,
26
+ PulseError: () => PulseError,
27
+ PulseRateLimitError: () => PulseRateLimitError,
28
+ mountCheckout: () => mountCheckout,
29
+ verifyWebhookSignature: () => verifyWebhookSignature
30
+ });
31
+ module.exports = __toCommonJS(index_exports);
32
+
33
+ // src/errors.ts
34
+ var PulseError = class extends Error {
35
+ constructor(message) {
36
+ super(message);
37
+ this.name = "PulseError";
38
+ }
39
+ };
40
+ var PulseApiError = class extends PulseError {
41
+ /** HTTP status code (e.g. 400, 404, 500). */
42
+ status;
43
+ /** Machine-readable error code (e.g. `"unauthorized"`, `"not_found"`). */
44
+ errorCode;
45
+ /** Rate limit info from response headers, if available. */
46
+ rateLimit;
47
+ constructor(status, errorCode, message, rateLimit) {
48
+ super(message);
49
+ this.name = "PulseApiError";
50
+ this.status = status;
51
+ this.errorCode = errorCode;
52
+ this.rateLimit = rateLimit;
53
+ }
54
+ };
55
+ var PulseAuthenticationError = class extends PulseApiError {
56
+ constructor(message = "Invalid API key") {
57
+ super(401, "unauthorized", message);
58
+ this.name = "PulseAuthenticationError";
59
+ }
60
+ };
61
+ var PulseRateLimitError = class extends PulseApiError {
62
+ /** Number of seconds to wait before retrying. */
63
+ retryAfter;
64
+ constructor(retryAfter, rateLimit) {
65
+ super(429, "rate_limit_exceeded", "Rate limit exceeded", rateLimit);
66
+ this.name = "PulseRateLimitError";
67
+ this.retryAfter = retryAfter;
68
+ }
69
+ };
70
+
71
+ // src/client.ts
72
+ var DEFAULT_BASE_URL = "https://api.beinfi.com";
73
+ var HttpClient = class {
74
+ apiKey;
75
+ baseUrl;
76
+ constructor(apiKey, baseUrl) {
77
+ if (!apiKey.startsWith("sk_live_")) {
78
+ throw new PulseError(
79
+ 'Invalid API key format. Keys must start with "sk_live_"'
80
+ );
81
+ }
82
+ this.apiKey = apiKey;
83
+ this.baseUrl = (baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
84
+ }
85
+ async request(method, path, options) {
86
+ let url = `${this.baseUrl}/api/v1${path}`;
87
+ if (options?.query) {
88
+ const params = new URLSearchParams();
89
+ for (const [key, value] of Object.entries(options.query)) {
90
+ if (value !== void 0) {
91
+ params.set(key, String(value));
92
+ }
93
+ }
94
+ const qs = params.toString();
95
+ if (qs) url += `?${qs}`;
96
+ }
97
+ const headers = {
98
+ Authorization: `Bearer ${this.apiKey}`,
99
+ "Content-Type": "application/json"
100
+ };
101
+ const response = await fetch(url, {
102
+ method,
103
+ headers,
104
+ body: options?.body ? JSON.stringify(options.body) : void 0
105
+ });
106
+ const rateLimit = this.parseRateLimit(response.headers);
107
+ if (!response.ok) {
108
+ this.handleError(response.status, await this.safeJson(response), rateLimit);
109
+ }
110
+ if (response.status === 204) {
111
+ return void 0;
112
+ }
113
+ const json = await response.json();
114
+ if (json && typeof json === "object" && "data" in json) {
115
+ return json.data;
116
+ }
117
+ return json;
118
+ }
119
+ parseRateLimit(headers) {
120
+ const limit = headers.get("X-RateLimit-Limit");
121
+ const remaining = headers.get("X-RateLimit-Remaining");
122
+ const reset = headers.get("X-RateLimit-Reset");
123
+ if (limit && remaining && reset) {
124
+ return {
125
+ limit: Number(limit),
126
+ remaining: Number(remaining),
127
+ reset: Number(reset)
128
+ };
129
+ }
130
+ return void 0;
131
+ }
132
+ async safeJson(response) {
133
+ try {
134
+ return await response.json();
135
+ } catch {
136
+ return null;
137
+ }
138
+ }
139
+ handleError(status, body, rateLimit) {
140
+ const errorCode = body?.error ?? "unknown_error";
141
+ const message = body?.message ?? `Request failed with status ${status}`;
142
+ if (status === 401) {
143
+ throw new PulseAuthenticationError(message);
144
+ }
145
+ if (status === 429) {
146
+ const retryAfter = rateLimit?.reset ? Math.max(0, rateLimit.reset - Math.floor(Date.now() / 1e3)) : 60;
147
+ throw new PulseRateLimitError(retryAfter, rateLimit);
148
+ }
149
+ throw new PulseApiError(status, errorCode, message, rateLimit);
150
+ }
151
+ };
152
+
153
+ // src/resources/payment-links.ts
154
+ var PaymentLinksResource = class {
155
+ constructor(client) {
156
+ this.client = client;
157
+ }
158
+ /**
159
+ * Create a new payment link.
160
+ *
161
+ * @param params - Payment link parameters (title, amount, optional currency and description).
162
+ * @returns The created payment link object.
163
+ * @throws {PulseAuthenticationError} If the API key is invalid.
164
+ * @throws {PulseApiError} If validation fails (e.g. invalid currency).
165
+ *
166
+ * @example
167
+ * ```typescript
168
+ * const link = await pulse.paymentLinks.create({
169
+ * title: 'Web Development',
170
+ * amount: '150.00',
171
+ * currency: 'USD',
172
+ * description: 'Landing page development',
173
+ * })
174
+ * console.log(link.id, link.slug)
175
+ * ```
176
+ */
177
+ async create(params) {
178
+ return this.client.request("POST", "/payment-links", {
179
+ body: params
180
+ });
181
+ }
182
+ /**
183
+ * List payment links for the authenticated user.
184
+ *
185
+ * @param params - Optional pagination parameters (limit, offset).
186
+ * @returns Array of payment link objects.
187
+ * @throws {PulseAuthenticationError} If the API key is invalid.
188
+ *
189
+ * @example
190
+ * ```typescript
191
+ * const links = await pulse.paymentLinks.list({ limit: 10, offset: 0 })
192
+ * for (const link of links) {
193
+ * console.log(link.title, link.amount, link.status)
194
+ * }
195
+ * ```
196
+ */
197
+ async list(params) {
198
+ return this.client.request("GET", "/payment-links", {
199
+ query: {
200
+ limit: params?.limit,
201
+ offset: params?.offset
202
+ }
203
+ });
204
+ }
205
+ /**
206
+ * Get a single payment link by ID.
207
+ *
208
+ * @param linkId - The payment link UUID.
209
+ * @returns The payment link object.
210
+ * @throws {PulseAuthenticationError} If the API key is invalid.
211
+ * @throws {PulseApiError} With status 404 if the link doesn't exist.
212
+ *
213
+ * @example
214
+ * ```typescript
215
+ * const link = await pulse.paymentLinks.get('abc-123-def')
216
+ * console.log(link.title, link.amount)
217
+ * ```
218
+ */
219
+ async get(linkId) {
220
+ return this.client.request("GET", `/payment-links/${linkId}`);
221
+ }
222
+ /**
223
+ * List payment intents (payment attempts) for a specific payment link.
224
+ *
225
+ * @param linkId - The payment link UUID.
226
+ * @returns Array of payment intent objects.
227
+ * @throws {PulseAuthenticationError} If the API key is invalid.
228
+ *
229
+ * @example
230
+ * ```typescript
231
+ * const intents = await pulse.paymentLinks.listIntents('abc-123-def')
232
+ * const confirmed = intents.filter(i => i.status === 'confirmed')
233
+ * console.log(`${confirmed.length} confirmed payments`)
234
+ * ```
235
+ */
236
+ async listIntents(linkId) {
237
+ return this.client.request(
238
+ "GET",
239
+ `/payment-links/${linkId}/intents`
240
+ );
241
+ }
242
+ };
243
+
244
+ // src/resources/webhooks.ts
245
+ var WebhooksResource = class {
246
+ constructor(client) {
247
+ this.client = client;
248
+ }
249
+ /**
250
+ * Create a new webhook subscription.
251
+ * The response includes a `secret` field (64-char hex) used to verify signatures.
252
+ * **Store this secret securely** — it is only returned once at creation time.
253
+ *
254
+ * @param params - Webhook URL and event types to subscribe to.
255
+ * @returns The created webhook with its signing secret.
256
+ * @throws {PulseAuthenticationError} If the API key is invalid.
257
+ *
258
+ * @example
259
+ * ```typescript
260
+ * const wh = await pulse.webhooks.create({
261
+ * url: 'https://example.com/webhook',
262
+ * events: ['payment.confirmed'],
263
+ * })
264
+ * // Save wh.secret to your environment/secrets manager
265
+ * console.log('Webhook secret:', wh.secret)
266
+ * ```
267
+ */
268
+ async create(params) {
269
+ return this.client.request("POST", "/webhooks", {
270
+ body: params
271
+ });
272
+ }
273
+ /**
274
+ * List all webhook subscriptions for the authenticated user.
275
+ *
276
+ * @returns Array of webhook objects (without secrets).
277
+ * @throws {PulseAuthenticationError} If the API key is invalid.
278
+ *
279
+ * @example
280
+ * ```typescript
281
+ * const webhooks = await pulse.webhooks.list()
282
+ * for (const wh of webhooks) {
283
+ * console.log(wh.url, wh.events, wh.isActive)
284
+ * }
285
+ * ```
286
+ */
287
+ async list() {
288
+ return this.client.request("GET", "/webhooks");
289
+ }
290
+ /**
291
+ * Delete a webhook subscription.
292
+ *
293
+ * @param id - The webhook UUID to delete.
294
+ * @throws {PulseAuthenticationError} If the API key is invalid.
295
+ *
296
+ * @example
297
+ * ```typescript
298
+ * await pulse.webhooks.delete('webhook-id')
299
+ * ```
300
+ */
301
+ async delete(id) {
302
+ return this.client.request("DELETE", `/webhooks/${id}`);
303
+ }
304
+ };
305
+
306
+ // src/resources/metering.ts
307
+ function generateId() {
308
+ const hex = "0123456789abcdef";
309
+ let id = "";
310
+ for (let i = 0; i < 32; i++) {
311
+ id += hex[Math.floor(Math.random() * 16)];
312
+ if (i === 7 || i === 11 || i === 15 || i === 19) id += "-";
313
+ }
314
+ return id;
315
+ }
316
+ var MeteringResource = class {
317
+ constructor(client) {
318
+ this.client = client;
319
+ }
320
+ /**
321
+ * Track a single usage event.
322
+ *
323
+ * @param params - Event parameters (meterId, customerId, value).
324
+ * @returns The created event object.
325
+ *
326
+ * @example
327
+ * ```typescript
328
+ * await pulse.metering.track({
329
+ * meterId: 'tokens',
330
+ * customerId: 'user_123',
331
+ * value: 1500,
332
+ * metadata: { model: 'gpt-4' }
333
+ * })
334
+ * ```
335
+ */
336
+ async track(params) {
337
+ return this.client.request(
338
+ "POST",
339
+ "/metering/events",
340
+ {
341
+ body: {
342
+ eventId: params.eventId || generateId(),
343
+ meterId: params.meterId,
344
+ customerId: params.customerId,
345
+ value: typeof params.value === "number" ? String(params.value) : params.value,
346
+ timestamp: params.timestamp?.toISOString(),
347
+ metadata: params.metadata
348
+ }
349
+ }
350
+ );
351
+ }
352
+ /**
353
+ * Track multiple usage events in a single request.
354
+ *
355
+ * @param events - Array of event parameters.
356
+ * @returns Batch result with accepted/failed counts.
357
+ *
358
+ * @example
359
+ * ```typescript
360
+ * await pulse.metering.trackBatch([
361
+ * { meterId: 'tokens', customerId: 'user_1', value: 500 },
362
+ * { meterId: 'tokens', customerId: 'user_2', value: 1200 },
363
+ * ])
364
+ * ```
365
+ */
366
+ async trackBatch(events) {
367
+ return this.client.request(
368
+ "POST",
369
+ "/metering/events/batch",
370
+ {
371
+ body: {
372
+ events: events.map((e) => ({
373
+ eventId: e.eventId || generateId(),
374
+ meterId: e.meterId,
375
+ customerId: e.customerId,
376
+ value: typeof e.value === "number" ? String(e.value) : e.value,
377
+ timestamp: e.timestamp?.toISOString(),
378
+ metadata: e.metadata
379
+ }))
380
+ }
381
+ }
382
+ );
383
+ }
384
+ /**
385
+ * Query aggregated usage data.
386
+ *
387
+ * @param query - Optional filters (customerId, date range).
388
+ * @returns Aggregated usage by meter.
389
+ *
390
+ * @example
391
+ * ```typescript
392
+ * const usage = await pulse.metering.getUsage({ customerId: 'user_123' })
393
+ * for (const item of usage.data) {
394
+ * console.log(item.meterName, item.totalValue, item.totalAmount)
395
+ * }
396
+ * ```
397
+ */
398
+ async getUsage(query) {
399
+ return this.client.request("GET", "/metering/usage", {
400
+ query: {
401
+ customerId: query?.customerId,
402
+ startDate: query?.startDate,
403
+ endDate: query?.endDate
404
+ }
405
+ });
406
+ }
407
+ /**
408
+ * List all products.
409
+ *
410
+ * @returns Array of product objects with meters.
411
+ */
412
+ async listProducts() {
413
+ return this.client.request("GET", "/metering/products");
414
+ }
415
+ /**
416
+ * Create a new product.
417
+ *
418
+ * @param data - Product data (name, optional description).
419
+ * @returns The created product object.
420
+ *
421
+ * @example
422
+ * ```typescript
423
+ * const product = await pulse.metering.createProduct({
424
+ * name: 'AI Agent',
425
+ * description: 'Usage-based AI agent billing',
426
+ * })
427
+ * ```
428
+ */
429
+ async createProduct(data) {
430
+ return this.client.request(
431
+ "POST",
432
+ "/metering/products",
433
+ { body: data }
434
+ );
435
+ }
436
+ /**
437
+ * Create a new meter on a product.
438
+ *
439
+ * @param productId - The product UUID.
440
+ * @param data - Meter data (name, displayName, unit, unitPrice).
441
+ * @returns The created meter object.
442
+ *
443
+ * @example
444
+ * ```typescript
445
+ * const meter = await pulse.metering.createMeter('product-id', {
446
+ * name: 'tokens',
447
+ * displayName: 'AI Tokens',
448
+ * unit: 'token',
449
+ * unitPrice: '0.0001',
450
+ * })
451
+ * ```
452
+ */
453
+ async createMeter(productId, data) {
454
+ return this.client.request(
455
+ "POST",
456
+ `/metering/products/${productId}/meters`,
457
+ { body: data }
458
+ );
459
+ }
460
+ /**
461
+ * Create a customer for a product.
462
+ *
463
+ * @param productId - The product UUID.
464
+ * @param data - Customer data (externalId, name, email, metadata).
465
+ * @returns The created customer object.
466
+ *
467
+ * @example
468
+ * ```typescript
469
+ * const customer = await pulse.metering.createCustomer('product-id', {
470
+ * externalId: 'user_123',
471
+ * name: 'John Doe',
472
+ * email: 'john@example.com',
473
+ * })
474
+ * ```
475
+ */
476
+ async createCustomer(productId, data) {
477
+ return this.client.request(
478
+ "POST",
479
+ `/metering/products/${productId}/customers`,
480
+ { body: data }
481
+ );
482
+ }
483
+ /**
484
+ * Get customer usage for a specific product.
485
+ *
486
+ * @param productId - The product UUID.
487
+ * @param customerId - The customer external ID.
488
+ * @param query - Optional date range filters.
489
+ * @returns Aggregated usage by meter for the customer.
490
+ */
491
+ async getCustomerUsage(productId, customerId, query) {
492
+ return this.client.request(
493
+ "GET",
494
+ `/metering/products/${productId}/customers/${customerId}/usage`,
495
+ {
496
+ query: {
497
+ startDate: query?.startDate,
498
+ endDate: query?.endDate
499
+ }
500
+ }
501
+ );
502
+ }
503
+ /**
504
+ * Create a session for tracking multiple events for a customer.
505
+ * Events are accumulated and sent as a batch when `.end()` is called.
506
+ *
507
+ * @param customerId - The customer external ID.
508
+ * @returns A session instance.
509
+ *
510
+ * @example
511
+ * ```typescript
512
+ * const session = pulse.metering.session('user_123')
513
+ * session.track('tokens', 500)
514
+ * session.track('tokens', 300)
515
+ * session.track('requests', 1)
516
+ * await session.end() // sends batch: tokens=800, requests=1
517
+ * ```
518
+ */
519
+ session(customerId) {
520
+ return new MeteringSession(this, customerId);
521
+ }
522
+ };
523
+ var MeteringSession = class {
524
+ constructor(metering, customerId) {
525
+ this.metering = metering;
526
+ this.customerId = customerId;
527
+ }
528
+ events = [];
529
+ /**
530
+ * Queue a tracking event in this session.
531
+ */
532
+ track(meterId, value, metadata) {
533
+ this.events.push({
534
+ meterId,
535
+ customerId: this.customerId,
536
+ value,
537
+ metadata
538
+ });
539
+ return this;
540
+ }
541
+ /**
542
+ * Send all accumulated events as a batch and clear the session.
543
+ */
544
+ async end() {
545
+ if (this.events.length === 0) {
546
+ return { accepted: 0, failed: 0, results: [] };
547
+ }
548
+ const result = await this.metering.trackBatch(this.events);
549
+ this.events = [];
550
+ return result;
551
+ }
552
+ };
553
+
554
+ // src/webhooks/verify.ts
555
+ var import_crypto = require("crypto");
556
+ function verifyWebhookSignature(rawBody, signatureHeader, secret) {
557
+ const expectedSig = (0, import_crypto.createHmac)("sha256", secret).update(rawBody).digest("hex");
558
+ const receivedSig = signatureHeader.startsWith("sha256=") ? signatureHeader.slice(7) : signatureHeader;
559
+ if (expectedSig.length !== receivedSig.length) {
560
+ return false;
561
+ }
562
+ return (0, import_crypto.timingSafeEqual)(
563
+ Buffer.from(expectedSig, "hex"),
564
+ Buffer.from(receivedSig, "hex")
565
+ );
566
+ }
567
+
568
+ // src/checkout/checkout.ts
569
+ var DEFAULT_BASE_URL2 = "https://pulse.beinfi.com";
570
+ function mountCheckout(selector, options) {
571
+ const container = typeof selector === "string" ? document.querySelector(selector) : selector;
572
+ if (!container) {
573
+ throw new Error(`[Pulse Checkout] Container not found: ${selector}`);
574
+ }
575
+ const baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL2).replace(/\/$/, "");
576
+ const allowedOrigin = new URL(baseUrl).origin;
577
+ const handlers = {};
578
+ function emit(event, ...args) {
579
+ for (const handler of handlers[event] ?? []) {
580
+ handler(...args);
581
+ }
582
+ }
583
+ const iframe = document.createElement("iframe");
584
+ iframe.src = `${baseUrl}/embed/pay/${options.linkId}`;
585
+ iframe.style.width = "100%";
586
+ iframe.style.border = "none";
587
+ iframe.style.colorScheme = "normal";
588
+ iframe.setAttribute("allowtransparency", "true");
589
+ iframe.allow = "clipboard-write";
590
+ function handleMessage(event) {
591
+ if (event.origin !== allowedOrigin) return;
592
+ const { type, ...data } = event.data ?? {};
593
+ switch (type) {
594
+ case "pulse:ready":
595
+ if (options.theme) {
596
+ iframe.contentWindow?.postMessage(
597
+ { type: "pulse:config", theme: options.theme },
598
+ allowedOrigin
599
+ );
600
+ }
601
+ options.onReady?.();
602
+ emit("ready");
603
+ break;
604
+ case "pulse:resize":
605
+ if (typeof data.height === "number") {
606
+ iframe.style.height = `${data.height}px`;
607
+ }
608
+ break;
609
+ case "pulse:success": {
610
+ const payment = data.payment;
611
+ options.onSuccess?.(payment);
612
+ emit("success", payment);
613
+ break;
614
+ }
615
+ case "pulse:error": {
616
+ const error = data.error;
617
+ options.onError?.(error);
618
+ emit("error", error);
619
+ break;
620
+ }
621
+ }
622
+ }
623
+ window.addEventListener("message", handleMessage);
624
+ container.appendChild(iframe);
625
+ return {
626
+ unmount() {
627
+ window.removeEventListener("message", handleMessage);
628
+ iframe.remove();
629
+ options.onClose?.();
630
+ emit("close");
631
+ },
632
+ on(event, handler) {
633
+ if (!handlers[event]) handlers[event] = [];
634
+ handlers[event].push(handler);
635
+ }
636
+ };
637
+ }
638
+
639
+ // src/index.ts
640
+ var Pulse = class {
641
+ /** Resource for creating, listing, and fetching payment links. */
642
+ paymentLinks;
643
+ /** Resource for creating, listing, and deleting webhook subscriptions. */
644
+ webhooks;
645
+ /** Resource for usage-based metering, tracking events, and querying usage. */
646
+ metering;
647
+ client;
648
+ /**
649
+ * Static utilities for verifying webhook signatures.
650
+ * Does not require a Pulse instance — useful in webhook handler endpoints.
651
+ *
652
+ * @example
653
+ * ```typescript
654
+ * const isValid = Pulse.webhooks.verifySignature(
655
+ * rawBody,
656
+ * req.headers['x-pulse-signature'],
657
+ * process.env.PULSE_WEBHOOK_SECRET
658
+ * )
659
+ * ```
660
+ */
661
+ static webhooks = {
662
+ verifySignature: verifyWebhookSignature
663
+ };
664
+ /**
665
+ * Static utilities for mounting the checkout widget.
666
+ * Browser-only — embeds an iframe-based checkout for a payment link.
667
+ *
668
+ * @example
669
+ * ```typescript
670
+ * const instance = Pulse.checkout.mount('#checkout', {
671
+ * linkId: 'abc-123',
672
+ * onSuccess: (payment) => console.log('Paid!', payment),
673
+ * })
674
+ * ```
675
+ */
676
+ static checkout = {
677
+ mount: mountCheckout
678
+ };
679
+ /**
680
+ * Create a new Pulse SDK client.
681
+ *
682
+ * @param config - Either an API key string (`"sk_live_..."`) or a {@link PulseConfig} object.
683
+ * @throws {PulseError} If the API key doesn't start with `"sk_live_"`.
684
+ *
685
+ * @example
686
+ * ```typescript
687
+ * // String shorthand
688
+ * const pulse = new Pulse('sk_live_...')
689
+ *
690
+ * // Config object
691
+ * const pulse = new Pulse({ apiKey: 'sk_live_...', baseUrl: 'https://api.beinfi.com' })
692
+ * ```
693
+ */
694
+ constructor(config) {
695
+ const apiKey = typeof config === "string" ? config : config.apiKey;
696
+ const baseUrl = typeof config === "string" ? void 0 : config.baseUrl;
697
+ this.client = new HttpClient(apiKey, baseUrl);
698
+ this.paymentLinks = new PaymentLinksResource(this.client);
699
+ this.webhooks = new WebhooksResource(this.client);
700
+ this.metering = new MeteringResource(this.client);
701
+ }
702
+ };
703
+ // Annotate the CommonJS export names for ESM import in node:
704
+ 0 && (module.exports = {
705
+ Pulse,
706
+ PulseApiError,
707
+ PulseAuthenticationError,
708
+ PulseError,
709
+ PulseRateLimitError,
710
+ mountCheckout,
711
+ verifyWebhookSignature
712
+ });