@payclave/sdk-server 0.1.1 → 0.3.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 CHANGED
@@ -3,14 +3,29 @@ import { createHmac, timingSafeEqual } from 'crypto';
3
3
 
4
4
  // src/index.ts
5
5
  var PAYCLAVE_WEBHOOK_EVENT_TYPES = [
6
+ "invoice.issued",
6
7
  "invoice.paid",
8
+ "invoice.partially_paid",
9
+ "invoice.past_due",
10
+ "invoice.overpaid",
11
+ "invoice.voided",
12
+ "invoice.uncollectible",
13
+ "invoice.refund_recorded",
14
+ "invoice.refund_verified",
15
+ "invoice.refund_failed",
16
+ "invoice.payment_received_after_void",
17
+ "invoice.payment_received_after_uncollectible",
7
18
  "invoice.expired",
19
+ "payment_link.completed",
20
+ "payment_link.expired",
8
21
  "payment.failed",
9
22
  "payment.underpaid",
10
23
  "payment.overpaid"
11
24
  ];
25
+ var PAYCLAVE_RECONCILIATION_SCHEMA_VERSION = "2026-08-29.v1";
12
26
  var PAYCLAVE_API_ERROR_CODES = [
13
27
  "ACCOUNT_SUSPENDED",
28
+ "ACTIVE_MERCHANT_REQUIRED",
14
29
  "API_KEY_FORBIDDEN",
15
30
  "API_KEY_REQUIRED",
16
31
  "AUTH_FORBIDDEN",
@@ -23,6 +38,7 @@ var PAYCLAVE_API_ERROR_CODES = [
23
38
  "GOOGLE_PROFILE_UNAVAILABLE",
24
39
  "GOOGLE_AUTH_STATE_INVALID",
25
40
  "AUTH_PASSWORD_ALREADY_SET",
41
+ "AUTH_PROXY_UNAUTHORIZED",
26
42
  "AUTH_PROVIDER_UNAVAILABLE",
27
43
  "AUTH_REQUIRED",
28
44
  "USE_SOCIAL_LOGIN",
@@ -39,22 +55,73 @@ var PAYCLAVE_API_ERROR_CODES = [
39
55
  "INVALID_WALLET_PAYMENT_ATTEMPT",
40
56
  "INVALID_TX_HASH",
41
57
  "INVALID_WALLET_ADDRESS",
58
+ "MODE_MISMATCH",
59
+ "MEMBERSHIP_REVOKED",
60
+ "MEMBER_ALREADY_EXISTS",
61
+ "MEMBER_LIMIT_REACHED",
62
+ "LAST_OWNER_REQUIRED",
63
+ "INVITATION_ALREADY_PENDING",
64
+ "INVITATION_ALREADY_USED",
65
+ "INVITATION_EMAIL_MISMATCH",
66
+ "INVITATION_EXPIRED",
67
+ "INVITATION_NOT_FOUND",
68
+ "OWNERSHIP_TRANSFER_REQUIRED",
42
69
  "NOT_FOUND",
70
+ "PUBLIC_KEY_FIELD_NOT_ALLOWED",
71
+ "PERMISSION_DENIED",
43
72
  "RATE_LIMIT_EXCEEDED",
73
+ "REAUTH_REQUIRED",
74
+ "STEP_UP_REQUIRED",
44
75
  "REQUEST_ERROR",
76
+ "REQUEST_TOO_LARGE",
45
77
  "SCAN_OR_COPY_UNAVAILABLE",
46
78
  "WALLET_PAYMENTS_UNAVAILABLE",
47
79
  "UNSUPPORTED_DEFAULT_WALLET",
48
80
  "VALIDATION_ERROR",
49
81
  "WEBHOOK_DELIVERY_NOT_FOUND",
82
+ "WEBHOOK_ENDPOINT_DISABLED",
50
83
  "WEBHOOK_ENDPOINT_NOT_FOUND",
51
84
  "WEBHOOK_EVENT_UNSUPPORTED",
85
+ "WEBHOOK_INCIDENT_NOT_FOUND",
52
86
  "WEBHOOK_SIGNATURE_INVALID",
87
+ "SECRET_OVERLAP_ACTIVE",
88
+ "SECRET_OVERLAP_EXPIRED",
53
89
  "CHECKOUT_SESSION_NOT_PAYABLE",
90
+ "EVENT_TYPE_UNSUPPORTED",
91
+ "EVENT_PAYLOAD_TOO_LARGE",
92
+ "JOURNEY_TOKEN_INVALID",
93
+ "EVENT_DUPLICATE",
94
+ "TIMESTAMP_OUT_OF_RANGE",
54
95
  "INVOICE_NOT_FOUND",
55
96
  "INVOICE_STATE_MISMATCH",
56
97
  "INVOICE_TRANSITION_GUARD_FAILED",
57
- "IDEMPOTENCY_KEY_CONFLICT"
98
+ "INVOICE_NOT_EDITABLE",
99
+ "INVOICE_ALREADY_ISSUED",
100
+ "INVOICE_NOT_PAYABLE",
101
+ "INVOICE_PDF_UNAVAILABLE",
102
+ "INVOICE_VERSION_CONFLICT",
103
+ "CURRENCY_MISMATCH",
104
+ "INVALID_TOTAL",
105
+ "CUSTOMER_EMAIL_REQUIRED",
106
+ "IDEMPOTENCY_KEY_CONFLICT",
107
+ "PAYMENT_LINK_NOT_FOUND",
108
+ "PAYMENT_LINK_VERSION_CONFLICT",
109
+ "LINK_INACTIVE",
110
+ "LINK_EXPIRED",
111
+ "LINK_ALREADY_USED",
112
+ "LINK_RESERVED",
113
+ "AMOUNT_OUT_OF_RANGE",
114
+ "FIELD_REQUIRED",
115
+ "FEATURE_UNAVAILABLE",
116
+ "MODE_UNAVAILABLE",
117
+ "CONFIG_CHANGED",
118
+ "RATE_LIMITED",
119
+ "EXPORT_RANGE_TOO_LARGE",
120
+ "EXPORT_NOT_READY",
121
+ "EXPORT_EXPIRED",
122
+ "EXPORT_CANCELLED",
123
+ "EXPORT_SCHEMA_UNSUPPORTED",
124
+ "EXPORT_TOO_LARGE_FOR_SYNC"
58
125
  ];
59
126
  var PAYCLAVE_SERVER_SDK_ERROR_CODES = [
60
127
  "INVALID_SECRET_KEY",
@@ -113,13 +180,15 @@ var PayclaveError = class extends Error {
113
180
  }
114
181
  };
115
182
  var PAYCLAVE_SERVER_SDK_NAME = "payclave-sdk-server";
116
- var PAYCLAVE_SERVER_SDK_VERSION = "0.1.0";
183
+ var PAYCLAVE_SERVER_SDK_VERSION = "0.3.0";
117
184
  var defaultApiBaseUrl = "https://api.payclave.com";
118
185
  var defaultFetcher = (input, init) => fetch(input, init);
119
186
  var secretKeyPattern = /^sk_(test|live)_[A-Za-z0-9_-]+$/;
120
187
  var amountPattern = /^(0|[1-9]\d*)(\.\d{1,6})?$/;
121
188
  var webhookUrlMessage = "Webhook URL must be a valid http or https URL.";
189
+ var webhookRawBodyGuideUrl = "https://www.payclave.com/developers/docs#webhooks";
122
190
  var defaultWebhookToleranceSeconds = 300;
191
+ var defaultTimeoutMs = 3e4;
123
192
  var minExpiryMinutes = 5;
124
193
  var maxExpiryMinutes = 24 * 60;
125
194
  var supportedWebhookEventTypes = new Set(PAYCLAVE_WEBHOOK_EVENT_TYPES);
@@ -132,6 +201,8 @@ var isPlainObject = (value) => {
132
201
  return prototype === Object.prototype || prototype === null;
133
202
  };
134
203
  var isStringOrNull = (value) => typeof value === "string" || value === null;
204
+ var isOptionalString = (value) => value === void 0 || typeof value === "string";
205
+ var isOptionalStringOrNull = (value) => value === void 0 || isStringOrNull(value);
135
206
  var isMetadata = (value) => isPlainObject(value);
136
207
  var isStringArray = (value) => Array.isArray(value) && value.every((item) => typeof item === "string");
137
208
  var joinUrl = (baseUrl, path) => `${baseUrl.replace(/\/+$/, "")}${path}`;
@@ -226,6 +297,79 @@ var assertOptionalMetadata = (metadata) => {
226
297
  });
227
298
  }
