@garuhq/node 4.1.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +49 -0
- package/dist/index.cjs +55 -51
- package/dist/index.d.cts +45 -31
- package/dist/index.d.ts +45 -31
- package/dist/index.js +56 -52
- 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
|
+
## [5.0.0] — 2026-09-09
|
|
7
|
+
|
|
8
|
+
**Breaking:** requests that omit `idempotencyKey` no longer carry an
|
|
9
|
+
`X-Idempotency-Key` header. No API contract changed and no gateway endpoint
|
|
10
|
+
requires the header, so most integrations need no code change — but if you were
|
|
11
|
+
relying on a key always being present, you must now pass one, which is the only
|
|
12
|
+
way it ever gave you real protection. See below.
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- **The SDK no longer invents an idempotency key.** Every write that takes
|
|
17
|
+
`idempotencyKey` (`charges.create`, `charges.refund`, `customers.create`,
|
|
18
|
+
`products.create`, `scheduledCharges.create`, `installmentPlans.create`,
|
|
19
|
+
`installmentPlans.requestRefund`, `webhookEvents.resend`) used to generate a
|
|
20
|
+
fresh UUIDv4 when you omitted one. That protected nothing: an idempotency key
|
|
21
|
+
only works if the SAME key comes back on a retry, and a key invented per call
|
|
22
|
+
is different every time. The header is now sent only when you pass a key.
|
|
23
|
+
|
|
24
|
+
This was not theoretical. On 2026-09-08 an integrator's HTTP client timed out
|
|
25
|
+
at 30s on a card charge that was still being created, retried, drew a fresh
|
|
26
|
+
UUIDv4, and charged a real buyer twice.
|
|
27
|
+
|
|
28
|
+
Docstrings that promised "Safe to retry: the same key returns the original
|
|
29
|
+
charge for 24h" were describing a guarantee the code did not provide. They now
|
|
30
|
+
say what actually happens.
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
|
|
34
|
+
- Behaviour change, no API change: requests where you omit `idempotencyKey` now
|
|
35
|
+
carry no `X-Idempotency-Key` header. Nothing rejects a missing key — the header
|
|
36
|
+
is optional on every gateway endpoint — and the gateway also gained a duplicate
|
|
37
|
+
guard that replays the original charge when the same buyer, product, rail and
|
|
38
|
+
instalment count arrive again within 60 seconds.
|
|
39
|
+
|
|
40
|
+
**To get real protection, pass a key derived from your own domain** so a retry
|
|
41
|
+
reproduces it:
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
await garu.charges.create({
|
|
45
|
+
productId,
|
|
46
|
+
paymentMethod: 'creditCard',
|
|
47
|
+
customer,
|
|
48
|
+
idempotencyKey: `booking:${booking.id}:charge`
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
- `generateIdempotencyKey()` is still exported and unchanged. It is only useful
|
|
53
|
+
if you store the result and reuse it across retries of the same operation.
|
|
54
|
+
|
|
6
55
|
## [4.1.0] — 2026-08-22
|
|
7
56
|
|
|
8
57
|
### Added
|
package/dist/index.cjs
CHANGED
|
@@ -188,8 +188,8 @@ function backoffDelay(attempt, retryAfterSec) {
|
|
|
188
188
|
function sleep(ms) {
|
|
189
189
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
190
190
|
}
|
|
191
|
-
function
|
|
192
|
-
return
|
|
191
|
+
function idempotencyHeaders(key) {
|
|
192
|
+
return key ? { "X-Idempotency-Key": key } : {};
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
// src/resources/charges.ts
|
|
@@ -201,9 +201,11 @@ var Charges = class {
|
|
|
201
201
|
/**
|
|
202
202
|
* Create a charge (PIX, boleto, or credit card).
|
|
203
203
|
*
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
204
|
+
* Pass `idempotencyKey` to make this safe to retry: the same key returns the
|
|
205
|
+
* original charge for 24h. Derive it from something stable in your own
|
|
206
|
+
* domain (an order id, a booking id) so a retry reproduces it. Omit it and
|
|
207
|
+
* no key is sent — the SDK does NOT invent one, because a key generated per
|
|
208
|
+
* call is different every time and protects nothing.
|
|
207
209
|
*
|
|
208
210
|
* @example
|
|
209
211
|
* // PIX — render charge.pix.code as a QR in your own checkout
|
|
@@ -236,7 +238,6 @@ var Charges = class {
|
|
|
236
238
|
* // charge.amount is the base price; charge.chargedTotal is what was charged.
|
|
237
239
|
*/
|
|
238
240
|
async create(params) {
|
|
239
|
-
const idempotencyKey = params.idempotencyKey ?? generateIdempotencyKey();
|
|
240
241
|
const body = {
|
|
241
242
|
productId: params.productId,
|
|
242
243
|
paymentMethod: params.paymentMethod,
|
|
@@ -245,7 +246,7 @@ var Charges = class {
|
|
|
245
246
|
if (params.card) body.card = params.card;
|
|
246
247
|
if (params.checkoutSessionToken) body.checkoutSessionToken = params.checkoutSessionToken;
|
|
247
248
|
if (params.additionalInfo !== void 0) body.additionalInfo = params.additionalInfo;
|
|
248
|
-
return this.post("/api/v1/charges", body,
|
|
249
|
+
return this.post("/api/v1/charges", body, idempotencyHeaders(params.idempotencyKey));
|
|
249
250
|
}
|
|
250
251
|
/**
|
|
251
252
|
* Retrieve a charge by uuid.
|
|
@@ -286,23 +287,20 @@ var Charges = class {
|
|
|
286
287
|
* settles.
|
|
287
288
|
*
|
|
288
289
|
* For Pix/boleto (which open a refund request instead of an automated
|
|
289
|
-
* reversal),
|
|
290
|
-
*
|
|
291
|
-
* card, which reverses automatically and has no manual request
|
|
292
|
-
* duplicate.
|
|
290
|
+
* reversal), pass `idempotencyKey` to make a retry return the original
|
|
291
|
+
* request rather than opening a second one; omit it and no key is sent.
|
|
292
|
+
* Ignored for card, which reverses automatically and has no manual request
|
|
293
|
+
* to duplicate.
|
|
293
294
|
*
|
|
294
295
|
* @example
|
|
295
296
|
* await garu.charges.refund('6f1c9b2e-...'); // full
|
|
296
297
|
* await garu.charges.refund('6f1c9b2e-...', { amount: 10.0 }); // R$10,00
|
|
297
298
|
*/
|
|
298
299
|
async refund(uuid, params = {}) {
|
|
299
|
-
const idempotencyKey = params.idempotencyKey ?? generateIdempotencyKey();
|
|
300
300
|
const body = {};
|
|
301
301
|
if (params.amount !== void 0) body.amount = params.amount;
|
|
302
302
|
if (params.reason !== void 0) body.reason = params.reason;
|
|
303
|
-
return this.post(`/api/v1/charges/${encodeURIComponent(uuid)}/refund`, body,
|
|
304
|
-
"X-Idempotency-Key": idempotencyKey
|
|
305
|
-
});
|
|
303
|
+
return this.post(`/api/v1/charges/${encodeURIComponent(uuid)}/refund`, body, idempotencyHeaders(params.idempotencyKey));
|
|
306
304
|
}
|
|
307
305
|
/**
|
|
308
306
|
* Cancel an unpaid charge.
|
|
@@ -343,10 +341,16 @@ var InstallmentPlans = class {
|
|
|
343
341
|
}
|
|
344
342
|
http;
|
|
345
343
|
/**
|
|
346
|
-
* Sell a product as a carnê.
|
|
347
|
-
*
|
|
348
|
-
*
|
|
349
|
-
*
|
|
344
|
+
* Sell a product as a carnê.
|
|
345
|
+
*
|
|
346
|
+
* Pass `idempotencyKey` to make this safe to retry: the same key returns the
|
|
347
|
+
* original plan for 24h. Derive it from something stable in your own
|
|
348
|
+
* domain (an order id, a booking id) so a retry reproduces it. Omit it and
|
|
349
|
+
* no key is sent — the SDK does NOT invent one, because a key generated per
|
|
350
|
+
* call is different every time and protects nothing.
|
|
351
|
+
* This matters more here than anywhere else in the API: the call registers a
|
|
352
|
+
* REAL boleto at the bank, so a retry without a key can put two payable
|
|
353
|
+
* barcodes in one buyer's hands.
|
|
350
354
|
*
|
|
351
355
|
* @example
|
|
352
356
|
* const carne = await garu.installmentPlans.create({
|
|
@@ -372,12 +376,11 @@ var InstallmentPlans = class {
|
|
|
372
376
|
* });
|
|
373
377
|
*/
|
|
374
378
|
async create(params) {
|
|
375
|
-
const idempotencyKey = params.idempotencyKey ?? generateIdempotencyKey();
|
|
376
379
|
const { idempotencyKey: _omit, ...body } = params;
|
|
377
380
|
return this.http.call(
|
|
378
381
|
(signal) => this.http.client.POST("/api/v1/installment-plans", {
|
|
379
382
|
body,
|
|
380
|
-
headers:
|
|
383
|
+
headers: idempotencyHeaders(params.idempotencyKey),
|
|
381
384
|
signal
|
|
382
385
|
}).then((r) => r)
|
|
383
386
|
);
|
|
@@ -520,10 +523,9 @@ var InstallmentPlans = class {
|
|
|
520
523
|
* team. Transfer the money to the buyer yourself, then close it with
|
|
521
524
|
* `garu.refundRequests.confirm`.
|
|
522
525
|
*
|
|
523
|
-
*
|
|
524
|
-
*
|
|
525
|
-
*
|
|
526
|
-
* defense-in-depth for the request-in-flight window.
|
|
526
|
+
* Pass `idempotencyKey` to cover the request-in-flight window; omit it and no
|
|
527
|
+
* key is sent. The backend already dedupes a second pending request for the
|
|
528
|
+
* same carnê, so this is defense-in-depth rather than the main guard.
|
|
527
529
|
*
|
|
528
530
|
* @example
|
|
529
531
|
* const request = await garu.installmentPlans.requestRefund(uuid, {
|
|
@@ -533,12 +535,11 @@ var InstallmentPlans = class {
|
|
|
533
535
|
* request.amount; // defaults to everything the carnê collected
|
|
534
536
|
*/
|
|
535
537
|
async requestRefund(uuid, params = {}) {
|
|
536
|
-
const idempotencyKey = params.idempotencyKey ?? generateIdempotencyKey();
|
|
537
538
|
const { idempotencyKey: _omit, ...body } = params;
|
|
538
539
|
return this.http.call(
|
|
539
540
|
(signal) => this.http.client.POST(`/api/v1/installment-plans/${uuid}/refund-requests`, {
|
|
540
541
|
body,
|
|
541
|
-
headers:
|
|
542
|
+
headers: idempotencyHeaders(params.idempotencyKey),
|
|
542
543
|
signal
|
|
543
544
|
}).then((r) => r)
|
|
544
545
|
);
|
|
@@ -646,9 +647,11 @@ var Customers = class {
|
|
|
646
647
|
/**
|
|
647
648
|
* Register a customer for the current seller.
|
|
648
649
|
*
|
|
649
|
-
*
|
|
650
|
-
*
|
|
651
|
-
*
|
|
650
|
+
* Pass `idempotencyKey` to make this safe to retry: the same key returns the
|
|
651
|
+
* original customer for 24h. Derive it from something stable in your own
|
|
652
|
+
* domain (an order id, a booking id) so a retry reproduces it. Omit it and
|
|
653
|
+
* no key is sent — the SDK does NOT invent one, because a key generated per
|
|
654
|
+
* call is different every time and protects nothing.
|
|
652
655
|
*
|
|
653
656
|
* @example
|
|
654
657
|
* const customer = await garu.customers.create({
|
|
@@ -661,12 +664,11 @@ var Customers = class {
|
|
|
661
664
|
* customer.uuid;
|
|
662
665
|
*/
|
|
663
666
|
async create(params) {
|
|
664
|
-
const idempotencyKey = params.idempotencyKey ?? generateIdempotencyKey();
|
|
665
667
|
const { idempotencyKey: _omit, ...body } = params;
|
|
666
668
|
return this.http.call(
|
|
667
669
|
(signal) => this.http.client.POST("/api/v1/customers", {
|
|
668
670
|
body,
|
|
669
|
-
headers:
|
|
671
|
+
headers: idempotencyHeaders(params.idempotencyKey),
|
|
670
672
|
signal
|
|
671
673
|
}).then((r) => r)
|
|
672
674
|
);
|
|
@@ -911,10 +913,11 @@ var Products = class {
|
|
|
911
913
|
* product (HTTP 201). Only `name` is required; everything else falls back
|
|
912
914
|
* to seller/server defaults.
|
|
913
915
|
*
|
|
914
|
-
*
|
|
915
|
-
*
|
|
916
|
-
*
|
|
917
|
-
*
|
|
916
|
+
* Pass `idempotencyKey` to make this safe to retry: the same key returns the
|
|
917
|
+
* original product for 24h. Derive it from something stable in your own
|
|
918
|
+
* domain (an order id, a booking id) so a retry reproduces it. Omit it and
|
|
919
|
+
* no key is sent — the SDK does NOT invent one, because a key generated per
|
|
920
|
+
* call is different every time and protects nothing.
|
|
918
921
|
*
|
|
919
922
|
* @example
|
|
920
923
|
* const product = await garu.products.create({
|
|
@@ -930,11 +933,10 @@ var Products = class {
|
|
|
930
933
|
*/
|
|
931
934
|
async create(params) {
|
|
932
935
|
const { idempotencyKey, ...body } = params;
|
|
933
|
-
const key = idempotencyKey ?? generateIdempotencyKey();
|
|
934
936
|
return this.http.call(
|
|
935
937
|
(signal) => this.http.client.POST("/api/v1/products", {
|
|
936
938
|
body,
|
|
937
|
-
headers:
|
|
939
|
+
headers: idempotencyHeaders(idempotencyKey),
|
|
938
940
|
signal
|
|
939
941
|
}).then((r) => r)
|
|
940
942
|
);
|
|
@@ -970,10 +972,15 @@ var ScheduledCharges = class {
|
|
|
970
972
|
}
|
|
971
973
|
http;
|
|
972
974
|
/**
|
|
973
|
-
* Create a new scheduled charge.
|
|
974
|
-
*
|
|
975
|
-
*
|
|
976
|
-
* series for 24h
|
|
975
|
+
* Create a new scheduled charge.
|
|
976
|
+
*
|
|
977
|
+
* Pass `idempotencyKey` to make this safe to retry: the same key returns the
|
|
978
|
+
* original series for 24h. Derive it from something stable in your own
|
|
979
|
+
* domain (an order id, a booking id) so a retry reproduces it. Omit it and
|
|
980
|
+
* no key is sent — the SDK does NOT invent one, because a key generated per
|
|
981
|
+
* call is different every time and protects nothing.
|
|
982
|
+
* Worth the effort here: without a key, a retry double-books recurring
|
|
983
|
+
* billing for the same customer.
|
|
977
984
|
*
|
|
978
985
|
* @example
|
|
979
986
|
* const charge = await garu.scheduledCharges.create({
|
|
@@ -1000,12 +1007,11 @@ var ScheduledCharges = class {
|
|
|
1000
1007
|
* });
|
|
1001
1008
|
*/
|
|
1002
1009
|
async create(params) {
|
|
1003
|
-
const idempotencyKey = params.idempotencyKey ?? generateIdempotencyKey();
|
|
1004
1010
|
const { idempotencyKey: _omit, ...body } = params;
|
|
1005
1011
|
return this.http.call(
|
|
1006
1012
|
(signal) => this.http.client.POST("/api/v1/scheduled-charges", {
|
|
1007
1013
|
body,
|
|
1008
|
-
headers:
|
|
1014
|
+
headers: idempotencyHeaders(params.idempotencyKey),
|
|
1009
1015
|
signal
|
|
1010
1016
|
}).then((r) => r)
|
|
1011
1017
|
);
|
|
@@ -1394,11 +1400,10 @@ var WebhookEvents = class {
|
|
|
1394
1400
|
* original — distinguishable both by the `resend_` prefix and by reading
|
|
1395
1401
|
* the response payload's `manualResendOf` field.
|
|
1396
1402
|
*
|
|
1397
|
-
*
|
|
1398
|
-
*
|
|
1399
|
-
*
|
|
1400
|
-
*
|
|
1401
|
-
* your own retry-suppression if that matters for your integration.
|
|
1403
|
+
* `idempotencyKey` is forwarded when you pass one and omitted when you don't.
|
|
1404
|
+
* Either way the gateway does not currently deduplicate `/resend` calls
|
|
1405
|
+
* against it, so retrying after a network failure can create more than one
|
|
1406
|
+
* clone — pair it with your own retry-suppression if that matters.
|
|
1402
1407
|
*
|
|
1403
1408
|
* Returns the *clone* event (new uuid), not the original. The original is
|
|
1404
1409
|
* unchanged on the server.
|
|
@@ -1410,11 +1415,10 @@ var WebhookEvents = class {
|
|
|
1410
1415
|
* clone.manualResendOf === event.uuid; // true — points back at the source
|
|
1411
1416
|
*/
|
|
1412
1417
|
async resend(uuid, params = {}) {
|
|
1413
|
-
const idempotencyKey = params.idempotencyKey ?? generateIdempotencyKey();
|
|
1414
1418
|
return this.http.call(
|
|
1415
1419
|
(signal) => this.http.client.POST(`/api/v1/webhook-events/${uuid}/resend`, {
|
|
1416
1420
|
body: {},
|
|
1417
|
-
headers:
|
|
1421
|
+
headers: idempotencyHeaders(params.idempotencyKey),
|
|
1418
1422
|
signal
|
|
1419
1423
|
}).then((r) => r)
|
|
1420
1424
|
);
|
package/dist/index.d.cts
CHANGED
|
@@ -1100,9 +1100,11 @@ declare class Charges {
|
|
|
1100
1100
|
/**
|
|
1101
1101
|
* Create a charge (PIX, boleto, or credit card).
|
|
1102
1102
|
*
|
|
1103
|
-
*
|
|
1104
|
-
*
|
|
1105
|
-
*
|
|
1103
|
+
* Pass `idempotencyKey` to make this safe to retry: the same key returns the
|
|
1104
|
+
* original charge for 24h. Derive it from something stable in your own
|
|
1105
|
+
* domain (an order id, a booking id) so a retry reproduces it. Omit it and
|
|
1106
|
+
* no key is sent — the SDK does NOT invent one, because a key generated per
|
|
1107
|
+
* call is different every time and protects nothing.
|
|
1106
1108
|
*
|
|
1107
1109
|
* @example
|
|
1108
1110
|
* // PIX — render charge.pix.code as a QR in your own checkout
|
|
@@ -1159,10 +1161,10 @@ declare class Charges {
|
|
|
1159
1161
|
* settles.
|
|
1160
1162
|
*
|
|
1161
1163
|
* For Pix/boleto (which open a refund request instead of an automated
|
|
1162
|
-
* reversal),
|
|
1163
|
-
*
|
|
1164
|
-
* card, which reverses automatically and has no manual request
|
|
1165
|
-
* duplicate.
|
|
1164
|
+
* reversal), pass `idempotencyKey` to make a retry return the original
|
|
1165
|
+
* request rather than opening a second one; omit it and no key is sent.
|
|
1166
|
+
* Ignored for card, which reverses automatically and has no manual request
|
|
1167
|
+
* to duplicate.
|
|
1166
1168
|
*
|
|
1167
1169
|
* @example
|
|
1168
1170
|
* await garu.charges.refund('6f1c9b2e-...'); // full
|
|
@@ -1196,10 +1198,16 @@ declare class InstallmentPlans {
|
|
|
1196
1198
|
private readonly http;
|
|
1197
1199
|
constructor(http: HttpClient);
|
|
1198
1200
|
/**
|
|
1199
|
-
* Sell a product as a carnê.
|
|
1200
|
-
*
|
|
1201
|
-
*
|
|
1202
|
-
*
|
|
1201
|
+
* Sell a product as a carnê.
|
|
1202
|
+
*
|
|
1203
|
+
* Pass `idempotencyKey` to make this safe to retry: the same key returns the
|
|
1204
|
+
* original plan for 24h. Derive it from something stable in your own
|
|
1205
|
+
* domain (an order id, a booking id) so a retry reproduces it. Omit it and
|
|
1206
|
+
* no key is sent — the SDK does NOT invent one, because a key generated per
|
|
1207
|
+
* call is different every time and protects nothing.
|
|
1208
|
+
* This matters more here than anywhere else in the API: the call registers a
|
|
1209
|
+
* REAL boleto at the bank, so a retry without a key can put two payable
|
|
1210
|
+
* barcodes in one buyer's hands.
|
|
1203
1211
|
*
|
|
1204
1212
|
* @example
|
|
1205
1213
|
* const carne = await garu.installmentPlans.create({
|
|
@@ -1310,10 +1318,9 @@ declare class InstallmentPlans {
|
|
|
1310
1318
|
* team. Transfer the money to the buyer yourself, then close it with
|
|
1311
1319
|
* `garu.refundRequests.confirm`.
|
|
1312
1320
|
*
|
|
1313
|
-
*
|
|
1314
|
-
*
|
|
1315
|
-
*
|
|
1316
|
-
* defense-in-depth for the request-in-flight window.
|
|
1321
|
+
* Pass `idempotencyKey` to cover the request-in-flight window; omit it and no
|
|
1322
|
+
* key is sent. The backend already dedupes a second pending request for the
|
|
1323
|
+
* same carnê, so this is defense-in-depth rather than the main guard.
|
|
1317
1324
|
*
|
|
1318
1325
|
* @example
|
|
1319
1326
|
* const request = await garu.installmentPlans.requestRefund(uuid, {
|
|
@@ -1404,9 +1411,11 @@ declare class Customers {
|
|
|
1404
1411
|
/**
|
|
1405
1412
|
* Register a customer for the current seller.
|
|
1406
1413
|
*
|
|
1407
|
-
*
|
|
1408
|
-
*
|
|
1409
|
-
*
|
|
1414
|
+
* Pass `idempotencyKey` to make this safe to retry: the same key returns the
|
|
1415
|
+
* original customer for 24h. Derive it from something stable in your own
|
|
1416
|
+
* domain (an order id, a booking id) so a retry reproduces it. Omit it and
|
|
1417
|
+
* no key is sent — the SDK does NOT invent one, because a key generated per
|
|
1418
|
+
* call is different every time and protects nothing.
|
|
1410
1419
|
*
|
|
1411
1420
|
* @example
|
|
1412
1421
|
* const customer = await garu.customers.create({
|
|
@@ -1576,10 +1585,11 @@ declare class Products {
|
|
|
1576
1585
|
* product (HTTP 201). Only `name` is required; everything else falls back
|
|
1577
1586
|
* to seller/server defaults.
|
|
1578
1587
|
*
|
|
1579
|
-
*
|
|
1580
|
-
*
|
|
1581
|
-
*
|
|
1582
|
-
*
|
|
1588
|
+
* Pass `idempotencyKey` to make this safe to retry: the same key returns the
|
|
1589
|
+
* original product for 24h. Derive it from something stable in your own
|
|
1590
|
+
* domain (an order id, a booking id) so a retry reproduces it. Omit it and
|
|
1591
|
+
* no key is sent — the SDK does NOT invent one, because a key generated per
|
|
1592
|
+
* call is different every time and protects nothing.
|
|
1583
1593
|
*
|
|
1584
1594
|
* @example
|
|
1585
1595
|
* const product = await garu.products.create({
|
|
@@ -1629,10 +1639,15 @@ declare class ScheduledCharges {
|
|
|
1629
1639
|
private readonly http;
|
|
1630
1640
|
constructor(http: HttpClient);
|
|
1631
1641
|
/**
|
|
1632
|
-
* Create a new scheduled charge.
|
|
1633
|
-
*
|
|
1634
|
-
*
|
|
1635
|
-
* series for 24h
|
|
1642
|
+
* Create a new scheduled charge.
|
|
1643
|
+
*
|
|
1644
|
+
* Pass `idempotencyKey` to make this safe to retry: the same key returns the
|
|
1645
|
+
* original series for 24h. Derive it from something stable in your own
|
|
1646
|
+
* domain (an order id, a booking id) so a retry reproduces it. Omit it and
|
|
1647
|
+
* no key is sent — the SDK does NOT invent one, because a key generated per
|
|
1648
|
+
* call is different every time and protects nothing.
|
|
1649
|
+
* Worth the effort here: without a key, a retry double-books recurring
|
|
1650
|
+
* billing for the same customer.
|
|
1636
1651
|
*
|
|
1637
1652
|
* @example
|
|
1638
1653
|
* const charge = await garu.scheduledCharges.create({
|
|
@@ -1899,11 +1914,10 @@ declare class WebhookEvents {
|
|
|
1899
1914
|
* original — distinguishable both by the `resend_` prefix and by reading
|
|
1900
1915
|
* the response payload's `manualResendOf` field.
|
|
1901
1916
|
*
|
|
1902
|
-
*
|
|
1903
|
-
*
|
|
1904
|
-
*
|
|
1905
|
-
*
|
|
1906
|
-
* your own retry-suppression if that matters for your integration.
|
|
1917
|
+
* `idempotencyKey` is forwarded when you pass one and omitted when you don't.
|
|
1918
|
+
* Either way the gateway does not currently deduplicate `/resend` calls
|
|
1919
|
+
* against it, so retrying after a network failure can create more than one
|
|
1920
|
+
* clone — pair it with your own retry-suppression if that matters.
|
|
1907
1921
|
*
|
|
1908
1922
|
* Returns the *clone* event (new uuid), not the original. The original is
|
|
1909
1923
|
* unchanged on the server.
|
package/dist/index.d.ts
CHANGED
|
@@ -1100,9 +1100,11 @@ declare class Charges {
|
|
|
1100
1100
|
/**
|
|
1101
1101
|
* Create a charge (PIX, boleto, or credit card).
|
|
1102
1102
|
*
|
|
1103
|
-
*
|
|
1104
|
-
*
|
|
1105
|
-
*
|
|
1103
|
+
* Pass `idempotencyKey` to make this safe to retry: the same key returns the
|
|
1104
|
+
* original charge for 24h. Derive it from something stable in your own
|
|
1105
|
+
* domain (an order id, a booking id) so a retry reproduces it. Omit it and
|
|
1106
|
+
* no key is sent — the SDK does NOT invent one, because a key generated per
|
|
1107
|
+
* call is different every time and protects nothing.
|
|
1106
1108
|
*
|
|
1107
1109
|
* @example
|
|
1108
1110
|
* // PIX — render charge.pix.code as a QR in your own checkout
|
|
@@ -1159,10 +1161,10 @@ declare class Charges {
|
|
|
1159
1161
|
* settles.
|
|
1160
1162
|
*
|
|
1161
1163
|
* For Pix/boleto (which open a refund request instead of an automated
|
|
1162
|
-
* reversal),
|
|
1163
|
-
*
|
|
1164
|
-
* card, which reverses automatically and has no manual request
|
|
1165
|
-
* duplicate.
|
|
1164
|
+
* reversal), pass `idempotencyKey` to make a retry return the original
|
|
1165
|
+
* request rather than opening a second one; omit it and no key is sent.
|
|
1166
|
+
* Ignored for card, which reverses automatically and has no manual request
|
|
1167
|
+
* to duplicate.
|
|
1166
1168
|
*
|
|
1167
1169
|
* @example
|
|
1168
1170
|
* await garu.charges.refund('6f1c9b2e-...'); // full
|
|
@@ -1196,10 +1198,16 @@ declare class InstallmentPlans {
|
|
|
1196
1198
|
private readonly http;
|
|
1197
1199
|
constructor(http: HttpClient);
|
|
1198
1200
|
/**
|
|
1199
|
-
* Sell a product as a carnê.
|
|
1200
|
-
*
|
|
1201
|
-
*
|
|
1202
|
-
*
|
|
1201
|
+
* Sell a product as a carnê.
|
|
1202
|
+
*
|
|
1203
|
+
* Pass `idempotencyKey` to make this safe to retry: the same key returns the
|
|
1204
|
+
* original plan for 24h. Derive it from something stable in your own
|
|
1205
|
+
* domain (an order id, a booking id) so a retry reproduces it. Omit it and
|
|
1206
|
+
* no key is sent — the SDK does NOT invent one, because a key generated per
|
|
1207
|
+
* call is different every time and protects nothing.
|
|
1208
|
+
* This matters more here than anywhere else in the API: the call registers a
|
|
1209
|
+
* REAL boleto at the bank, so a retry without a key can put two payable
|
|
1210
|
+
* barcodes in one buyer's hands.
|
|
1203
1211
|
*
|
|
1204
1212
|
* @example
|
|
1205
1213
|
* const carne = await garu.installmentPlans.create({
|
|
@@ -1310,10 +1318,9 @@ declare class InstallmentPlans {
|
|
|
1310
1318
|
* team. Transfer the money to the buyer yourself, then close it with
|
|
1311
1319
|
* `garu.refundRequests.confirm`.
|
|
1312
1320
|
*
|
|
1313
|
-
*
|
|
1314
|
-
*
|
|
1315
|
-
*
|
|
1316
|
-
* defense-in-depth for the request-in-flight window.
|
|
1321
|
+
* Pass `idempotencyKey` to cover the request-in-flight window; omit it and no
|
|
1322
|
+
* key is sent. The backend already dedupes a second pending request for the
|
|
1323
|
+
* same carnê, so this is defense-in-depth rather than the main guard.
|
|
1317
1324
|
*
|
|
1318
1325
|
* @example
|
|
1319
1326
|
* const request = await garu.installmentPlans.requestRefund(uuid, {
|
|
@@ -1404,9 +1411,11 @@ declare class Customers {
|
|
|
1404
1411
|
/**
|
|
1405
1412
|
* Register a customer for the current seller.
|
|
1406
1413
|
*
|
|
1407
|
-
*
|
|
1408
|
-
*
|
|
1409
|
-
*
|
|
1414
|
+
* Pass `idempotencyKey` to make this safe to retry: the same key returns the
|
|
1415
|
+
* original customer for 24h. Derive it from something stable in your own
|
|
1416
|
+
* domain (an order id, a booking id) so a retry reproduces it. Omit it and
|
|
1417
|
+
* no key is sent — the SDK does NOT invent one, because a key generated per
|
|
1418
|
+
* call is different every time and protects nothing.
|
|
1410
1419
|
*
|
|
1411
1420
|
* @example
|
|
1412
1421
|
* const customer = await garu.customers.create({
|
|
@@ -1576,10 +1585,11 @@ declare class Products {
|
|
|
1576
1585
|
* product (HTTP 201). Only `name` is required; everything else falls back
|
|
1577
1586
|
* to seller/server defaults.
|
|
1578
1587
|
*
|
|
1579
|
-
*
|
|
1580
|
-
*
|
|
1581
|
-
*
|
|
1582
|
-
*
|
|
1588
|
+
* Pass `idempotencyKey` to make this safe to retry: the same key returns the
|
|
1589
|
+
* original product for 24h. Derive it from something stable in your own
|
|
1590
|
+
* domain (an order id, a booking id) so a retry reproduces it. Omit it and
|
|
1591
|
+
* no key is sent — the SDK does NOT invent one, because a key generated per
|
|
1592
|
+
* call is different every time and protects nothing.
|
|
1583
1593
|
*
|
|
1584
1594
|
* @example
|
|
1585
1595
|
* const product = await garu.products.create({
|
|
@@ -1629,10 +1639,15 @@ declare class ScheduledCharges {
|
|
|
1629
1639
|
private readonly http;
|
|
1630
1640
|
constructor(http: HttpClient);
|
|
1631
1641
|
/**
|
|
1632
|
-
* Create a new scheduled charge.
|
|
1633
|
-
*
|
|
1634
|
-
*
|
|
1635
|
-
* series for 24h
|
|
1642
|
+
* Create a new scheduled charge.
|
|
1643
|
+
*
|
|
1644
|
+
* Pass `idempotencyKey` to make this safe to retry: the same key returns the
|
|
1645
|
+
* original series for 24h. Derive it from something stable in your own
|
|
1646
|
+
* domain (an order id, a booking id) so a retry reproduces it. Omit it and
|
|
1647
|
+
* no key is sent — the SDK does NOT invent one, because a key generated per
|
|
1648
|
+
* call is different every time and protects nothing.
|
|
1649
|
+
* Worth the effort here: without a key, a retry double-books recurring
|
|
1650
|
+
* billing for the same customer.
|
|
1636
1651
|
*
|
|
1637
1652
|
* @example
|
|
1638
1653
|
* const charge = await garu.scheduledCharges.create({
|
|
@@ -1899,11 +1914,10 @@ declare class WebhookEvents {
|
|
|
1899
1914
|
* original — distinguishable both by the `resend_` prefix and by reading
|
|
1900
1915
|
* the response payload's `manualResendOf` field.
|
|
1901
1916
|
*
|
|
1902
|
-
*
|
|
1903
|
-
*
|
|
1904
|
-
*
|
|
1905
|
-
*
|
|
1906
|
-
* your own retry-suppression if that matters for your integration.
|
|
1917
|
+
* `idempotencyKey` is forwarded when you pass one and omitted when you don't.
|
|
1918
|
+
* Either way the gateway does not currently deduplicate `/resend` calls
|
|
1919
|
+
* against it, so retrying after a network failure can create more than one
|
|
1920
|
+
* clone — pair it with your own retry-suppression if that matters.
|
|
1907
1921
|
*
|
|
1908
1922
|
* Returns the *clone* event (new uuid), not the original. The original is
|
|
1909
1923
|
* unchanged on the server.
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import createClient from 'openapi-fetch';
|
|
2
|
-
import { createHmac, timingSafeEqual
|
|
2
|
+
import { createHmac, timingSafeEqual } from 'crypto';
|
|
3
3
|
|
|
4
4
|
// src/http.ts
|
|
5
5
|
|
|
@@ -182,8 +182,8 @@ function backoffDelay(attempt, retryAfterSec) {
|
|
|
182
182
|
function sleep(ms) {
|
|
183
183
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
184
184
|
}
|
|
185
|
-
function
|
|
186
|
-
return
|
|
185
|
+
function idempotencyHeaders(key) {
|
|
186
|
+
return key ? { "X-Idempotency-Key": key } : {};
|
|
187
187
|
}
|
|
188
188
|
|
|
189
189
|
// src/resources/charges.ts
|
|
@@ -195,9 +195,11 @@ var Charges = class {
|
|
|
195
195
|
/**
|
|
196
196
|
* Create a charge (PIX, boleto, or credit card).
|
|
197
197
|
*
|
|
198
|
-
*
|
|
199
|
-
*
|
|
200
|
-
*
|
|
198
|
+
* Pass `idempotencyKey` to make this safe to retry: the same key returns the
|
|
199
|
+
* original charge for 24h. Derive it from something stable in your own
|
|
200
|
+
* domain (an order id, a booking id) so a retry reproduces it. Omit it and
|
|
201
|
+
* no key is sent — the SDK does NOT invent one, because a key generated per
|
|
202
|
+
* call is different every time and protects nothing.
|
|
201
203
|
*
|
|
202
204
|
* @example
|
|
203
205
|
* // PIX — render charge.pix.code as a QR in your own checkout
|
|
@@ -230,7 +232,6 @@ var Charges = class {
|
|
|
230
232
|
* // charge.amount is the base price; charge.chargedTotal is what was charged.
|
|
231
233
|
*/
|
|
232
234
|
async create(params) {
|
|
233
|
-
const idempotencyKey = params.idempotencyKey ?? generateIdempotencyKey();
|
|
234
235
|
const body = {
|
|
235
236
|
productId: params.productId,
|
|
236
237
|
paymentMethod: params.paymentMethod,
|
|
@@ -239,7 +240,7 @@ var Charges = class {
|
|
|
239
240
|
if (params.card) body.card = params.card;
|
|
240
241
|
if (params.checkoutSessionToken) body.checkoutSessionToken = params.checkoutSessionToken;
|
|
241
242
|
if (params.additionalInfo !== void 0) body.additionalInfo = params.additionalInfo;
|
|
242
|
-
return this.post("/api/v1/charges", body,
|
|
243
|
+
return this.post("/api/v1/charges", body, idempotencyHeaders(params.idempotencyKey));
|
|
243
244
|
}
|
|
244
245
|
/**
|
|
245
246
|
* Retrieve a charge by uuid.
|
|
@@ -280,23 +281,20 @@ var Charges = class {
|
|
|
280
281
|
* settles.
|
|
281
282
|
*
|
|
282
283
|
* For Pix/boleto (which open a refund request instead of an automated
|
|
283
|
-
* reversal),
|
|
284
|
-
*
|
|
285
|
-
* card, which reverses automatically and has no manual request
|
|
286
|
-
* duplicate.
|
|
284
|
+
* reversal), pass `idempotencyKey` to make a retry return the original
|
|
285
|
+
* request rather than opening a second one; omit it and no key is sent.
|
|
286
|
+
* Ignored for card, which reverses automatically and has no manual request
|
|
287
|
+
* to duplicate.
|
|
287
288
|
*
|
|
288
289
|
* @example
|
|
289
290
|
* await garu.charges.refund('6f1c9b2e-...'); // full
|
|
290
291
|
* await garu.charges.refund('6f1c9b2e-...', { amount: 10.0 }); // R$10,00
|
|
291
292
|
*/
|
|
292
293
|
async refund(uuid, params = {}) {
|
|
293
|
-
const idempotencyKey = params.idempotencyKey ?? generateIdempotencyKey();
|
|
294
294
|
const body = {};
|
|
295
295
|
if (params.amount !== void 0) body.amount = params.amount;
|
|
296
296
|
if (params.reason !== void 0) body.reason = params.reason;
|
|
297
|
-
return this.post(`/api/v1/charges/${encodeURIComponent(uuid)}/refund`, body,
|
|
298
|
-
"X-Idempotency-Key": idempotencyKey
|
|
299
|
-
});
|
|
297
|
+
return this.post(`/api/v1/charges/${encodeURIComponent(uuid)}/refund`, body, idempotencyHeaders(params.idempotencyKey));
|
|
300
298
|
}
|
|
301
299
|
/**
|
|
302
300
|
* Cancel an unpaid charge.
|
|
@@ -337,10 +335,16 @@ var InstallmentPlans = class {
|
|
|
337
335
|
}
|
|
338
336
|
http;
|
|
339
337
|
/**
|
|
340
|
-
* Sell a product as a carnê.
|
|
341
|
-
*
|
|
342
|
-
*
|
|
343
|
-
*
|
|
338
|
+
* Sell a product as a carnê.
|
|
339
|
+
*
|
|
340
|
+
* Pass `idempotencyKey` to make this safe to retry: the same key returns the
|
|
341
|
+
* original plan for 24h. Derive it from something stable in your own
|
|
342
|
+
* domain (an order id, a booking id) so a retry reproduces it. Omit it and
|
|
343
|
+
* no key is sent — the SDK does NOT invent one, because a key generated per
|
|
344
|
+
* call is different every time and protects nothing.
|
|
345
|
+
* This matters more here than anywhere else in the API: the call registers a
|
|
346
|
+
* REAL boleto at the bank, so a retry without a key can put two payable
|
|
347
|
+
* barcodes in one buyer's hands.
|
|
344
348
|
*
|
|
345
349
|
* @example
|
|
346
350
|
* const carne = await garu.installmentPlans.create({
|
|
@@ -366,12 +370,11 @@ var InstallmentPlans = class {
|
|
|
366
370
|
* });
|
|
367
371
|
*/
|
|
368
372
|
async create(params) {
|
|
369
|
-
const idempotencyKey = params.idempotencyKey ?? generateIdempotencyKey();
|
|
370
373
|
const { idempotencyKey: _omit, ...body } = params;
|
|
371
374
|
return this.http.call(
|
|
372
375
|
(signal) => this.http.client.POST("/api/v1/installment-plans", {
|
|
373
376
|
body,
|
|
374
|
-
headers:
|
|
377
|
+
headers: idempotencyHeaders(params.idempotencyKey),
|
|
375
378
|
signal
|
|
376
379
|
}).then((r) => r)
|
|
377
380
|
);
|
|
@@ -514,10 +517,9 @@ var InstallmentPlans = class {
|
|
|
514
517
|
* team. Transfer the money to the buyer yourself, then close it with
|
|
515
518
|
* `garu.refundRequests.confirm`.
|
|
516
519
|
*
|
|
517
|
-
*
|
|
518
|
-
*
|
|
519
|
-
*
|
|
520
|
-
* defense-in-depth for the request-in-flight window.
|
|
520
|
+
* Pass `idempotencyKey` to cover the request-in-flight window; omit it and no
|
|
521
|
+
* key is sent. The backend already dedupes a second pending request for the
|
|
522
|
+
* same carnê, so this is defense-in-depth rather than the main guard.
|
|
521
523
|
*
|
|
522
524
|
* @example
|
|
523
525
|
* const request = await garu.installmentPlans.requestRefund(uuid, {
|
|
@@ -527,12 +529,11 @@ var InstallmentPlans = class {
|
|
|
527
529
|
* request.amount; // defaults to everything the carnê collected
|
|
528
530
|
*/
|
|
529
531
|
async requestRefund(uuid, params = {}) {
|
|
530
|
-
const idempotencyKey = params.idempotencyKey ?? generateIdempotencyKey();
|
|
531
532
|
const { idempotencyKey: _omit, ...body } = params;
|
|
532
533
|
return this.http.call(
|
|
533
534
|
(signal) => this.http.client.POST(`/api/v1/installment-plans/${uuid}/refund-requests`, {
|
|
534
535
|
body,
|
|
535
|
-
headers:
|
|
536
|
+
headers: idempotencyHeaders(params.idempotencyKey),
|
|
536
537
|
signal
|
|
537
538
|
}).then((r) => r)
|
|
538
539
|
);
|
|
@@ -640,9 +641,11 @@ var Customers = class {
|
|
|
640
641
|
/**
|
|
641
642
|
* Register a customer for the current seller.
|
|
642
643
|
*
|
|
643
|
-
*
|
|
644
|
-
*
|
|
645
|
-
*
|
|
644
|
+
* Pass `idempotencyKey` to make this safe to retry: the same key returns the
|
|
645
|
+
* original customer for 24h. Derive it from something stable in your own
|
|
646
|
+
* domain (an order id, a booking id) so a retry reproduces it. Omit it and
|
|
647
|
+
* no key is sent — the SDK does NOT invent one, because a key generated per
|
|
648
|
+
* call is different every time and protects nothing.
|
|
646
649
|
*
|
|
647
650
|
* @example
|
|
648
651
|
* const customer = await garu.customers.create({
|
|
@@ -655,12 +658,11 @@ var Customers = class {
|
|
|
655
658
|
* customer.uuid;
|
|
656
659
|
*/
|
|
657
660
|
async create(params) {
|
|
658
|
-
const idempotencyKey = params.idempotencyKey ?? generateIdempotencyKey();
|
|
659
661
|
const { idempotencyKey: _omit, ...body } = params;
|
|
660
662
|
return this.http.call(
|
|
661
663
|
(signal) => this.http.client.POST("/api/v1/customers", {
|
|
662
664
|
body,
|
|
663
|
-
headers:
|
|
665
|
+
headers: idempotencyHeaders(params.idempotencyKey),
|
|
664
666
|
signal
|
|
665
667
|
}).then((r) => r)
|
|
666
668
|
);
|
|
@@ -905,10 +907,11 @@ var Products = class {
|
|
|
905
907
|
* product (HTTP 201). Only `name` is required; everything else falls back
|
|
906
908
|
* to seller/server defaults.
|
|
907
909
|
*
|
|
908
|
-
*
|
|
909
|
-
*
|
|
910
|
-
*
|
|
911
|
-
*
|
|
910
|
+
* Pass `idempotencyKey` to make this safe to retry: the same key returns the
|
|
911
|
+
* original product for 24h. Derive it from something stable in your own
|
|
912
|
+
* domain (an order id, a booking id) so a retry reproduces it. Omit it and
|
|
913
|
+
* no key is sent — the SDK does NOT invent one, because a key generated per
|
|
914
|
+
* call is different every time and protects nothing.
|
|
912
915
|
*
|
|
913
916
|
* @example
|
|
914
917
|
* const product = await garu.products.create({
|
|
@@ -924,11 +927,10 @@ var Products = class {
|
|
|
924
927
|
*/
|
|
925
928
|
async create(params) {
|
|
926
929
|
const { idempotencyKey, ...body } = params;
|
|
927
|
-
const key = idempotencyKey ?? generateIdempotencyKey();
|
|
928
930
|
return this.http.call(
|
|
929
931
|
(signal) => this.http.client.POST("/api/v1/products", {
|
|
930
932
|
body,
|
|
931
|
-
headers:
|
|
933
|
+
headers: idempotencyHeaders(idempotencyKey),
|
|
932
934
|
signal
|
|
933
935
|
}).then((r) => r)
|
|
934
936
|
);
|
|
@@ -964,10 +966,15 @@ var ScheduledCharges = class {
|
|
|
964
966
|
}
|
|
965
967
|
http;
|
|
966
968
|
/**
|
|
967
|
-
* Create a new scheduled charge.
|
|
968
|
-
*
|
|
969
|
-
*
|
|
970
|
-
* series for 24h
|
|
969
|
+
* Create a new scheduled charge.
|
|
970
|
+
*
|
|
971
|
+
* Pass `idempotencyKey` to make this safe to retry: the same key returns the
|
|
972
|
+
* original series for 24h. Derive it from something stable in your own
|
|
973
|
+
* domain (an order id, a booking id) so a retry reproduces it. Omit it and
|
|
974
|
+
* no key is sent — the SDK does NOT invent one, because a key generated per
|
|
975
|
+
* call is different every time and protects nothing.
|
|
976
|
+
* Worth the effort here: without a key, a retry double-books recurring
|
|
977
|
+
* billing for the same customer.
|
|
971
978
|
*
|
|
972
979
|
* @example
|
|
973
980
|
* const charge = await garu.scheduledCharges.create({
|
|
@@ -994,12 +1001,11 @@ var ScheduledCharges = class {
|
|
|
994
1001
|
* });
|
|
995
1002
|
*/
|
|
996
1003
|
async create(params) {
|
|
997
|
-
const idempotencyKey = params.idempotencyKey ?? generateIdempotencyKey();
|
|
998
1004
|
const { idempotencyKey: _omit, ...body } = params;
|
|
999
1005
|
return this.http.call(
|
|
1000
1006
|
(signal) => this.http.client.POST("/api/v1/scheduled-charges", {
|
|
1001
1007
|
body,
|
|
1002
|
-
headers:
|
|
1008
|
+
headers: idempotencyHeaders(params.idempotencyKey),
|
|
1003
1009
|
signal
|
|
1004
1010
|
}).then((r) => r)
|
|
1005
1011
|
);
|
|
@@ -1388,11 +1394,10 @@ var WebhookEvents = class {
|
|
|
1388
1394
|
* original — distinguishable both by the `resend_` prefix and by reading
|
|
1389
1395
|
* the response payload's `manualResendOf` field.
|
|
1390
1396
|
*
|
|
1391
|
-
*
|
|
1392
|
-
*
|
|
1393
|
-
*
|
|
1394
|
-
*
|
|
1395
|
-
* your own retry-suppression if that matters for your integration.
|
|
1397
|
+
* `idempotencyKey` is forwarded when you pass one and omitted when you don't.
|
|
1398
|
+
* Either way the gateway does not currently deduplicate `/resend` calls
|
|
1399
|
+
* against it, so retrying after a network failure can create more than one
|
|
1400
|
+
* clone — pair it with your own retry-suppression if that matters.
|
|
1396
1401
|
*
|
|
1397
1402
|
* Returns the *clone* event (new uuid), not the original. The original is
|
|
1398
1403
|
* unchanged on the server.
|
|
@@ -1404,11 +1409,10 @@ var WebhookEvents = class {
|
|
|
1404
1409
|
* clone.manualResendOf === event.uuid; // true — points back at the source
|
|
1405
1410
|
*/
|
|
1406
1411
|
async resend(uuid, params = {}) {
|
|
1407
|
-
const idempotencyKey = params.idempotencyKey ?? generateIdempotencyKey();
|
|
1408
1412
|
return this.http.call(
|
|
1409
1413
|
(signal) => this.http.client.POST(`/api/v1/webhook-events/${uuid}/resend`, {
|
|
1410
1414
|
body: {},
|
|
1411
|
-
headers:
|
|
1415
|
+
headers: idempotencyHeaders(params.idempotencyKey),
|
|
1412
1416
|
signal
|
|
1413
1417
|
}).then((r) => r)
|
|
1414
1418
|
);
|