@garuhq/node 0.11.1 → 0.12.1
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/CHANGELOG.md +49 -0
- package/README.md +32 -0
- package/dist/index.cjs +52 -2
- package/dist/index.d.cts +62 -3
- package/dist/index.d.ts +62 -3
- package/dist/index.js +52 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,55 @@
|
|
|
3
3
|
All notable changes to `@garuhq/node` are documented in this file. Format:
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Versioning: [SemVer](https://semver.org/).
|
|
5
5
|
|
|
6
|
+
## [0.12.1] — 2026-05-19
|
|
7
|
+
|
|
8
|
+
### Fixed
|
|
9
|
+
|
|
10
|
+
- `webhookEvents.resend(id)` now auto-attaches `X-Idempotency-Key`
|
|
11
|
+
(UUIDv4) so transient transport retries (5xx → SDK backoff) cannot
|
|
12
|
+
create duplicate clones. Previously, a 503 mid-flight after the
|
|
13
|
+
backend had already committed the clone could trigger an SDK retry
|
|
14
|
+
and produce a second clone with a different id. With the
|
|
15
|
+
idempotency key in place, the backend returns the original clone on
|
|
16
|
+
the second call within 24h. Pass `{ idempotencyKey }` to dedupe
|
|
17
|
+
across your own retry layer.
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- `ResendWebhookEventParams` type exported from the package root —
|
|
22
|
+
the optional `{ idempotencyKey?: string }` for `resend()`.
|
|
23
|
+
- README quickstart entry for `webhookEvents`
|
|
24
|
+
(`list` / `get` / `resend` / `retry`), including the audit-trail
|
|
25
|
+
contract and the SDK→gateway idempotency note.
|
|
26
|
+
|
|
27
|
+
## [0.12.0] — 2026-05-19
|
|
28
|
+
|
|
29
|
+
### Added
|
|
30
|
+
|
|
31
|
+
- `webhookEvents.resend(id)` — `POST /api/webhook-events/{id}/resend`,
|
|
32
|
+
the audit-trail-preserving counterpart to `retry()`. The backend
|
|
33
|
+
inserts a *clone* event (new numeric id) that points back at the
|
|
34
|
+
source via `manualResendOf`, then dispatches that clone. The
|
|
35
|
+
original row is untouched, so the historical record of the prior
|
|
36
|
+
failure (status, response status/body, attempts) survives. Works on
|
|
37
|
+
any source status (`success` / `failed` / `pending`).
|
|
38
|
+
- Outbound delivery uses `Idempotency-Key: resend_<originalId>`, so
|
|
39
|
+
recipient handlers can distinguish a resend from a fresh delivery
|
|
40
|
+
both by the header prefix and by reading the response payload's
|
|
41
|
+
`manualResendOf` field.
|
|
42
|
+
- `WebhookEvent.manualResendOf: number | null` — populated with the
|
|
43
|
+
source event's numeric id on rows produced by `resend()`, `null`
|
|
44
|
+
everywhere else (originally-fired events and legacy `retry()`
|
|
45
|
+
outputs).
|
|
46
|
+
|
|
47
|
+
### Deprecated
|
|
48
|
+
|
|
49
|
+
- `webhookEvents.retry(id)` is soft-deprecated. It still works and is
|
|
50
|
+
not scheduled for removal — older CLI / MCP releases depend on it —
|
|
51
|
+
but new integrations should prefer `resend()`, which preserves the
|
|
52
|
+
original event's audit trail by cloning instead of mutating the row
|
|
53
|
+
in place.
|
|
54
|
+
|
|
6
55
|
## [0.11.1] — 2026-05-19
|
|
7
56
|
|
|
8
57
|
### Fixed
|
package/README.md
CHANGED
|
@@ -292,6 +292,38 @@ app.post('/webhooks/garu', express.raw({ type: 'application/json' }), (req, res)
|
|
|
292
292
|
> [!IMPORTANT]
|
|
293
293
|
> Always pass the raw request body to `verify()`. Parsing and re-serializing JSON will break the signature check.
|
|
294
294
|
|
|
295
|
+
## Webhook events
|
|
296
|
+
|
|
297
|
+
The seller-facing delivery log for outbound webhooks. Use it to audit deliveries, surface failures, and replay events when a customer's endpoint missed one. Webhook endpoint *configuration* (URL, subscribed events, secret) is still dashboard-only — this resource only covers the event log + manual retries.
|
|
298
|
+
|
|
299
|
+
```ts
|
|
300
|
+
// Surface anything that didn't make it through
|
|
301
|
+
const failed = await garu.webhookEvents.list({ status: 'failed', limit: 50 });
|
|
302
|
+
|
|
303
|
+
// Inspect one event end-to-end
|
|
304
|
+
const event = await garu.webhookEvents.get(42);
|
|
305
|
+
console.log(event.responseStatus, event.responseBody);
|
|
306
|
+
|
|
307
|
+
// Audit-trail-preserving replay (recommended)
|
|
308
|
+
const clone = await garu.webhookEvents.resend(42);
|
|
309
|
+
clone.id !== event.id; // true — fresh row with its own id
|
|
310
|
+
clone.manualResendOf === event.id; // true — points back at the source
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
`resend(id)` is the audit-preserving counterpart to `retry(id)` — the backend inserts a fresh event whose `manualResendOf` points back at the source, then dispatches that clone. The original row stays exactly as it was, so the historical record of the prior failure (status, response status/body, attempts) survives. Works on any source status (`success` / `failed` / `pending`).
|
|
314
|
+
|
|
315
|
+
Outbound deliveries of a resent event carry `Idempotency-Key: resend_<originalId>`, so recipient handlers can distinguish a resend from a fresh delivery both by the header prefix and by reading the response payload's `manualResendOf` field.
|
|
316
|
+
|
|
317
|
+
> [!NOTE]
|
|
318
|
+
> The SDK auto-attaches `X-Idempotency-Key` (UUIDv4) on `resend()` so transient transport retries can't create duplicate clones. Pass `{ idempotencyKey }` to dedupe across your own retry layer.
|
|
319
|
+
|
|
320
|
+
| Method | Purpose |
|
|
321
|
+
| ------------------------------- | ---------------------------------------------------------------------------------- |
|
|
322
|
+
| `list(params?)` | Paginated event log. Filter by `status`, `eventType`, `endpointId`. Newest first. |
|
|
323
|
+
| `get(id)` | One event — full payload, endpoint snapshot, most recent response. |
|
|
324
|
+
| `resend(id, params?)` | Clone-on-resend. Returns the new event; original is untouched. **Preferred.** |
|
|
325
|
+
| `retry(id)` | Legacy in-place reset (mutates the original row). Soft-deprecated. |
|
|
326
|
+
|
|
295
327
|
## Error handling
|
|
296
328
|
|
|
297
329
|
Every error extends `GaruError`. API errors include `status`, `requestId`, and `body`.
|
package/dist/index.cjs
CHANGED
|
@@ -898,10 +898,16 @@ var WebhookEvents = class {
|
|
|
898
898
|
);
|
|
899
899
|
}
|
|
900
900
|
/**
|
|
901
|
+
* @deprecated For most cases prefer {@link resend}, which preserves the
|
|
902
|
+
* original event's audit trail by cloning rather than mutating. `retry()`
|
|
903
|
+
* resets the original row in place — once it succeeds, the historical
|
|
904
|
+
* record of the prior failure is gone. Kept here for callers that
|
|
905
|
+
* explicitly want the legacy in-place semantics (and for backwards
|
|
906
|
+
* compatibility with older CLI / MCP releases).
|
|
907
|
+
*
|
|
901
908
|
* Re-deliver a webhook event by ID. Resets it to `pending`, clears the
|
|
902
909
|
* retry schedule, and triggers an immediate delivery attempt. Works on
|
|
903
|
-
* any status (`success`, `failed`, `pending`)
|
|
904
|
-
* customer reports a missed or unprocessed event.
|
|
910
|
+
* any status (`success`, `failed`, `pending`).
|
|
905
911
|
*
|
|
906
912
|
* @example
|
|
907
913
|
* const failed = await garu.webhookEvents.list({ status: 'failed', limit: 5 });
|
|
@@ -917,6 +923,50 @@ var WebhookEvents = class {
|
|
|
917
923
|
}).then((r) => r)
|
|
918
924
|
);
|
|
919
925
|
}
|
|
926
|
+
/**
|
|
927
|
+
* Re-deliver a webhook event by ID, audit-trail preserving. Unlike
|
|
928
|
+
* {@link retry}, this does *not* mutate the original row — it inserts a
|
|
929
|
+
* fresh event (new numeric id) that points back at the source via
|
|
930
|
+
* `manualResendOf`, then dispatches that clone. The original row is
|
|
931
|
+
* untouched, so the historical record of the prior failure (and its
|
|
932
|
+
* response status / body) is preserved.
|
|
933
|
+
*
|
|
934
|
+
* Works on any source status (`success`, `failed`, `pending`). Use this
|
|
935
|
+
* when a customer reports a missed or unprocessed event, or to replay an
|
|
936
|
+
* event during a backfill — both reasons where you want the original
|
|
937
|
+
* delivery's outcome to remain on the record.
|
|
938
|
+
*
|
|
939
|
+
* **Outbound delivery semantics**: the gateway POSTs the clone with
|
|
940
|
+
* `Idempotency-Key: resend_<originalId>` (where `<originalId>` is the id
|
|
941
|
+
* of the source event, not the clone). Recipient handlers that key off
|
|
942
|
+
* `Idempotency-Key` will see this as a distinct delivery from the
|
|
943
|
+
* original — distinguishable both by the `resend_` prefix and by reading
|
|
944
|
+
* the response payload's `manualResendOf` field.
|
|
945
|
+
*
|
|
946
|
+
* **SDK→gateway dedup**: the SDK auto-attaches `X-Idempotency-Key`
|
|
947
|
+
* (UUIDv4 unless you pass `idempotencyKey`) so transient transport
|
|
948
|
+
* retries (5xx → SDK backoff) cannot create duplicate clones — the
|
|
949
|
+
* backend returns the original clone on the second call within 24h.
|
|
950
|
+
*
|
|
951
|
+
* Returns the *clone* event (new id), not the original. The original is
|
|
952
|
+
* unchanged on the server.
|
|
953
|
+
*
|
|
954
|
+
* @example
|
|
955
|
+
* const event = await garu.webhookEvents.get(42);
|
|
956
|
+
* const clone = await garu.webhookEvents.resend(42);
|
|
957
|
+
* clone.id !== event.id; // true — clone has its own id
|
|
958
|
+
* clone.manualResendOf === event.id; // true — points back at the source
|
|
959
|
+
*/
|
|
960
|
+
async resend(id, params = {}) {
|
|
961
|
+
const idempotencyKey = params.idempotencyKey ?? generateIdempotencyKey();
|
|
962
|
+
return this.http.call(
|
|
963
|
+
(signal) => this.http.client.POST(`/api/webhook-events/${id}/resend`, {
|
|
964
|
+
body: {},
|
|
965
|
+
headers: { "X-Idempotency-Key": idempotencyKey },
|
|
966
|
+
signal
|
|
967
|
+
}).then((r) => r)
|
|
968
|
+
);
|
|
969
|
+
}
|
|
920
970
|
};
|
|
921
971
|
var webhooks = {
|
|
922
972
|
verify(params) {
|
package/dist/index.d.cts
CHANGED
|
@@ -596,6 +596,14 @@ interface WebhookEvent {
|
|
|
596
596
|
responseStatus: number | null;
|
|
597
597
|
/** Response body from the most recent attempt, truncated by the gateway. */
|
|
598
598
|
responseBody: string | null;
|
|
599
|
+
/**
|
|
600
|
+
* When this row is a clone produced by `webhookEvents.resend(id)`, this is
|
|
601
|
+
* the numeric id of the original event the clone was forked from. `null`
|
|
602
|
+
* on every originally-fired event (and on events resurrected via the
|
|
603
|
+
* legacy `webhookEvents.retry(id)` mutation, which mutates in place
|
|
604
|
+
* instead of cloning).
|
|
605
|
+
*/
|
|
606
|
+
manualResendOf: number | null;
|
|
599
607
|
createdAt: string;
|
|
600
608
|
[key: string]: unknown;
|
|
601
609
|
}
|
|
@@ -610,6 +618,16 @@ interface ListWebhookEventsParams {
|
|
|
610
618
|
/** Filter by the destination endpoint that should receive (or received) the event. */
|
|
611
619
|
endpointId?: number;
|
|
612
620
|
}
|
|
621
|
+
interface ResendWebhookEventParams {
|
|
622
|
+
/**
|
|
623
|
+
* SDK→gateway idempotency key. If omitted, the SDK generates a UUIDv4
|
|
624
|
+
* and forwards it as `X-Idempotency-Key`. Within 24h the backend
|
|
625
|
+
* returns the original clone instead of creating a new one — pass a
|
|
626
|
+
* stable key from your own retry layer to dedupe across SDK
|
|
627
|
+
* invocations.
|
|
628
|
+
*/
|
|
629
|
+
idempotencyKey?: string;
|
|
630
|
+
}
|
|
613
631
|
/**
|
|
614
632
|
* Per-product portal customization (Atletia coach-as-product modeling and
|
|
615
633
|
* any other B2B2C platform). `null` fields inherit from the seller-level
|
|
@@ -1117,10 +1135,16 @@ declare class WebhookEvents {
|
|
|
1117
1135
|
*/
|
|
1118
1136
|
get(id: number): Promise<WebhookEvent>;
|
|
1119
1137
|
/**
|
|
1138
|
+
* @deprecated For most cases prefer {@link resend}, which preserves the
|
|
1139
|
+
* original event's audit trail by cloning rather than mutating. `retry()`
|
|
1140
|
+
* resets the original row in place — once it succeeds, the historical
|
|
1141
|
+
* record of the prior failure is gone. Kept here for callers that
|
|
1142
|
+
* explicitly want the legacy in-place semantics (and for backwards
|
|
1143
|
+
* compatibility with older CLI / MCP releases).
|
|
1144
|
+
*
|
|
1120
1145
|
* Re-deliver a webhook event by ID. Resets it to `pending`, clears the
|
|
1121
1146
|
* retry schedule, and triggers an immediate delivery attempt. Works on
|
|
1122
|
-
* any status (`success`, `failed`, `pending`)
|
|
1123
|
-
* customer reports a missed or unprocessed event.
|
|
1147
|
+
* any status (`success`, `failed`, `pending`).
|
|
1124
1148
|
*
|
|
1125
1149
|
* @example
|
|
1126
1150
|
* const failed = await garu.webhookEvents.list({ status: 'failed', limit: 5 });
|
|
@@ -1129,6 +1153,41 @@ declare class WebhookEvents {
|
|
|
1129
1153
|
* }
|
|
1130
1154
|
*/
|
|
1131
1155
|
retry(id: number): Promise<WebhookEvent>;
|
|
1156
|
+
/**
|
|
1157
|
+
* Re-deliver a webhook event by ID, audit-trail preserving. Unlike
|
|
1158
|
+
* {@link retry}, this does *not* mutate the original row — it inserts a
|
|
1159
|
+
* fresh event (new numeric id) that points back at the source via
|
|
1160
|
+
* `manualResendOf`, then dispatches that clone. The original row is
|
|
1161
|
+
* untouched, so the historical record of the prior failure (and its
|
|
1162
|
+
* response status / body) is preserved.
|
|
1163
|
+
*
|
|
1164
|
+
* Works on any source status (`success`, `failed`, `pending`). Use this
|
|
1165
|
+
* when a customer reports a missed or unprocessed event, or to replay an
|
|
1166
|
+
* event during a backfill — both reasons where you want the original
|
|
1167
|
+
* delivery's outcome to remain on the record.
|
|
1168
|
+
*
|
|
1169
|
+
* **Outbound delivery semantics**: the gateway POSTs the clone with
|
|
1170
|
+
* `Idempotency-Key: resend_<originalId>` (where `<originalId>` is the id
|
|
1171
|
+
* of the source event, not the clone). Recipient handlers that key off
|
|
1172
|
+
* `Idempotency-Key` will see this as a distinct delivery from the
|
|
1173
|
+
* original — distinguishable both by the `resend_` prefix and by reading
|
|
1174
|
+
* the response payload's `manualResendOf` field.
|
|
1175
|
+
*
|
|
1176
|
+
* **SDK→gateway dedup**: the SDK auto-attaches `X-Idempotency-Key`
|
|
1177
|
+
* (UUIDv4 unless you pass `idempotencyKey`) so transient transport
|
|
1178
|
+
* retries (5xx → SDK backoff) cannot create duplicate clones — the
|
|
1179
|
+
* backend returns the original clone on the second call within 24h.
|
|
1180
|
+
*
|
|
1181
|
+
* Returns the *clone* event (new id), not the original. The original is
|
|
1182
|
+
* unchanged on the server.
|
|
1183
|
+
*
|
|
1184
|
+
* @example
|
|
1185
|
+
* const event = await garu.webhookEvents.get(42);
|
|
1186
|
+
* const clone = await garu.webhookEvents.resend(42);
|
|
1187
|
+
* clone.id !== event.id; // true — clone has its own id
|
|
1188
|
+
* clone.manualResendOf === event.id; // true — points back at the source
|
|
1189
|
+
*/
|
|
1190
|
+
resend(id: number, params?: ResendWebhookEventParams): Promise<WebhookEvent>;
|
|
1132
1191
|
}
|
|
1133
1192
|
|
|
1134
1193
|
interface GaruOptions {
|
|
@@ -1230,4 +1289,4 @@ declare class GaruServerError extends GaruAPIError {
|
|
|
1230
1289
|
constructor(message: string, status: number, requestId: string | null, body: unknown);
|
|
1231
1290
|
}
|
|
1232
1291
|
|
|
1233
|
-
export { type CancelAtPeriodEndScheduledChargeParams, type CancelRecurrenceScheduledChargeParams, type CardInfo, type ChangePaymentMethodScheduledChargeParams, type Charge, type ChargeList, type ChargeStatus, type CreateChargeParams, type CreateCustomerParams, type CreateScheduledChargeParams, type Customer, type CustomerList, type CustomerRecord, type FailurePayload, Garu, GaruAPIError, GaruAuthenticationError, GaruConnectionError, GaruError, type GaruErrorCode, type GaruFailureCode, GaruNotFoundError, type GaruOptions, GaruPermissionError, GaruRateLimitError, GaruServerError, GaruSignatureVerificationError, GaruValidationError, type ListChargesParams, type ListCustomersParams, type ListProductsParams, type ListScheduledChargeAttemptsParams, type ListScheduledChargesParams, type ListWebhookEventsParams, type MarkPaidScheduledChargeParams, type MetaFeatures, type MetaResponse, type PaginatedList, type PauseScheduledChargeParams, type PaymentMethod, type PaymentMethodExpiredPayload, type PaymentMethodExpiringPayload, type PostponeScheduledChargeParams, type Product, type ProductList, type ProductPortalConfig, type RecurrenceConfig, type RecurrenceInterval, type RefundChargeParams, type ScheduledChargeActor, type ScheduledChargeAttempt, type ScheduledChargeAttemptList, type ScheduledChargeAttemptSource, type ScheduledChargeAttemptStatus, type ScheduledChargeDetail, type ScheduledChargeEvent, type ScheduledChargeEventType, type ScheduledChargeLinkedTransaction, type ScheduledChargeList, type ScheduledChargeRecord, type ScheduledChargeStatus, type ScheduledChargeType, type ScheduledPaymentMethod, type SetProductPortalConfigParams, type UpdateCustomerParams, type VerifiedWebhook, type VerifyWebhookParams, type WebhookEvent, type WebhookEventEndpoint, type WebhookEventList, type WebhookEventStatus, type WirePaymentMethodId, webhooks };
|
|
1292
|
+
export { type CancelAtPeriodEndScheduledChargeParams, type CancelRecurrenceScheduledChargeParams, type CardInfo, type ChangePaymentMethodScheduledChargeParams, type Charge, type ChargeList, type ChargeStatus, type CreateChargeParams, type CreateCustomerParams, type CreateScheduledChargeParams, type Customer, type CustomerList, type CustomerRecord, type FailurePayload, Garu, GaruAPIError, GaruAuthenticationError, GaruConnectionError, GaruError, type GaruErrorCode, type GaruFailureCode, GaruNotFoundError, type GaruOptions, GaruPermissionError, GaruRateLimitError, GaruServerError, GaruSignatureVerificationError, GaruValidationError, type ListChargesParams, type ListCustomersParams, type ListProductsParams, type ListScheduledChargeAttemptsParams, type ListScheduledChargesParams, type ListWebhookEventsParams, type MarkPaidScheduledChargeParams, type MetaFeatures, type MetaResponse, type PaginatedList, type PauseScheduledChargeParams, type PaymentMethod, type PaymentMethodExpiredPayload, type PaymentMethodExpiringPayload, type PostponeScheduledChargeParams, type Product, type ProductList, type ProductPortalConfig, type RecurrenceConfig, type RecurrenceInterval, type RefundChargeParams, type ResendWebhookEventParams, type ScheduledChargeActor, type ScheduledChargeAttempt, type ScheduledChargeAttemptList, type ScheduledChargeAttemptSource, type ScheduledChargeAttemptStatus, type ScheduledChargeDetail, type ScheduledChargeEvent, type ScheduledChargeEventType, type ScheduledChargeLinkedTransaction, type ScheduledChargeList, type ScheduledChargeRecord, type ScheduledChargeStatus, type ScheduledChargeType, type ScheduledPaymentMethod, type SetProductPortalConfigParams, type UpdateCustomerParams, type VerifiedWebhook, type VerifyWebhookParams, type WebhookEvent, type WebhookEventEndpoint, type WebhookEventList, type WebhookEventStatus, type WirePaymentMethodId, webhooks };
|
package/dist/index.d.ts
CHANGED
|
@@ -596,6 +596,14 @@ interface WebhookEvent {
|
|
|
596
596
|
responseStatus: number | null;
|
|
597
597
|
/** Response body from the most recent attempt, truncated by the gateway. */
|
|
598
598
|
responseBody: string | null;
|
|
599
|
+
/**
|
|
600
|
+
* When this row is a clone produced by `webhookEvents.resend(id)`, this is
|
|
601
|
+
* the numeric id of the original event the clone was forked from. `null`
|
|
602
|
+
* on every originally-fired event (and on events resurrected via the
|
|
603
|
+
* legacy `webhookEvents.retry(id)` mutation, which mutates in place
|
|
604
|
+
* instead of cloning).
|
|
605
|
+
*/
|
|
606
|
+
manualResendOf: number | null;
|
|
599
607
|
createdAt: string;
|
|
600
608
|
[key: string]: unknown;
|
|
601
609
|
}
|
|
@@ -610,6 +618,16 @@ interface ListWebhookEventsParams {
|
|
|
610
618
|
/** Filter by the destination endpoint that should receive (or received) the event. */
|
|
611
619
|
endpointId?: number;
|
|
612
620
|
}
|
|
621
|
+
interface ResendWebhookEventParams {
|
|
622
|
+
/**
|
|
623
|
+
* SDK→gateway idempotency key. If omitted, the SDK generates a UUIDv4
|
|
624
|
+
* and forwards it as `X-Idempotency-Key`. Within 24h the backend
|
|
625
|
+
* returns the original clone instead of creating a new one — pass a
|
|
626
|
+
* stable key from your own retry layer to dedupe across SDK
|
|
627
|
+
* invocations.
|
|
628
|
+
*/
|
|
629
|
+
idempotencyKey?: string;
|
|
630
|
+
}
|
|
613
631
|
/**
|
|
614
632
|
* Per-product portal customization (Atletia coach-as-product modeling and
|
|
615
633
|
* any other B2B2C platform). `null` fields inherit from the seller-level
|
|
@@ -1117,10 +1135,16 @@ declare class WebhookEvents {
|
|
|
1117
1135
|
*/
|
|
1118
1136
|
get(id: number): Promise<WebhookEvent>;
|
|
1119
1137
|
/**
|
|
1138
|
+
* @deprecated For most cases prefer {@link resend}, which preserves the
|
|
1139
|
+
* original event's audit trail by cloning rather than mutating. `retry()`
|
|
1140
|
+
* resets the original row in place — once it succeeds, the historical
|
|
1141
|
+
* record of the prior failure is gone. Kept here for callers that
|
|
1142
|
+
* explicitly want the legacy in-place semantics (and for backwards
|
|
1143
|
+
* compatibility with older CLI / MCP releases).
|
|
1144
|
+
*
|
|
1120
1145
|
* Re-deliver a webhook event by ID. Resets it to `pending`, clears the
|
|
1121
1146
|
* retry schedule, and triggers an immediate delivery attempt. Works on
|
|
1122
|
-
* any status (`success`, `failed`, `pending`)
|
|
1123
|
-
* customer reports a missed or unprocessed event.
|
|
1147
|
+
* any status (`success`, `failed`, `pending`).
|
|
1124
1148
|
*
|
|
1125
1149
|
* @example
|
|
1126
1150
|
* const failed = await garu.webhookEvents.list({ status: 'failed', limit: 5 });
|
|
@@ -1129,6 +1153,41 @@ declare class WebhookEvents {
|
|
|
1129
1153
|
* }
|
|
1130
1154
|
*/
|
|
1131
1155
|
retry(id: number): Promise<WebhookEvent>;
|
|
1156
|
+
/**
|
|
1157
|
+
* Re-deliver a webhook event by ID, audit-trail preserving. Unlike
|
|
1158
|
+
* {@link retry}, this does *not* mutate the original row — it inserts a
|
|
1159
|
+
* fresh event (new numeric id) that points back at the source via
|
|
1160
|
+
* `manualResendOf`, then dispatches that clone. The original row is
|
|
1161
|
+
* untouched, so the historical record of the prior failure (and its
|
|
1162
|
+
* response status / body) is preserved.
|
|
1163
|
+
*
|
|
1164
|
+
* Works on any source status (`success`, `failed`, `pending`). Use this
|
|
1165
|
+
* when a customer reports a missed or unprocessed event, or to replay an
|
|
1166
|
+
* event during a backfill — both reasons where you want the original
|
|
1167
|
+
* delivery's outcome to remain on the record.
|
|
1168
|
+
*
|
|
1169
|
+
* **Outbound delivery semantics**: the gateway POSTs the clone with
|
|
1170
|
+
* `Idempotency-Key: resend_<originalId>` (where `<originalId>` is the id
|
|
1171
|
+
* of the source event, not the clone). Recipient handlers that key off
|
|
1172
|
+
* `Idempotency-Key` will see this as a distinct delivery from the
|
|
1173
|
+
* original — distinguishable both by the `resend_` prefix and by reading
|
|
1174
|
+
* the response payload's `manualResendOf` field.
|
|
1175
|
+
*
|
|
1176
|
+
* **SDK→gateway dedup**: the SDK auto-attaches `X-Idempotency-Key`
|
|
1177
|
+
* (UUIDv4 unless you pass `idempotencyKey`) so transient transport
|
|
1178
|
+
* retries (5xx → SDK backoff) cannot create duplicate clones — the
|
|
1179
|
+
* backend returns the original clone on the second call within 24h.
|
|
1180
|
+
*
|
|
1181
|
+
* Returns the *clone* event (new id), not the original. The original is
|
|
1182
|
+
* unchanged on the server.
|
|
1183
|
+
*
|
|
1184
|
+
* @example
|
|
1185
|
+
* const event = await garu.webhookEvents.get(42);
|
|
1186
|
+
* const clone = await garu.webhookEvents.resend(42);
|
|
1187
|
+
* clone.id !== event.id; // true — clone has its own id
|
|
1188
|
+
* clone.manualResendOf === event.id; // true — points back at the source
|
|
1189
|
+
*/
|
|
1190
|
+
resend(id: number, params?: ResendWebhookEventParams): Promise<WebhookEvent>;
|
|
1132
1191
|
}
|
|
1133
1192
|
|
|
1134
1193
|
interface GaruOptions {
|
|
@@ -1230,4 +1289,4 @@ declare class GaruServerError extends GaruAPIError {
|
|
|
1230
1289
|
constructor(message: string, status: number, requestId: string | null, body: unknown);
|
|
1231
1290
|
}
|
|
1232
1291
|
|
|
1233
|
-
export { type CancelAtPeriodEndScheduledChargeParams, type CancelRecurrenceScheduledChargeParams, type CardInfo, type ChangePaymentMethodScheduledChargeParams, type Charge, type ChargeList, type ChargeStatus, type CreateChargeParams, type CreateCustomerParams, type CreateScheduledChargeParams, type Customer, type CustomerList, type CustomerRecord, type FailurePayload, Garu, GaruAPIError, GaruAuthenticationError, GaruConnectionError, GaruError, type GaruErrorCode, type GaruFailureCode, GaruNotFoundError, type GaruOptions, GaruPermissionError, GaruRateLimitError, GaruServerError, GaruSignatureVerificationError, GaruValidationError, type ListChargesParams, type ListCustomersParams, type ListProductsParams, type ListScheduledChargeAttemptsParams, type ListScheduledChargesParams, type ListWebhookEventsParams, type MarkPaidScheduledChargeParams, type MetaFeatures, type MetaResponse, type PaginatedList, type PauseScheduledChargeParams, type PaymentMethod, type PaymentMethodExpiredPayload, type PaymentMethodExpiringPayload, type PostponeScheduledChargeParams, type Product, type ProductList, type ProductPortalConfig, type RecurrenceConfig, type RecurrenceInterval, type RefundChargeParams, type ScheduledChargeActor, type ScheduledChargeAttempt, type ScheduledChargeAttemptList, type ScheduledChargeAttemptSource, type ScheduledChargeAttemptStatus, type ScheduledChargeDetail, type ScheduledChargeEvent, type ScheduledChargeEventType, type ScheduledChargeLinkedTransaction, type ScheduledChargeList, type ScheduledChargeRecord, type ScheduledChargeStatus, type ScheduledChargeType, type ScheduledPaymentMethod, type SetProductPortalConfigParams, type UpdateCustomerParams, type VerifiedWebhook, type VerifyWebhookParams, type WebhookEvent, type WebhookEventEndpoint, type WebhookEventList, type WebhookEventStatus, type WirePaymentMethodId, webhooks };
|
|
1292
|
+
export { type CancelAtPeriodEndScheduledChargeParams, type CancelRecurrenceScheduledChargeParams, type CardInfo, type ChangePaymentMethodScheduledChargeParams, type Charge, type ChargeList, type ChargeStatus, type CreateChargeParams, type CreateCustomerParams, type CreateScheduledChargeParams, type Customer, type CustomerList, type CustomerRecord, type FailurePayload, Garu, GaruAPIError, GaruAuthenticationError, GaruConnectionError, GaruError, type GaruErrorCode, type GaruFailureCode, GaruNotFoundError, type GaruOptions, GaruPermissionError, GaruRateLimitError, GaruServerError, GaruSignatureVerificationError, GaruValidationError, type ListChargesParams, type ListCustomersParams, type ListProductsParams, type ListScheduledChargeAttemptsParams, type ListScheduledChargesParams, type ListWebhookEventsParams, type MarkPaidScheduledChargeParams, type MetaFeatures, type MetaResponse, type PaginatedList, type PauseScheduledChargeParams, type PaymentMethod, type PaymentMethodExpiredPayload, type PaymentMethodExpiringPayload, type PostponeScheduledChargeParams, type Product, type ProductList, type ProductPortalConfig, type RecurrenceConfig, type RecurrenceInterval, type RefundChargeParams, type ResendWebhookEventParams, type ScheduledChargeActor, type ScheduledChargeAttempt, type ScheduledChargeAttemptList, type ScheduledChargeAttemptSource, type ScheduledChargeAttemptStatus, type ScheduledChargeDetail, type ScheduledChargeEvent, type ScheduledChargeEventType, type ScheduledChargeLinkedTransaction, type ScheduledChargeList, type ScheduledChargeRecord, type ScheduledChargeStatus, type ScheduledChargeType, type ScheduledPaymentMethod, type SetProductPortalConfigParams, type UpdateCustomerParams, type VerifiedWebhook, type VerifyWebhookParams, type WebhookEvent, type WebhookEventEndpoint, type WebhookEventList, type WebhookEventStatus, type WirePaymentMethodId, webhooks };
|
package/dist/index.js
CHANGED
|
@@ -892,10 +892,16 @@ var WebhookEvents = class {
|
|
|
892
892
|
);
|
|
893
893
|
}
|
|
894
894
|
/**
|
|
895
|
+
* @deprecated For most cases prefer {@link resend}, which preserves the
|
|
896
|
+
* original event's audit trail by cloning rather than mutating. `retry()`
|
|
897
|
+
* resets the original row in place — once it succeeds, the historical
|
|
898
|
+
* record of the prior failure is gone. Kept here for callers that
|
|
899
|
+
* explicitly want the legacy in-place semantics (and for backwards
|
|
900
|
+
* compatibility with older CLI / MCP releases).
|
|
901
|
+
*
|
|
895
902
|
* Re-deliver a webhook event by ID. Resets it to `pending`, clears the
|
|
896
903
|
* retry schedule, and triggers an immediate delivery attempt. Works on
|
|
897
|
-
* any status (`success`, `failed`, `pending`)
|
|
898
|
-
* customer reports a missed or unprocessed event.
|
|
904
|
+
* any status (`success`, `failed`, `pending`).
|
|
899
905
|
*
|
|
900
906
|
* @example
|
|
901
907
|
* const failed = await garu.webhookEvents.list({ status: 'failed', limit: 5 });
|
|
@@ -911,6 +917,50 @@ var WebhookEvents = class {
|
|
|
911
917
|
}).then((r) => r)
|
|
912
918
|
);
|
|
913
919
|
}
|
|
920
|
+
/**
|
|
921
|
+
* Re-deliver a webhook event by ID, audit-trail preserving. Unlike
|
|
922
|
+
* {@link retry}, this does *not* mutate the original row — it inserts a
|
|
923
|
+
* fresh event (new numeric id) that points back at the source via
|
|
924
|
+
* `manualResendOf`, then dispatches that clone. The original row is
|
|
925
|
+
* untouched, so the historical record of the prior failure (and its
|
|
926
|
+
* response status / body) is preserved.
|
|
927
|
+
*
|
|
928
|
+
* Works on any source status (`success`, `failed`, `pending`). Use this
|
|
929
|
+
* when a customer reports a missed or unprocessed event, or to replay an
|
|
930
|
+
* event during a backfill — both reasons where you want the original
|
|
931
|
+
* delivery's outcome to remain on the record.
|
|
932
|
+
*
|
|
933
|
+
* **Outbound delivery semantics**: the gateway POSTs the clone with
|
|
934
|
+
* `Idempotency-Key: resend_<originalId>` (where `<originalId>` is the id
|
|
935
|
+
* of the source event, not the clone). Recipient handlers that key off
|
|
936
|
+
* `Idempotency-Key` will see this as a distinct delivery from the
|
|
937
|
+
* original — distinguishable both by the `resend_` prefix and by reading
|
|
938
|
+
* the response payload's `manualResendOf` field.
|
|
939
|
+
*
|
|
940
|
+
* **SDK→gateway dedup**: the SDK auto-attaches `X-Idempotency-Key`
|
|
941
|
+
* (UUIDv4 unless you pass `idempotencyKey`) so transient transport
|
|
942
|
+
* retries (5xx → SDK backoff) cannot create duplicate clones — the
|
|
943
|
+
* backend returns the original clone on the second call within 24h.
|
|
944
|
+
*
|
|
945
|
+
* Returns the *clone* event (new id), not the original. The original is
|
|
946
|
+
* unchanged on the server.
|
|
947
|
+
*
|
|
948
|
+
* @example
|
|
949
|
+
* const event = await garu.webhookEvents.get(42);
|
|
950
|
+
* const clone = await garu.webhookEvents.resend(42);
|
|
951
|
+
* clone.id !== event.id; // true — clone has its own id
|
|
952
|
+
* clone.manualResendOf === event.id; // true — points back at the source
|
|
953
|
+
*/
|
|
954
|
+
async resend(id, params = {}) {
|
|
955
|
+
const idempotencyKey = params.idempotencyKey ?? generateIdempotencyKey();
|
|
956
|
+
return this.http.call(
|
|
957
|
+
(signal) => this.http.client.POST(`/api/webhook-events/${id}/resend`, {
|
|
958
|
+
body: {},
|
|
959
|
+
headers: { "X-Idempotency-Key": idempotencyKey },
|
|
960
|
+
signal
|
|
961
|
+
}).then((r) => r)
|
|
962
|
+
);
|
|
963
|
+
}
|
|
914
964
|
};
|
|
915
965
|
var webhooks = {
|
|
916
966
|
verify(params) {
|