228
299
  };
300
+ var assertInvoiceDraftFields = (input) => {
301
+ if (!isPlainObject(input.customer) || !Array.isArray(input.lines) || input.lines.length < 1 || input.lines.length > 100) {
302
+ throw new PayclaveError({
303
+ message: "Invoice drafts require a customer object and 1 to 100 lines.",
304
+ code: "INVALID_REQUEST_BODY",
305
+ status: 0
306
+ });
307
+ }
308
+ assertOptionalMetadata(input.metadata);
309
+ assertOptionalExpiry(input.checkoutExpiresInMinutes);
310
+ };
311
+ var assertInvoiceVersion = (version) => {
312
+ if (typeof version !== "number" || !Number.isInteger(version) || version < 1) {
313
+ throw new PayclaveError({
314
+ message: "Invoice version must be a positive integer.",
315
+ code: "INVALID_REQUEST_BODY",
316
+ status: 0
317
+ });
318
+ }
319
+ };
320
+ var assertPaymentLinkFields = (input) => {
321
+ if (!isPlainObject(input) || typeof input.title !== "string" || input.title.trim() === "" || input.mode !== void 0 && input.mode !== "test" && input.mode !== "live" || input.amountType !== "fixed" && input.amountType !== "customer_entered" || input.usageType !== void 0 && input.usageType !== "single_use" && input.usageType !== "reusable" || input.currencyCode !== void 0 && input.currencyCode !== "USDC" && input.currencyCode !== "USDT") {
322
+ throw new PayclaveError({
323
+ message: "Payment link fields are invalid.",
324
+ code: "INVALID_REQUEST_BODY",
325
+ status: 0
326
+ });
327
+ }
328
+ if (input.amountType === "fixed") {
329
+ assertAmount(input.amount);
330
+ } else {
331
+ assertAmount(input.minimumAmount);
332
+ if (input.maximumAmount !== void 0 && input.maximumAmount !== "") {
333
+ assertAmount(input.maximumAmount);
334
+ }
335
+ }
336
+ if (input.collect !== void 0 && (!isPlainObject(input.collect) || Object.values(input.collect).some((value) => typeof value !== "boolean"))) {
337
+ throw new PayclaveError({
338
+ message: "Payment link customer fields must be booleans.",
339
+ code: "INVALID_REQUEST_BODY",
340
+ status: 0
341
+ });
342
+ }
343
+ assertOptionalMetadata(input.metadata);
344
+ };
345
+ var assertPaymentLinkVersion = (version) => {
346
+ if (typeof version !== "number" || !Number.isInteger(version) || version < 1) {
347
+ throw new PayclaveError({
348
+ message: "Payment link version must be a positive integer.",
349
+ code: "INVALID_REQUEST_BODY",
350
+ status: 0
351
+ });
352
+ }
353
+ };
354
+ var paymentLinkBody = (input) => compact({
355
+ mode: input.mode,
356
+ title: input.title,
357
+ description: input.description,
358
+ amountType: input.amountType,
359
+ amount: input.amount,
360
+ minimumAmount: input.minimumAmount,
361
+ maximumAmount: input.maximumAmount,
362
+ currencyCode: input.currencyCode,
363
+ usageType: input.usageType,
364
+ activeAt: input.activeAt,
365
+ expiresAt: input.expiresAt,
366
+ collect: input.collect,
367
+ referencePrefix: input.referencePrefix,
368
+ successUrl: input.successUrl,
369
+ cancelUrl: input.cancelUrl,
370
+ successMessage: input.successMessage,
371
+ metadata: input.metadata
372
+ });
229
373
  var assertIdempotencyKey = (key) => {
230
374
  if (typeof key !== "string" || key.length === 0) {
231
375
  throw new PayclaveError({
@@ -311,6 +455,15 @@ var assertPositiveIntegerLimit = (limit) => {
311
455
  });
312
456
  }
313
457
  };
458
+ var assertReconciliationFormat = (format) => {
459
+ if (format !== "csv" && format !== "json") {
460
+ throw new PayclaveError({
461
+ message: "Reconciliation export format must be csv or json.",
462
+ code: "INVALID_REQUEST_BODY",
463
+ status: 0
464
+ });
465
+ }
466
+ };
314
467
  var serializeBody = (body) => {
315
468
  try {
316
469
  return JSON.stringify(body);
@@ -363,6 +516,98 @@ var parseResponse = async (response, guard) => {
363
516
  }
364
517
  return body.data;
365
518
  };
519
+ var parseInvoicePDFResponse = async (response) => {
520
+ const fallbackRequestId = response.headers.get("X-Request-ID");
521
+ if (!response.ok) {
522
+ const body = await response.json().catch(() => null);
523
+ if (isFailureResponse(body)) {
524
+ throw new PayclaveError({
525
+ message: body.error.message,
526
+ code: body.error.code,
527
+ status: response.status,
528
+ requestId: body.meta?.requestId ?? fallbackRequestId,
529
+ details: body.error.details
530
+ });
531
+ }
532
+ throw new PayclaveError({
533
+ message: "Payclave returned an invalid response.",
534
+ code: "INVALID_RESPONSE",
535
+ status: response.status,
536
+ requestId: fallbackRequestId
537
+ });
538
+ }
539
+ if (response.headers.get("content-type")?.split(";", 1)[0].trim() !== "application/pdf") {
540
+ throw new PayclaveError({
541
+ message: "Payclave returned an invalid invoice PDF response.",
542
+ code: "INVALID_RESPONSE",
543
+ status: response.status,
544
+ requestId: fallbackRequestId
545
+ });
546
+ }
547
+ const bytes = new Uint8Array(await response.arrayBuffer());
548
+ if (bytes.length < 5 || String.fromCharCode(...bytes.slice(0, 5)) !== "%PDF-") {
549
+ throw new PayclaveError({
550
+ message: "Payclave returned invalid invoice PDF bytes.",
551
+ code: "INVALID_RESPONSE",
552
+ status: response.status,
553
+ requestId: fallbackRequestId
554
+ });
555
+ }
556
+ const disposition = response.headers.get("content-disposition") ?? "";
557
+ const filenameMatch = disposition.match(
558
+ /filename=(?:"([^"\r\n/\\]+\.pdf)"|([^;\s\r\n/\\]+\.pdf))/i
559
+ );
560
+ const filename = filenameMatch?.[1] ?? filenameMatch?.[2] ?? "payclave-invoice.pdf";
561
+ return {
562
+ bytes,
563
+ contentType: "application/pdf",
564
+ filename,
565
+ requestId: fallbackRequestId
566
+ };
567
+ };
568
+ var parseReconciliationDownloadResponse = async (response) => {
569
+ const requestId = response.headers.get("X-Request-ID");
570
+ if (!response.ok) {
571
+ const body = await response.json().catch(() => null);
572
+ if (isFailureResponse(body)) {
573
+ throw new PayclaveError({
574
+ message: body.error.message,
575
+ code: body.error.code,
576
+ status: response.status,
577
+ requestId: body.meta?.requestId ?? requestId,
578
+ details: body.error.details
579
+ });
580
+ }
581
+ throw new PayclaveError({
582
+ message: "Payclave returned an invalid response.",
583
+ code: "INVALID_RESPONSE",
584
+ status: response.status,
585
+ requestId
586
+ });
587
+ }
588
+ if (response.headers.get("content-type")?.split(";", 1)[0].trim() !== "application/zip" || !response.body) {
589
+ throw new PayclaveError({
590
+ message: "Payclave returned an invalid reconciliation archive response.",
591
+ code: "INVALID_RESPONSE",
592
+ status: response.status,
593
+ requestId
594
+ });
595
+ }
596
+ const disposition = response.headers.get("content-disposition") ?? "";
597
+ const filenameMatch = disposition.match(
598
+ /filename=(?:"([^"\r\n/\\]+\.zip)"|([^;\s\r\n/\\]+\.zip))/i
599
+ );
600
+ const rawSize = response.headers.get("content-length");
601
+ const parsedSize = rawSize === null ? Number.NaN : Number(rawSize);
602
+ return {
603
+ stream: response.body,
604
+ contentType: "application/zip",
605
+ filename: filenameMatch?.[1] ?? filenameMatch?.[2] ?? "payclave-reconciliation.zip",
606
+ byteSize: Number.isSafeInteger(parsedSize) && parsedSize >= 0 ? parsedSize : null,
607
+ sha256: response.headers.get("X-Payclave-Content-SHA256"),
608
+ requestId
609
+ };
610
+ };
366
611
  var runFetch = async ({
367
612
  fetcher,
368
613
  url,
@@ -436,32 +681,45 @@ var isCreatedCheckoutSession = (value) => {
436
681
  if (!isRecord(value)) {
437
682
  return false;
438
683
  }
439
- return typeof value.id === "string" && typeof value.checkoutId === "string" && value.object === "checkout_session" && typeof value.mode === "string" && value.status === "pending" && typeof value.invoiceId === "string" && typeof value.invoiceNumber === "string" && typeof value.amountDue === "string" && typeof value.amountReceived === "string" && typeof value.currencyCode === "string" && typeof value.chainId === "number" && typeof value.tokenSymbol === "string" && typeof value.tokenContract === "string" && typeof value.settlementWalletAddress === "string" && isStringOrNull(value.externalReference) && isStringOrNull(value.customerEmail) && isMetadata(value.metadata) && typeof value.checkoutUrl === "string" && typeof value.expiresAt === "string" && typeof value.createdAt === "string";
684
+ return typeof value.id === "string" && typeof value.checkoutId === "string" && value.object === "checkout_session" && typeof value.mode === "string" && isOptionalString(value.sourceType) && value.status === "pending" && typeof value.collectionState === "string" && typeof value.invoiceId === "string" && typeof value.invoiceNumber === "string" && typeof value.amountDue === "string" && typeof value.amountReceived === "string" && typeof value.total === "string" && typeof value.customerAmountPaid === "string" && typeof value.customerAmountRemaining === "string" && typeof value.currencyCode === "string" && typeof value.chainId === "number" && typeof value.tokenSymbol === "string" && typeof value.tokenContract === "string" && typeof value.settlementWalletAddress === "string" && isStringOrNull(value.externalReference) && isStringOrNull(value.customerEmail) && isMetadata(value.metadata) && typeof value.checkoutUrl === "string" && typeof value.expiresAt === "string" && typeof value.createdAt === "string";
440
685
  };
441
686
  var isCheckoutSession = (value) => {
442
687
  if (!isRecord(value)) {
443
688
  return false;
444
689
  }
445
- return typeof value.id === "string" && typeof value.checkoutId === "string" && value.object === "checkout_session" && typeof value.mode === "string" && typeof value.status === "string" && isStringOrNull(value.invoiceId) && isStringOrNull(value.invoiceNumber) && typeof value.amountDue === "string" && typeof value.amountReceived === "string" && typeof value.currencyCode === "string" && typeof value.chainId === "number" && typeof value.tokenSymbol === "string" && typeof value.tokenContract === "string" && typeof value.settlementWalletAddress === "string" && isStringOrNull(value.externalReference) && isStringOrNull(value.customerEmail) && isMetadata(value.metadata) && typeof value.checkoutUrl === "string" && typeof value.expiresAt === "string" && isStringOrNull(value.completedAt) && typeof value.createdAt === "string";
690
+ return typeof value.id === "string" && typeof value.checkoutId === "string" && value.object === "checkout_session" && typeof value.mode === "string" && isOptionalString(value.sourceType) && typeof value.status === "string" && typeof value.collectionState === "string" && isStringOrNull(value.invoiceId) && isStringOrNull(value.invoiceNumber) && typeof value.amountDue === "string" && typeof value.amountReceived === "string" && typeof value.total === "string" && typeof value.customerAmountPaid === "string" && typeof value.customerAmountRemaining === "string" && typeof value.currencyCode === "string" && typeof value.chainId === "number" && typeof value.tokenSymbol === "string" && typeof value.tokenContract === "string" && typeof value.settlementWalletAddress === "string" && isStringOrNull(value.externalReference) && isStringOrNull(value.customerEmail) && isMetadata(value.metadata) && typeof value.checkoutUrl === "string" && typeof value.expiresAt === "string" && isStringOrNull(value.completedAt) && typeof value.createdAt === "string";
446
691
  };
447
692
  var isInvoice = (value) => {
448
693
  if (!isRecord(value)) {
449
694
  return false;
450
695
  }
451
- return typeof value.id === "string" && typeof value.invoiceNumber === "string" && value.object === "invoice" && typeof value.mode === "string" && typeof value.status === "string" && typeof value.amountDue === "string" && typeof value.amountReceived === "string" && typeof value.platformFee === "string" && typeof value.netAmount === "string" && typeof value.currencyCode === "string" && typeof value.chainId === "number" && typeof value.tokenContract === "string" && typeof value.settlementWalletAddress === "string" && isStringOrNull(value.externalReference) && isMetadata(value.metadata) && typeof value.expiresAt === "string" && isStringOrNull(value.paidAt) && isStringOrNull(value.cancelledAt) && typeof value.createdAt === "string";
696
+ return typeof value.id === "string" && isStringOrNull(value.invoiceNumber) && value.object === "invoice" && typeof value.mode === "string" && typeof value.status === "string" && typeof value.collectionState === "string" && typeof value.subtotal === "string" && typeof value.discountTotal === "string" && typeof value.taxTotal === "string" && typeof value.total === "string" && typeof value.customerAmountPaid === "string" && typeof value.customerAmountRemaining === "string" && typeof value.expectedMerchantSettlement === "string" && typeof value.merchantAmountSettled === "string" && typeof value.overpaymentAmount === "string" && typeof value.migrationState === "string" && typeof value.amountDue === "string" && typeof value.amountReceived === "string" && typeof value.platformFee === "string" && typeof value.netAmount === "string" && typeof value.currencyCode === "string" && typeof value.chainId === "number" && typeof value.tokenContract === "string" && typeof value.settlementWalletAddress === "string" && isStringOrNull(value.externalReference) && isMetadata(value.metadata) && isStringOrNull(value.expiresAt) && isStringOrNull(value.paidAt) && isStringOrNull(value.cancelledAt) && isOptionalStringOrNull(value.voidedAt) && isOptionalStringOrNull(value.uncollectibleAt) && typeof value.createdAt === "string" && isOptionalString(value.internalId) && isOptionalString(value.sourceType) && (value.version === void 0 || typeof value.version === "number") && isOptionalString(value.calculationVersion) && (value.customer === void 0 || isRecord(value.customer)) && (value.lines === void 0 || Array.isArray(value.lines)) && (value.discount === void 0 || value.discount === null || isRecord(value.discount)) && (value.taxes === void 0 || Array.isArray(value.taxes)) && isOptionalStringOrNull(value.dueAt) && isOptionalStringOrNull(value.issuedAt) && isOptionalStringOrNull(value.publicToken) && (value.hostedInvoiceEnabled === void 0 || typeof value.hostedInvoiceEnabled === "boolean") && isOptionalStringOrNull(value.hostedInvoiceUrl) && (value.checkoutSessions === void 0 || Array.isArray(value.checkoutSessions)) && (value.payments === void 0 || Array.isArray(value.payments)) && (value.adjustments === void 0 || Array.isArray(value.adjustments)) && (value.deliveries === void 0 || Array.isArray(value.deliveries)) && (value.reminderSchedule === void 0 || isRecord(value.reminderSchedule)) && isOptionalStringOrNull(value.remindersPausedAt) && isOptionalStringOrNull(value.lastReminderAt) && isOptionalStringOrNull(value.nextReminderAt) && isOptionalStringOrNull(value.lastSentAt) && isOptionalString(value.updatedAt) && isOptionalStringOrNull(value.lastActivityAt);
452
697
  };
698
+ var isInvoiceCheckoutSessionCreated = (value) => isRecord(value) && typeof value.invoiceId === "string" && typeof value.invoiceNumber === "string" && typeof value.checkoutSessionId === "string" && typeof value.checkoutUrl === "string" && typeof value.amountDue === "string" && typeof value.currencyCode === "string" && typeof value.expiresAt === "string";
699
+ var isRefundReferenceResult = (value) => isRecord(value) && isRecord(value.adjustment) && isInvoice(value.invoice);
700
+ var isRefundDecision = (value) => isRecord(value) && typeof value.allowed === "boolean" && typeof value.requiresApproval === "boolean" && typeof value.refundableAmount === "string" && typeof value.overpaidAmount === "string" && Array.isArray(value.warnings);
701
+ var isInvoiceList = (value) => isRecord(value) && Array.isArray(value.items) && value.items.every(isInvoice) && typeof value.hasMore === "boolean" && isStringOrNull(value.nextCursor);
702
+ var isPaymentLinkCollect = (value) => isRecord(value) && typeof value.email === "boolean" && typeof value.name === "boolean" && typeof value.reference === "boolean";
703
+ var isPaymentLink = (value) => isRecord(value) && typeof value.id === "string" && value.object === "payment_link" && typeof value.publicId === "string" && typeof value.url === "string" && typeof value.merchantId === "string" && typeof value.mode === "string" && typeof value.status === "string" && typeof value.version === "number" && typeof value.title === "string" && typeof value.description === "string" && (value.amountType === "fixed" || value.amountType === "customer_entered") && isStringOrNull(value.amount) && isStringOrNull(value.minimumAmount) && isStringOrNull(value.maximumAmount) && typeof value.currencyCode === "string" && typeof value.chainId === "number" && typeof value.tokenContract === "string" && (value.usageType === "single_use" || value.usageType === "reusable") && typeof value.completedPayments === "number" && typeof value.startedCheckouts === "number" && isStringOrNull(value.activeAt) && isStringOrNull(value.expiresAt) && isStringOrNull(value.pausedAt) && isStringOrNull(value.archivedAt) && isPaymentLinkCollect(value.collect) && typeof value.referencePrefix === "string" && isStringOrNull(value.successUrl) && isStringOrNull(value.cancelUrl) && typeof value.successMessage === "string" && isMetadata(value.metadata) && isStringOrNull(value.reservationInvoiceId) && isStringOrNull(value.reservedAt) && typeof value.createdAt === "string" && typeof value.updatedAt === "string" && isStringOrNull(value.lastCheckoutCreatedAt);
704
+ var isPaymentLinkList = (value) => isRecord(value) && Array.isArray(value.items) && value.items.every(isPaymentLink) && typeof value.hasMore === "boolean" && isStringOrNull(value.nextCursor);
705
+ var isPaymentLinkPayments = (value) => isRecord(value) && Array.isArray(value.items) && value.items.every(isInvoice);
453
706
  var isPayment = (value) => {
454
707
  if (!isRecord(value)) {
455
708
  return false;
456
709
  }
457
- return typeof value.id === "string" && value.object === "payment" && typeof value.invoiceId === "string" && typeof value.invoiceNumber === "string" && isStringOrNull(value.transactionId) && typeof value.mode === "string" && typeof value.status === "string" && typeof value.amountExpected === "string" && typeof value.amountReceived === "string" && typeof value.platformFee === "string" && typeof value.netAmount === "string" && typeof value.chainId === "number" && typeof value.settlementWalletAddress === "string" && isStringOrNull(value.failureReason) && isStringOrNull(value.confirmedAt) && typeof value.createdAt === "string";
710
+ return typeof value.id === "string" && value.object === "payment" && typeof value.invoiceId === "string" && typeof value.invoiceNumber === "string" && isStringOrNull(value.transactionId) && typeof value.mode === "string" && typeof value.status === "string" && typeof value.amountExpected === "string" && typeof value.amountReceived === "string" && typeof value.customerAmountTendered === "string" && typeof value.customerAmountCredited === "string" && typeof value.expectedMerchantSettlement === "string" && typeof value.merchantAmountSettled === "string" && typeof value.platformFeeExpected === "string" && typeof value.platformFeeCollected === "string" && typeof value.payerWalletAddress === "string" && typeof value.payerWalletEvidence === "string" && typeof value.creditEvidenceType === "string" && typeof value.migrationState === "string" && typeof value.platformFee === "string" && typeof value.netAmount === "string" && typeof value.chainId === "number" && typeof value.settlementWalletAddress === "string" && isStringOrNull(value.failureReason) && isStringOrNull(value.confirmedAt) && typeof value.createdAt === "string";
458
711
  };
459
712
  var isWebhookEndpoint = (value) => {
460
713
  if (!isRecord(value)) {
461
714
  return false;
462
715
  }
463
- return typeof value.id === "string" && value.object === "webhook_endpoint" && typeof value.mode === "string" && typeof value.url === "string" && typeof value.enabled === "boolean" && isStringArray(value.eventTypes) && typeof value.signingSecret === "string" && typeof value.createdAt === "string";
716
+ return typeof value.id === "string" && value.object === "webhook_endpoint" && typeof value.mode === "string" && typeof value.url === "string" && typeof value.enabled === "boolean" && isStringArray(value.eventTypes) && (value.signingSecret === void 0 || typeof value.signingSecret === "string") && (value.copyRequired === void 0 || typeof value.copyRequired === "boolean") && typeof value.currentSecretVersion === "number" && Array.isArray(value.secretVersions) && value.secretVersions.every(isWebhookSecretVersion) && isRecord(value.secretOverlap) && typeof value.secretOverlap.status === "string" && isStringOrNull(value.secretOverlap.expiresAt) && (typeof value.secretOverlap.previousVersion === "number" || value.secretOverlap.previousVersion === null) && typeof value.createdAt === "string" && typeof value.updatedAt === "string";
464
717
  };
718
+ var isWebhookSecretVersion = (value) => isRecord(value) && typeof value.version === "number" && typeof value.createdAt === "string" && typeof value.activatesAt === "string" && isStringOrNull(value.expiresAt) && isStringOrNull(value.revokedAt) && isStringOrNull(value.testedAt);
719
+ var isWebhookEndpointArray = (value) => Array.isArray(value) && value.every(isWebhookEndpoint);
720
+ var isWebhookEndpointArchive = (value) => isRecord(value) && typeof value.id === "string" && value.object === "webhook_endpoint" && value.archived === true;
721
+ var isWebhookIncident = (value) => isRecord(value) && typeof value.id === "string" && value.object === "webhook_incident" && typeof value.endpointId === "string" && typeof value.mode === "string" && typeof value.status === "string" && typeof value.reasonFamily === "string" && typeof value.failureCount === "number" && typeof value.affectedDeliveryCount === "number" && isStringArray(value.affectedDeliveryIds) && typeof value.firstFailedAt === "string" && typeof value.lastFailedAt === "string" && typeof value.openedAt === "string" && isStringOrNull(value.resolvedAt) && typeof value.lastDeliveryId === "string" && typeof value.lastAttemptId === "string" && typeof value.createdAt === "string" && typeof value.updatedAt === "string";
722
+ var isWebhookIncidentArray = (value) => Array.isArray(value) && value.every(isWebhookIncident);
465
723
  var isWebhookEvent = (value) => {
466
724
  if (!isRecord(value)) {
467
725
  return false;
@@ -472,15 +730,22 @@ var isWebhookDeliveryAttemptSummary = (value) => {
472
730
  if (!isRecord(value)) {
473
731
  return false;
474
732
  }
475
- return (typeof value.responseStatusCode === "number" || value.responseStatusCode === null) && isStringOrNull(value.errorMessage) && typeof value.attemptedAt === "string";
733
+ return (typeof value.responseStatusCode === "number" || value.responseStatusCode === null) && isStringOrNull(value.errorMessage) && (value.errorCategory === void 0 || isStringOrNull(value.errorCategory)) && typeof value.attemptedAt === "string";
476
734
  };
735
+ var isWebhookDeliveryAttempt = (value) => isRecord(value) && typeof value.id === "string" && typeof value.attemptNumber === "number" && (typeof value.responseStatusCode === "number" || value.responseStatusCode === null) && isStringOrNull(value.responseBody) && typeof value.responseBodyTruncated === "boolean" && isStringOrNull(value.errorMessage) && (value.errorCategory === void 0 || isStringOrNull(value.errorCategory)) && (value.responseHeaders === void 0 || value.responseHeaders === null || isRecord(value.responseHeaders)) && (value.requestHeaders === void 0 || value.requestHeaders === null || isRecord(value.requestHeaders)) && (value.destinationHost === void 0 || typeof value.destinationHost === "string") && (value.sanitizedAt === void 0 || typeof value.sanitizedAt === "string") && typeof value.attemptedAt === "string" && typeof value.startedAt === "string" && typeof value.completedAt === "string" && typeof value.durationMs === "number";
477
736
  var isWebhookDelivery = (value) => {
478
737
  if (!isRecord(value)) {
479
738
  return false;
480
739
  }
481
- return typeof value.id === "string" && value.object === "webhook_delivery" && typeof value.endpointId === "string" && isStringOrNull(value.invoiceId) && typeof value.eventType === "string" && typeof value.status === "string" && typeof value.idempotencyKey === "string" && isWebhookEvent(value.payload) && typeof value.nextAttemptAt === "string" && isStringOrNull(value.deliveredAt) && typeof value.attemptCount === "number" && (value.latestAttempt === null || isWebhookDeliveryAttemptSummary(value.latestAttempt)) && typeof value.createdAt === "string";
740
+ return typeof value.id === "string" && value.object === "webhook_delivery" && typeof value.endpointId === "string" && isStringOrNull(value.invoiceId) && typeof value.eventId === "string" && typeof value.eventType === "string" && typeof value.status === "string" && typeof value.idempotencyKey === "string" && isWebhookEvent(value.payload) && typeof value.nextAttemptAt === "string" && isStringOrNull(value.deliveredAt) && typeof value.attemptCount === "number" && (value.latestErrorCategory === void 0 || isStringOrNull(value.latestErrorCategory)) && (value.latestAttempt === null || isWebhookDeliveryAttemptSummary(value.latestAttempt)) && isStringOrNull(value.replayOfDeliveryId) && isStringOrNull(value.replayRootDeliveryId) && isStringOrNull(value.replayedBy) && isStringOrNull(value.replayedAt) && typeof value.createdAt === "string";
482
741
  };
742
+ var isWebhookDeliveryDetail = (value) => isWebhookDelivery(value) && Array.isArray(value.attempts) && value.attempts.every(isWebhookDeliveryAttempt);
743
+ var isWebhookDeliveryAttemptArray = (value) => Array.isArray(value) && value.every(isWebhookDeliveryAttempt);
483
744
  var isWebhookDeliveryArray = (value) => Array.isArray(value) && value.every(isWebhookDelivery);
745
+ var isReconciliationSchema = (value) => isRecord(value) && typeof value.schemaVersion === "string" && Array.isArray(value.formats) && Array.isArray(value.dateBases) && typeof value.maximumRangeDays === "number" && typeof value.rangeEnd === "string" && typeof value.retention === "string" && Array.isArray(value.files) && Array.isArray(value.stateRules);
746
+ var isReconciliationSummary = (value) => isRecord(value) && typeof value.schemaVersion === "string" && typeof value.dateBasis === "string" && typeof value.from === "string" && typeof value.to === "string" && typeof value.cutoffAt === "string" && typeof value.timezone === "string" && isRecord(value.rowCounts) && Array.isArray(value.summaryByToken) && Array.isArray(value.exceptions) && isStringArray(value.warnings);
747
+ var isReconciliationExport = (value) => isRecord(value) && typeof value.id === "string" && typeof value.merchantId === "string" && typeof value.mode === "string" && typeof value.status === "string" && typeof value.format === "string" && typeof value.schemaVersion === "string" && isRecord(value.filters) && typeof value.filters.from === "string" && typeof value.filters.to === "string" && typeof value.dateBasis === "string" && typeof value.timezone === "string" && typeof value.requestedBy === "string" && typeof value.requestedAt === "string" && typeof value.attempts === "number" && typeof value.includePII === "boolean" && typeof value.createdAt === "string" && typeof value.updatedAt === "string";
748
+ var isReconciliationExportList = (value) => isRecord(value) && Array.isArray(value.items) && value.items.every(isReconciliationExport) && typeof value.hasMore === "boolean" && (value.nextCursor === void 0 || typeof value.nextCursor === "string");
484
749
  var normalizePayloadBytes = (payload) => {
485
750
  if (typeof payload === "string") {
486
751
  return Buffer.from(payload, "utf8");
@@ -618,9 +883,10 @@ function assertPayclaveWebhookSignature({
618
883
  (candidate) => timingSafeHexEqual(candidate, expected)
619
884
  )) {
620
885
  throw new PayclaveError({
621
- message: "Payclave webhook signature is invalid.",
886
+ message: `Payclave webhook signature is invalid. Verify the signature against the exact raw request body before parsing it. See ${webhookRawBodyGuideUrl}`,
622
887
  code: "WEBHOOK_SIGNATURE_INVALID",
623
- status: 0
888
+ status: 0,
889
+ details: { documentationUrl: webhookRawBodyGuideUrl }
624
890
  });
625
891
  }
626
892
  }
@@ -658,7 +924,7 @@ function createPayclaveServerClient({
658
924
  secretKey,
659
925
  apiBaseUrl = defaultApiBaseUrl,
660
926
  fetcher = defaultFetcher,
661
- timeoutMs
927
+ timeoutMs = defaultTimeoutMs
662
928
  }) {
663
929
  assertSecretKey(secretKey);
664
930
  assertTimeoutMs(timeoutMs);
@@ -744,6 +1010,40 @@ function createPayclaveServerClient({
744
1010
  guard: isInvoice
745
1011
  });
746
1012
  };
1013
+ const createInvoiceDraft = (input) => {
1014
+ assertInvoiceDraftFields(input);
1015
+ const { signal, idempotencyKey, ...body } = input;
1016
+ return request({
1017
+ method: "POST",
1018
+ path: "/v1/invoices",
1019
+ body,
1020
+ idempotencyKey,
1021
+ signal,
1022
+ guard: isInvoice
1023
+ });
1024
+ };
1025
+ const listInvoices = (input = {}) => {
1026
+ const query = new URLSearchParams();
1027
+ if (input.limit !== void 0) {
1028
+ assertPositiveIntegerLimit(input.limit);
1029
+ query.set("limit", String(input.limit));
1030
+ }
1031
+ if (input.startingAfter !== void 0) {
1032
+ assertIdentifier(input.startingAfter, "Starting invoice id");
1033
+ query.set("startingAfter", input.startingAfter);
1034
+ }
1035
+ if (input.collectionState !== void 0) {
1036
+ assertIdentifier(input.collectionState, "Invoice collection state");
1037
+ query.set("collectionState", input.collectionState);
1038
+ }
1039
+ const suffix = query.size > 0 ? `?${query.toString()}` : "";
1040
+ return request({
1041
+ method: "GET",
1042
+ path: `/v1/invoices${suffix}`,
1043
+ signal: input.signal,
1044
+ guard: isInvoiceList
1045
+ });
1046
+ };
747
1047
  const getInvoice = (id, options = {}) => {
748
1048
  assertIdentifier(id, "Invoice id");
749
1049
  return request({
@@ -753,6 +1053,243 @@ function createPayclaveServerClient({
753
1053
  guard: isInvoice
754
1054
  });
755
1055
  };
1056
+ const downloadInvoicePDF = async (id, options = {}) => {
1057
+ assertIdentifier(id, "Invoice id");
1058
+ const response = await runFetch({
1059
+ fetcher,
1060
+ url: joinUrl(
1061
+ normalizedApiBaseUrl,
1062
+ `/v1/invoices/${encodePathSegment(id)}/pdf`
1063
+ ),
1064
+ init: {
1065
+ method: "GET",
1066
+ headers: {
1067
+ Accept: "application/pdf",
1068
+ Authorization: `Bearer ${secretKey}`,
1069
+ "X-Payclave-Client": buildClientHeader()
1070
+ }
1071
+ },
1072
+ externalSignal: options.signal,
1073
+ timeoutMs
1074
+ });
1075
+ return parseInvoicePDFResponse(response);
1076
+ };
1077
+ const updateInvoiceDraft = (id, input) => {
1078
+ assertIdentifier(id, "Invoice id");
1079
+ assertInvoiceDraftFields(input);
1080
+ assertInvoiceVersion(input.version);
1081
+ const { signal, idempotencyKey, ...body } = input;
1082
+ return request({
1083
+ method: "PATCH",
1084
+ path: `/v1/invoices/${encodePathSegment(id)}`,
1085
+ body,
1086
+ idempotencyKey,
1087
+ signal,
1088
+ guard: isInvoice
1089
+ });
1090
+ };
1091
+ const issueInvoice = (id, input) => {
1092
+ assertIdentifier(id, "Invoice id");
1093
+ assertInvoiceVersion(input.version);
1094
+ return request({
1095
+ method: "POST",
1096
+ path: `/v1/invoices/${encodePathSegment(id)}/issue`,
1097
+ body: { version: input.version, send: input.send },
1098
+ idempotencyKey: input.idempotencyKey,
1099
+ signal: input.signal,
1100
+ guard: isInvoice
1101
+ });
1102
+ };
1103
+ const createInvoiceCheckoutSession = (id, input = {}) => {
1104
+ assertIdentifier(id, "Invoice id");
1105
+ return request({
1106
+ method: "POST",
1107
+ path: `/v1/invoices/${encodePathSegment(id)}/checkout-sessions`,
1108
+ idempotencyKey: input.idempotencyKey,
1109
+ signal: input.signal,
1110
+ guard: isInvoiceCheckoutSessionCreated
1111
+ });
1112
+ };
1113
+ const sendInvoice = (id, input = {}) => {
1114
+ assertIdentifier(id, "Invoice id");
1115
+ return request({
1116
+ method: "POST",
1117
+ path: `/v1/invoices/${encodePathSegment(id)}/send`,
1118
+ idempotencyKey: input.idempotencyKey,
1119
+ signal: input.signal,
1120
+ guard: isInvoice
1121
+ });
1122
+ };
1123
+ const remindInvoice = (id, input = {}) => {
1124
+ assertIdentifier(id, "Invoice id");
1125
+ return request({
1126
+ method: "POST",
1127
+ path: `/v1/invoices/${encodePathSegment(id)}/remind`,
1128
+ idempotencyKey: input.idempotencyKey,
1129
+ signal: input.signal,
1130
+ guard: isInvoice
1131
+ });
1132
+ };
1133
+ const invoiceAction = (id, path, input) => {
1134
+ assertIdentifier(id, "Invoice id");
1135
+ return request({
1136
+ method: "POST",
1137
+ path: `/v1/invoices/${encodePathSegment(id)}/${path}`,
1138
+ body: compact({ reason: input.reason }),
1139
+ idempotencyKey: input.idempotencyKey,
1140
+ signal: input.signal,
1141
+ guard: isInvoice
1142
+ });
1143
+ };
1144
+ const voidInvoice = (id, input = {}) => invoiceAction(id, "void", input);
1145
+ const voidInvoiceRemaining = (id, input = {}) => invoiceAction(id, "void-remaining", input);
1146
+ const markInvoiceUncollectible = (id, input = {}) => invoiceAction(id, "mark-uncollectible", input);
1147
+ const duplicateInvoice = (id, input = {}) => {
1148
+ assertIdentifier(id, "Invoice id");
1149
+ return request({
1150
+ method: "POST",
1151
+ path: `/v1/invoices/${encodePathSegment(id)}/duplicate`,
1152
+ idempotencyKey: input.idempotencyKey,
1153
+ signal: input.signal,
1154
+ guard: isInvoice
1155
+ });
1156
+ };
1157
+ const recordInvoiceRefundReference = (id, input) => {
1158
+ assertIdentifier(id, "Invoice id");
1159
+ assertIdentifier(input.paymentId, "Payment id");
1160
+ assertAmount(input.amount);
1161
+ const { signal, idempotencyKey, ...body } = input;
1162
+ return request({
1163
+ method: "POST",
1164
+ path: `/v1/invoices/${encodePathSegment(id)}/refund-references`,
1165
+ body,
1166
+ idempotencyKey,
1167
+ signal,
1168
+ guard: isRefundReferenceResult
1169
+ });
1170
+ };
1171
+ const checkInvoiceRefund = (id, input) => {
1172
+ assertIdentifier(id, "Invoice id");
1173
+ assertIdentifier(input.paymentId, "Payment id");
1174
+ assertAmount(input.amount);
1175
+ const { signal, ...body } = input;
1176
+ return request({
1177
+ method: "POST",
1178
+ path: `/v1/invoices/${encodePathSegment(id)}/refund-checks`,
1179
+ body,
1180
+ signal,
1181
+ guard: isRefundDecision
1182
+ });
1183
+ };
1184
+ const createPaymentLink = (input) => {
1185
+ assertPaymentLinkFields(input);
1186
+ return request({
1187
+ method: "POST",
1188
+ path: "/v1/payment-links",
1189
+ body: paymentLinkBody(input),
1190
+ idempotencyKey: input.idempotencyKey,
1191
+ signal: input.signal,
1192
+ guard: isPaymentLink
1193
+ });
1194
+ };
1195
+ const listPaymentLinks = (input = {}) => {
1196
+ const query = new URLSearchParams();
1197
+ if (input.limit !== void 0) {
1198
+ assertPositiveIntegerLimit(input.limit);
1199
+ query.set("limit", String(input.limit));
1200
+ }
1201
+ for (const [name, value] of [
1202
+ ["startingAfter", input.startingAfter],
1203
+ ["status", input.status],
1204
+ ["amountType", input.amountType],
1205
+ ["usageType", input.usageType],
1206
+ ["currencyCode", input.currencyCode],
1207
+ ["search", input.search],
1208
+ ["createdFrom", input.createdFrom],
1209
+ ["createdTo", input.createdTo]
1210
+ ]) {
1211
+ if (value !== void 0) {
1212
+ assertIdentifier(value, name);
1213
+ query.set(name, value);
1214
+ }
1215
+ }
1216
+ const suffix = query.size > 0 ? `?${query.toString()}` : "";
1217
+ return request({
1218
+ method: "GET",
1219
+ path: `/v1/payment-links${suffix}`,
1220
+ signal: input.signal,
1221
+ guard: isPaymentLinkList
1222
+ });
1223
+ };
1224
+ const getPaymentLink = (id, options = {}) => {
1225
+ assertIdentifier(id, "Payment link id");
1226
+ return request({
1227
+ method: "GET",
1228
+ path: `/v1/payment-links/${encodePathSegment(id)}`,
1229
+ signal: options.signal,
1230
+ guard: isPaymentLink
1231
+ });
1232
+ };
1233
+ const updatePaymentLink = (id, input) => {
1234
+ assertIdentifier(id, "Payment link id");
1235
+ assertPaymentLinkFields(input);
1236
+ assertPaymentLinkVersion(input.version);
1237
+ return request({
1238
+ method: "PATCH",
1239
+ path: `/v1/payment-links/${encodePathSegment(id)}`,
1240
+ body: { ...paymentLinkBody(input), version: input.version },
1241
+ idempotencyKey: input.idempotencyKey,
1242
+ signal: input.signal,
1243
+ guard: isPaymentLink
1244
+ });
1245
+ };
1246
+ const paymentLinkAction = (id, action, input = {}) => {
1247
+ assertIdentifier(id, "Payment link id");
1248
+ return request({
1249
+ method: "POST",
1250
+ path: `/v1/payment-links/${encodePathSegment(id)}/${action}`,
1251
+ idempotencyKey: input.idempotencyKey,
1252
+ signal: input.signal,
1253
+ guard: isPaymentLink
1254
+ });
1255
+ };
1256
+ const pausePaymentLink = (id, input = {}) => paymentLinkAction(id, "pause", input);
1257
+ const resumePaymentLink = (id, input = {}) => paymentLinkAction(id, "resume", input);
1258
+ const archivePaymentLink = (id, input = {}) => paymentLinkAction(id, "archive", input);
1259
+ const duplicatePaymentLink = (id, input = {}) => paymentLinkAction(id, "duplicate", input);
1260
+ const releasePaymentLinkReservation = (id, input) => {
1261
+ assertIdentifier(id, "Payment link id");
1262
+ if (input.acknowledgeLatePaymentRisk !== true) {
1263
+ throw new PayclaveError({
1264
+ message: "Payment-link reservation release requires explicit late-payment risk acknowledgement.",
1265
+ code: "INVALID_REQUEST_BODY",
1266
+ status: 0
1267
+ });
1268
+ }
1269
+ return request({
1270
+ method: "POST",
1271
+ path: `/v1/payment-links/${encodePathSegment(id)}/release-reservation`,
1272
+ body: { acknowledgeLatePaymentRisk: input.acknowledgeLatePaymentRisk },
1273
+ idempotencyKey: input.idempotencyKey,
1274
+ signal: input.signal,
1275
+ guard: isPaymentLink
1276
+ });
1277
+ };
1278
+ const listPaymentLinkPayments = (id, input = {}) => {
1279
+ assertIdentifier(id, "Payment link id");
1280
+ const query = new URLSearchParams();
1281
+ if (input.limit !== void 0) {
1282
+ assertPositiveIntegerLimit(input.limit);
1283
+ query.set("limit", String(input.limit));
1284
+ }
1285
+ const suffix = query.size > 0 ? `?${query.toString()}` : "";
1286
+ return request({
1287
+ method: "GET",
1288
+ path: `/v1/payment-links/${encodePathSegment(id)}/payments${suffix}`,
1289
+ signal: input.signal,
1290
+ guard: isPaymentLinkPayments
1291
+ });
1292
+ };
756
1293
  const getPayment = (id, options = {}) => {
757
1294
  assertIdentifier(id, "Payment id");
758
1295
  return request({
@@ -776,6 +1313,75 @@ function createPayclaveServerClient({
776
1313
  guard: isWebhookEndpoint
777
1314
  });
778
1315
  };
1316
+ const listWebhookEndpoints = (options = {}) => request({
1317
+ method: "GET",
1318
+ path: "/v1/webhook-endpoints",
1319
+ signal: options.signal,
1320
+ guard: isWebhookEndpointArray
1321
+ });
1322
+ const getWebhookEndpoint = (id, options = {}) => {
1323
+ assertIdentifier(id, "Webhook endpoint id");
1324
+ return request({
1325
+ method: "GET",
1326
+ path: `/v1/webhook-endpoints/${encodePathSegment(id)}`,
1327
+ signal: options.signal,
1328
+ guard: isWebhookEndpoint
1329
+ });
1330
+ };
1331
+ const updateWebhookEndpoint = (id, input) => {
1332
+ assertIdentifier(id, "Webhook endpoint id");
1333
+ const url = input.url === void 0 ? void 0 : normalizeWebhookUrl(input.url);
1334
+ assertWebhookEventTypes(input.eventTypes);
1335
+ if (input.alertThreshold !== void 0 && (!Number.isInteger(input.alertThreshold) || input.alertThreshold < 2 || input.alertThreshold > 10)) {
1336
+ throw new PayclaveError({
1337
+ message: "Webhook alert threshold must be between 2 and 10.",
1338
+ code: "INVALID_ARGUMENT",
1339
+ status: 0
1340
+ });
1341
+ }
1342
+ const { signal, idempotencyKey, ...rest } = input;
1343
+ const body = { ...rest, ...url === void 0 ? {} : { url } };
1344
+ return request({
1345
+ method: "PATCH",
1346
+ path: `/v1/webhook-endpoints/${encodePathSegment(id)}`,
1347
+ body,
1348
+ idempotencyKey,
1349
+ signal,
1350
+ guard: isWebhookEndpoint
1351
+ });
1352
+ };
1353
+ const archiveWebhookEndpoint = (id, input) => {
1354
+ assertIdentifier(id, "Webhook endpoint id");
1355
+ return request({
1356
+ method: "DELETE",
1357
+ path: `/v1/webhook-endpoints/${encodePathSegment(id)}`,
1358
+ idempotencyKey: input.idempotencyKey,
1359
+ signal: input.signal,
1360
+ guard: isWebhookEndpointArchive
1361
+ });
1362
+ };
1363
+ const rotateWebhookSecret = (id, input) => {
1364
+ assertIdentifier(id, "Webhook endpoint id");
1365
+ return request({
1366
+ method: "POST",
1367
+ path: `/v1/webhook-endpoints/${encodePathSegment(id)}/rotate-secret`,
1368
+ body: {},
1369
+ idempotencyKey: input.idempotencyKey,
1370
+ signal: input.signal,
1371
+ guard: isWebhookEndpoint
1372
+ });
1373
+ };
1374
+ const endWebhookSecretOverlap = (id, input) => {
1375
+ assertIdentifier(id, "Webhook endpoint id");
1376
+ return request({
1377
+ method: "POST",
1378
+ path: `/v1/webhook-endpoints/${encodePathSegment(id)}/end-secret-overlap`,
1379
+ body: {},
1380
+ idempotencyKey: input.idempotencyKey,
1381
+ signal: input.signal,
1382
+ guard: isWebhookEndpoint
1383
+ });
1384
+ };
779
1385
  const createTestWebhook = (input) => {
780
1386
  assertIdentifier(input.endpointId, "Webhook endpoint id");
781
1387
  assertWebhookEventTypes(
@@ -797,7 +1403,23 @@ function createPayclaveServerClient({
797
1403
  if (limit !== void 0) {
798
1404
  assertPositiveIntegerLimit(limit);
799
1405
  }
800
- const query = limit !== void 0 ? `?limit=${encodeURIComponent(String(limit))}` : "";
1406
+ const params = new URLSearchParams();
1407
+ if (limit !== void 0) params.set("limit", String(limit));
1408
+ for (const [key, value] of [
1409
+ ["endpointId", input.endpointId],
1410
+ ["eventType", input.eventType],
1411
+ ["status", input.status],
1412
+ ["createdFrom", input.createdFrom],
1413
+ ["createdTo", input.createdTo],
1414
+ ["replayStatus", input.replayStatus],
1415
+ ["responseFamily", input.responseFamily]
1416
+ ]) {
1417
+ if (value !== void 0) {
1418
+ assertIdentifier(value, key);
1419
+ params.set(key, value);
1420
+ }
1421
+ }
1422
+ const query = params.size > 0 ? `?${params.toString()}` : "";
801
1423
  return request({
802
1424
  method: "GET",
803
1425
  path: `/v1/webhook-deliveries${query}`,
@@ -805,16 +1427,222 @@ function createPayclaveServerClient({
805
1427
  guard: isWebhookDeliveryArray
806
1428
  });
807
1429
  };
1430
+ const getWebhookDelivery = (id, options = {}) => {
1431
+ assertIdentifier(id, "Webhook delivery id");
1432
+ return request({
1433
+ method: "GET",
1434
+ path: `/v1/webhook-deliveries/${encodePathSegment(id)}`,
1435
+ signal: options.signal,
1436
+ guard: isWebhookDeliveryDetail
1437
+ });
1438
+ };
1439
+ const listWebhookDeliveryAttempts = (id, options = {}) => {
1440
+ assertIdentifier(id, "Webhook delivery id");
1441
+ return request({
1442
+ method: "GET",
1443
+ path: `/v1/webhook-deliveries/${encodePathSegment(id)}/attempts`,
1444
+ signal: options.signal,
1445
+ guard: isWebhookDeliveryAttemptArray
1446
+ });
1447
+ };
1448
+ const replayWebhookDelivery = (id, input) => {
1449
+ assertIdentifier(id, "Webhook delivery id");
1450
+ return request({
1451
+ method: "POST",
1452
+ path: `/v1/webhook-deliveries/${encodePathSegment(id)}/replay`,
1453
+ idempotencyKey: input.idempotencyKey,
1454
+ signal: input.signal,
1455
+ guard: isWebhookDeliveryDetail
1456
+ });
1457
+ };
1458
+ const listWebhookIncidents = (input = {}) => {
1459
+ const query = input.status ? `?status=${input.status}` : "";
1460
+ return request({
1461
+ method: "GET",
1462
+ path: `/v1/webhook-incidents${query}`,
1463
+ signal: input.signal,
1464
+ guard: isWebhookIncidentArray
1465
+ });
1466
+ };
1467
+ const getWebhookIncident = (id, options = {}) => {
1468
+ assertIdentifier(id, "Webhook incident id");
1469
+ return request({
1470
+ method: "GET",
1471
+ path: `/v1/webhook-incidents/${encodePathSegment(id)}`,
1472
+ signal: options.signal,
1473
+ guard: isWebhookIncident
1474
+ });
1475
+ };
1476
+ const getReconciliationSchema = (version = PAYCLAVE_RECONCILIATION_SCHEMA_VERSION, options = {}) => {
1477
+ assertIdentifier(version, "Reconciliation schema version");
1478
+ return request({
1479
+ method: "GET",
1480
+ path: `/v1/reconciliation/schema/${encodePathSegment(version)}`,
1481
+ signal: options.signal,
1482
+ guard: isReconciliationSchema
1483
+ });
1484
+ };
1485
+ const getReconciliationSummary = (input) => {
1486
+ assertIdentifier(input.dateBasis, "Reconciliation date basis");
1487
+ assertIdentifier(input.from, "Reconciliation from timestamp");
1488
+ assertIdentifier(input.to, "Reconciliation to timestamp");
1489
+ const query = new URLSearchParams({
1490
+ dateBasis: input.dateBasis,
1491
+ from: input.from,
1492
+ to: input.to,
1493
+ timezone: input.timezone ?? "UTC"
1494
+ });
1495
+ if (input.exceptionOnly !== void 0) {
1496
+ query.set("exceptionOnly", String(input.exceptionOnly));
1497
+ }
1498
+ for (const status of input.invoiceStatuses ?? []) {
1499
+ query.append("invoiceStatus", status);
1500
+ }
1501
+ for (const status of input.paymentStatuses ?? []) {
1502
+ query.append("paymentStatus", status);
1503
+ }
1504
+ for (const token of input.settlementTokens ?? []) {
1505
+ query.append("settlementToken", token);
1506
+ }
1507
+ return request({
1508
+ method: "GET",
1509
+ path: `/v1/reconciliation/summary?${query.toString()}`,
1510
+ signal: input.signal,
1511
+ guard: isReconciliationSummary
1512
+ });
1513
+ };
1514
+ const createReconciliationExport = (input) => {
1515
+ assertReconciliationFormat(input.format);
1516
+ assertIdentifier(input.dateBasis, "Reconciliation date basis");
1517
+ assertIdentifier(input.from, "Reconciliation from timestamp");
1518
+ assertIdentifier(input.to, "Reconciliation to timestamp");
1519
+ const { signal, idempotencyKey, ...fields } = input;
1520
+ return request({
1521
+ method: "POST",
1522
+ path: "/v1/reconciliation-exports",
1523
+ body: compact({
1524
+ ...fields,
1525
+ mode: input.mode ?? (secretKey.startsWith("sk_live_") ? "live" : "test"),
1526
+ timezone: input.timezone ?? "UTC",
1527
+ exceptionOnly: input.exceptionOnly ?? false,
1528
+ includePII: input.includePII ?? false,
1529
+ schemaVersion: input.schemaVersion ?? PAYCLAVE_RECONCILIATION_SCHEMA_VERSION
1530
+ }),
1531
+ idempotencyKey,
1532
+ signal,
1533
+ guard: isReconciliationExport
1534
+ });
1535
+ };
1536
+ const listReconciliationExports = (input = {}) => {
1537
+ const query = new URLSearchParams();
1538
+ if (input.limit !== void 0) {
1539
+ assertPositiveIntegerLimit(input.limit);
1540
+ query.set("limit", String(input.limit));
1541
+ }
1542
+ if (input.startingAfter !== void 0) {
1543
+ assertIdentifier(input.startingAfter, "Starting reconciliation export id");
1544
+ query.set("startingAfter", input.startingAfter);
1545
+ }
1546
+ const suffix = query.size > 0 ? `?${query.toString()}` : "";
1547
+ return request({
1548
+ method: "GET",
1549
+ path: `/v1/reconciliation-exports${suffix}`,
1550
+ signal: input.signal,
1551
+ guard: isReconciliationExportList
1552
+ });
1553
+ };
1554
+ const getReconciliationExport = (id, options = {}) => {
1555
+ assertIdentifier(id, "Reconciliation export id");
1556
+ return request({
1557
+ method: "GET",
1558
+ path: `/v1/reconciliation-exports/${encodePathSegment(id)}`,
1559
+ signal: options.signal,
1560
+ guard: isReconciliationExport
1561
+ });
1562
+ };
1563
+ const cancelReconciliationExport = (id, input = {}) => {
1564
+ assertIdentifier(id, "Reconciliation export id");
1565
+ return request({
1566
+ method: "POST",
1567
+ path: `/v1/reconciliation-exports/${encodePathSegment(id)}/cancel`,
1568
+ idempotencyKey: input.idempotencyKey,
1569
+ signal: input.signal,
1570
+ guard: isReconciliationExport
1571
+ });
1572
+ };
1573
+ const downloadReconciliationExport = async (id, options = {}) => {
1574
+ assertIdentifier(id, "Reconciliation export id");
1575
+ const response = await runFetch({
1576
+ fetcher,
1577
+ url: joinUrl(
1578
+ normalizedApiBaseUrl,
1579
+ `/v1/reconciliation-exports/${encodePathSegment(id)}/download`
1580
+ ),
1581
+ init: {
1582
+ method: "GET",
1583
+ headers: {
1584
+ Accept: "application/zip",
1585
+ Authorization: `Bearer ${secretKey}`,
1586
+ "X-Payclave-Client": buildClientHeader()
1587
+ }
1588
+ },
1589
+ externalSignal: options.signal,
1590
+ timeoutMs
1591
+ });
1592
+ return parseReconciliationDownloadResponse(response);
1593
+ };
808
1594
  return {
809
1595
  createCheckoutSession,
810
1596
  getCheckoutSession,
811
1597
  createInvoice,
1598
+ createInvoiceDraft,
1599
+ listInvoices,
812
1600
  getInvoice,
1601
+ downloadInvoicePDF,
1602
+ updateInvoiceDraft,
1603
+ issueInvoice,
1604
+ sendInvoice,
1605
+ remindInvoice,
1606
+ createInvoiceCheckoutSession,
1607
+ voidInvoice,
1608
+ voidInvoiceRemaining,
1609
+ markInvoiceUncollectible,
1610
+ duplicateInvoice,
1611
+ checkInvoiceRefund,
1612
+ recordInvoiceRefundReference,
1613
+ createPaymentLink,
1614
+ listPaymentLinks,
1615
+ getPaymentLink,
1616
+ updatePaymentLink,
1617
+ pausePaymentLink,
1618
+ resumePaymentLink,
1619
+ archivePaymentLink,
1620
+ duplicatePaymentLink,
1621
+ releasePaymentLinkReservation,
1622
+ listPaymentLinkPayments,
813
1623
  getPayment,
814
1624
  createWebhookEndpoint,
1625
+ listWebhookEndpoints,
1626
+ getWebhookEndpoint,
1627
+ updateWebhookEndpoint,
1628
+ archiveWebhookEndpoint,
1629
+ rotateWebhookSecret,
1630
+ endWebhookSecretOverlap,
815
1631
  createTestWebhook,
816
- listWebhookDeliveries
1632
+ listWebhookDeliveries,
1633
+ getWebhookDelivery,
1634
+ listWebhookDeliveryAttempts,
1635
+ replayWebhookDelivery,
1636
+ listWebhookIncidents,
1637
+ getWebhookIncident,
1638
+ getReconciliationSchema,
1639
+ getReconciliationSummary,
1640
+ createReconciliationExport,
1641
+ listReconciliationExports,
1642
+ getReconciliationExport,
1643
+ cancelReconciliationExport,
1644
+ downloadReconciliationExport
817
1645
  };
818
1646
  }
819
1647
 
820
- export { PAYCLAVE_API_ERROR_CODES, PAYCLAVE_SERVER_SDK_ERROR_CODES, PAYCLAVE_SERVER_SDK_NAME, PAYCLAVE_SERVER_SDK_VERSION, PAYCLAVE_WEBHOOK_EVENT_TYPES, PAYCLAVE_WEBHOOK_VERIFICATION_ERROR_CODES, PayclaveError, assertPayclaveWebhookSignature, constructPayclaveWebhookEvent, createPayclaveServerClient, verifyPayclaveWebhookSignature };
1648
+ export { PAYCLAVE_API_ERROR_CODES, PAYCLAVE_RECONCILIATION_SCHEMA_VERSION, PAYCLAVE_SERVER_SDK_ERROR_CODES, PAYCLAVE_SERVER_SDK_NAME, PAYCLAVE_SERVER_SDK_VERSION, PAYCLAVE_WEBHOOK_EVENT_TYPES, PAYCLAVE_WEBHOOK_VERIFICATION_ERROR_CODES, PayclaveError, assertPayclaveWebhookSignature, constructPayclaveWebhookEvent, createPayclaveServerClient, verifyPayclaveWebhookSignature };