@garuhq/node 0.4.0 → 0.5.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 CHANGED
@@ -3,6 +3,41 @@
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.5.0] — 2026-05-01
7
+
8
+ ### Added
9
+
10
+ - `scheduledCharges` resource on the `Garu` client. Schedule a charge to
11
+ bill a customer on a future date; Garu drives the customer reminder
12
+ on the due date and dunning to the seller team after.
13
+ - `scheduledCharges.create({ customerId, amount, type, dueDate, methods, ... })`
14
+ — `POST /api/scheduled-charges`. PIX and Boleto are supported now;
15
+ `type` accepts only `one_time` in this version.
16
+ - `scheduledCharges.list({ status?, customerId?, type?, dueFrom?, dueTo?, search?, ... })`
17
+ — `GET /api/scheduled-charges`. `status` accepts a single value or
18
+ an array; arrays are sent as repeated query params.
19
+ - `scheduledCharges.get(id)` — `GET /api/scheduled-charges/{id}`.
20
+ Returns a bundle: `{ charge, events, transactions }`.
21
+ - `scheduledCharges.postpone(id, { newDueDate, reason? })` — allowed
22
+ from `scheduled` / `due_today` / `overdue` / `paused`. Clears any
23
+ pending dunning so the new dueDate triggers a fresh reminder.
24
+ - `scheduledCharges.pause(id, { reason? })` — allowed from
25
+ `scheduled` / `due_today` / `overdue`.
26
+ - `scheduledCharges.resume(id)` — only valid from `paused`.
27
+ - `scheduledCharges.markPaid(id, { paymentDate, externalReference? })`
28
+ — record an off-Garu payment (transfer, cash). Allowed from
29
+ `due_today` / `overdue`.
30
+ - `customers.list({ status: 'overdue' })` — new filter that returns
31
+ customers with at least one overdue scheduled charge.
32
+ - Types exported from the package root: `CreateScheduledChargeParams`,
33
+ `ListScheduledChargesParams`, `MarkPaidScheduledChargeParams`,
34
+ `PauseScheduledChargeParams`, `PostponeScheduledChargeParams`,
35
+ `ScheduledChargeActor`, `ScheduledChargeDetail`,
36
+ `ScheduledChargeEvent`, `ScheduledChargeEventType`,
37
+ `ScheduledChargeLinkedTransaction`, `ScheduledChargeList`,
38
+ `ScheduledChargeRecord`, `ScheduledChargeStatus`,
39
+ `ScheduledChargeType`, `ScheduledPaymentMethod`.
40
+
6
41
  ## [0.3.0] — 2026-04-28
7
42
 
8
43
  ### Added
package/dist/index.cjs CHANGED
@@ -367,6 +367,7 @@ var Customers = class {
367
367
  if (params.page !== void 0) query.page = String(params.page);
368
368
  if (params.limit !== void 0) query.limit = String(params.limit);
369
369
  if (params.search) query.search = params.search;
370
+ if (params.status) query.status = params.status;
370
371
  const qs = new URLSearchParams(query).toString();
371
372
  const url = `/api/customers${qs ? `?${qs}` : ""}`;
372
373
  return this.http.call(
@@ -503,6 +504,156 @@ var Products = class {
503
504
  );
504
505
  }
505
506
  };
507
+
508
+ // src/resources/scheduled-charges.ts
509
+ var ScheduledCharges = class {
510
+ constructor(http) {
511
+ this.http = http;
512
+ }
513
+ http;
514
+ /**
515
+ * Create a new scheduled charge. Auto-attaches `X-Idempotency-Key`
516
+ * (UUIDv4 if you don't pass `idempotencyKey`) so retries on transient
517
+ * network failures don't silently double-create.
518
+ *
519
+ * @example
520
+ * const charge = await garu.scheduledCharges.create({
521
+ * customerId: 42,
522
+ * amount: 297.50,
523
+ * type: 'one_time',
524
+ * dueDate: '2026-06-15',
525
+ * methods: ['pix', 'boleto'],
526
+ * description: 'Mensalidade Junho'
527
+ * });
528
+ */
529
+ async create(params) {
530
+ const idempotencyKey = params.idempotencyKey ?? generateIdempotencyKey();
531
+ const { idempotencyKey: _omit, ...body } = params;
532
+ return this.http.call(
533
+ (signal) => this.http.client.POST("/api/scheduled-charges", {
534
+ body,
535
+ headers: { "X-Idempotency-Key": idempotencyKey },
536
+ signal
537
+ }).then((r) => r)
538
+ );
539
+ }
540
+ /**
541
+ * List scheduled charges for the authenticated seller, with pagination
542
+ * and filters. Repeat the `status` array to filter on multiple values.
543
+ *
544
+ * @example
545
+ * const overdue = await garu.scheduledCharges.list({ status: 'overdue', limit: 50 });
546
+ *
547
+ * @example
548
+ * const upcoming = await garu.scheduledCharges.list({
549
+ * status: ['scheduled', 'due_today'],
550
+ * dueFrom: '2026-06-01',
551
+ * dueTo: '2026-06-30'
552
+ * });
553
+ */
554
+ async list(params = {}) {
555
+ const qs = new URLSearchParams();
556
+ if (params.page !== void 0) qs.set("page", String(params.page));
557
+ if (params.limit !== void 0) qs.set("limit", String(params.limit));
558
+ if (params.customerId !== void 0) qs.set("customerId", String(params.customerId));
559
+ if (params.type) qs.set("type", params.type);
560
+ if (params.dueFrom) qs.set("dueFrom", params.dueFrom);
561
+ if (params.dueTo) qs.set("dueTo", params.dueTo);
562
+ if (params.search) qs.set("search", params.search);
563
+ if (params.status) {
564
+ const statuses = Array.isArray(params.status) ? params.status : [params.status];
565
+ for (const s of statuses) qs.append("status", s);
566
+ }
567
+ const query = qs.toString();
568
+ const url = `/api/scheduled-charges${query ? `?${query}` : ""}`;
569
+ return this.http.call(
570
+ (signal) => this.http.client.GET(url, { signal }).then(
571
+ (r) => r
572
+ )
573
+ );
574
+ }
575
+ /**
576
+ * Fetch a single scheduled charge by ID, bundled with its event timeline
577
+ * and any linked Garu transactions.
578
+ *
579
+ * @example
580
+ * const { charge, events, transactions } = await garu.scheduledCharges.get('sch_abc123');
581
+ * // charge.status, events[].eventType, transactions[].status
582
+ */
583
+ async get(id) {
584
+ return this.http.call(
585
+ (signal) => this.http.client.GET(`/api/scheduled-charges/${id}`, { signal }).then(
586
+ (r) => r
587
+ )
588
+ );
589
+ }
590
+ /**
591
+ * Postpone a scheduled charge to a new due date. Allowed from
592
+ * `scheduled` / `due_today` / `overdue` / `paused`. Clears any pending
593
+ * dunning so the new dueDate triggers a fresh customer reminder.
594
+ *
595
+ * @example
596
+ * await garu.scheduledCharges.postpone('sch_abc123', {
597
+ * newDueDate: '2026-07-01',
598
+ * reason: 'cliente pediu mais prazo'
599
+ * });
600
+ */
601
+ async postpone(id, params) {
602
+ return this.http.call(
603
+ (signal) => this.http.client.POST(`/api/scheduled-charges/${id}/postpone`, {
604
+ body: params,
605
+ signal
606
+ }).then((r) => r)
607
+ );
608
+ }
609
+ /**
610
+ * Pause a scheduled charge. No reminders fire while paused. Resume
611
+ * returns it to `scheduled`. Allowed from
612
+ * `scheduled` / `due_today` / `overdue`.
613
+ *
614
+ * @example
615
+ * await garu.scheduledCharges.pause('sch_abc123', { reason: 'em negociação' });
616
+ */
617
+ async pause(id, params = {}) {
618
+ return this.http.call(
619
+ (signal) => this.http.client.POST(`/api/scheduled-charges/${id}/pause`, {
620
+ body: params,
621
+ signal
622
+ }).then((r) => r)
623
+ );
624
+ }
625
+ /**
626
+ * Resume a paused scheduled charge. Only valid from `paused`.
627
+ *
628
+ * @example
629
+ * await garu.scheduledCharges.resume('sch_abc123');
630
+ */
631
+ async resume(id) {
632
+ return this.http.call(
633
+ (signal) => this.http.client.POST(`/api/scheduled-charges/${id}/resume`, {
634
+ signal
635
+ }).then((r) => r)
636
+ );
637
+ }
638
+ /**
639
+ * Manually mark a scheduled charge as paid, e.g. when the customer paid
640
+ * outside Garu (bank transfer, cash). Allowed from `due_today` / `overdue`.
641
+ *
642
+ * @example
643
+ * await garu.scheduledCharges.markPaid('sch_abc123', {
644
+ * paymentDate: '2026-06-20',
645
+ * externalReference: 'TED 4472881'
646
+ * });
647
+ */
648
+ async markPaid(id, params) {
649
+ return this.http.call(
650
+ (signal) => this.http.client.POST(`/api/scheduled-charges/${id}/mark-paid`, {
651
+ body: params,
652
+ signal
653
+ }).then((r) => r)
654
+ );
655
+ }
656
+ };
506
657
  var webhooks = {
507
658
  verify(params) {
508
659
  const { signature, secret, payload } = params;
@@ -568,6 +719,7 @@ var Garu = class {
568
719
  customers;
569
720
  meta;
570
721
  products;
722
+ scheduledCharges;
571
723
  /**
572
724
  * Webhook helpers. Available both as an instance member and as a static —
573
725
  * `Garu.webhooks.verify(...)` works without constructing a client.
@@ -587,6 +739,7 @@ var Garu = class {
587
739
  this.customers = new Customers(http);
588
740
  this.meta = new Meta(http);
589
741
  this.products = new Products(http);
742
+ this.scheduledCharges = new ScheduledCharges(http);
590
743
  }
591
744
  };
592
745
 
package/dist/index.d.cts CHANGED
@@ -272,6 +272,127 @@ interface ListCustomersParams {
272
272
  page?: number;
273
273
  limit?: number;
274
274
  search?: string;
275
+ /** Filter by aggregated status. `overdue` returns customers with at least one overdue scheduled charge. */
276
+ status?: 'overdue';
277
+ }
278
+ type ScheduledChargeStatus = 'scheduled' | 'due_today' | 'overdue' | 'paid' | 'paused' | 'canceled' | 'trial' | 'pending_tokenization' | 'recurrence_canceled';
279
+ type ScheduledChargeType = 'one_time' | 'recurring';
280
+ type ScheduledPaymentMethod = 'pix' | 'boleto';
281
+ type ScheduledChargeEventType = 'created' | 'postponed' | 'paused' | 'resumed' | 'recurrence_canceled' | 'manually_marked_paid' | 'paid' | 'overdue_reminder_sent' | 'd_day_reminder_sent';
282
+ type ScheduledChargeActor = {
283
+ type: 'user';
284
+ id: number;
285
+ } | {
286
+ type: 'api_key';
287
+ id: number;
288
+ } | {
289
+ type: 'system';
290
+ };
291
+ interface ScheduledChargeRecord {
292
+ id: string;
293
+ sellerId: number;
294
+ customerId: number;
295
+ productId: number | null;
296
+ /** Decimal BRL (e.g. `297.50`), never centavos. */
297
+ amount: number;
298
+ description: string | null;
299
+ type: ScheduledChargeType;
300
+ /** YYYY-MM-DD in São Paulo time. */
301
+ dueDate: string;
302
+ methods: ScheduledPaymentMethod[];
303
+ status: ScheduledChargeStatus;
304
+ externalReference: string | null;
305
+ metadata: Record<string, unknown> | null;
306
+ createdAt: string;
307
+ updatedAt: string;
308
+ /** Eager-loaded customer (id/name/email/document only). */
309
+ customer?: {
310
+ id: number;
311
+ name: string;
312
+ email: string;
313
+ document: string;
314
+ } | null;
315
+ /** Eager-loaded product (id/uuid/name only). */
316
+ product?: {
317
+ id: number;
318
+ uuid: string;
319
+ name: string;
320
+ } | null;
321
+ [key: string]: unknown;
322
+ }
323
+ interface ScheduledChargeEvent {
324
+ id: number;
325
+ scheduledChargeId: string;
326
+ eventType: ScheduledChargeEventType;
327
+ actor: ScheduledChargeActor;
328
+ payload: Record<string, unknown> | null;
329
+ createdAt: string;
330
+ }
331
+ interface ScheduledChargeLinkedTransaction {
332
+ id: number;
333
+ /** Centavos (BRL × 100), matching `garu.charges.*` value semantics. */
334
+ value: number;
335
+ paymentMethod: string;
336
+ status: string;
337
+ date: string;
338
+ refundedAt: string | null;
339
+ [key: string]: unknown;
340
+ }
341
+ interface ScheduledChargeDetail {
342
+ charge: ScheduledChargeRecord;
343
+ events: ScheduledChargeEvent[];
344
+ transactions: ScheduledChargeLinkedTransaction[];
345
+ }
346
+ type ScheduledChargeList = PaginatedList<ScheduledChargeRecord>;
347
+ interface CreateScheduledChargeParams {
348
+ customerId: number;
349
+ productId?: number;
350
+ /** Decimal BRL (e.g. `297.50`). */
351
+ amount: number;
352
+ description?: string;
353
+ /**
354
+ * Schedule type. Only `one_time` is accepted by the current API; the
355
+ * literal narrows to that until recurring schedules ship.
356
+ */
357
+ type: 'one_time';
358
+ /** YYYY-MM-DD in São Paulo time. Must be today or future. */
359
+ dueDate: string;
360
+ /** PIX and Boleto are supported now; card requires tokenization (future). */
361
+ methods: ScheduledPaymentMethod[];
362
+ externalReference?: string;
363
+ metadata?: Record<string, unknown>;
364
+ /**
365
+ * Optional idempotency key for safe retries. The SDK auto-generates a
366
+ * UUIDv4 when omitted and forwards it as `X-Idempotency-Key`.
367
+ */
368
+ idempotencyKey?: string;
369
+ }
370
+ interface ListScheduledChargesParams {
371
+ page?: number;
372
+ limit?: number;
373
+ customerId?: number;
374
+ status?: ScheduledChargeStatus | ScheduledChargeStatus[];
375
+ type?: ScheduledChargeType;
376
+ /** YYYY-MM-DD lower bound for `dueDate`. */
377
+ dueFrom?: string;
378
+ /** YYYY-MM-DD upper bound for `dueDate`. */
379
+ dueTo?: string;
380
+ /** Free-text match against customer name / email / document. */
381
+ search?: string;
382
+ }
383
+ interface PostponeScheduledChargeParams {
384
+ /** YYYY-MM-DD in São Paulo time. Must be today or future. */
385
+ newDueDate: string;
386
+ reason?: string;
387
+ }
388
+ interface PauseScheduledChargeParams {
389
+ reason?: string;
390
+ }
391
+ interface MarkPaidScheduledChargeParams {
392
+ /** YYYY-MM-DD in São Paulo time. Must be today or past. */
393
+ paymentDate: string;
394
+ /** Bank reference, internal ID, or any stable string for reconciliation. */
395
+ externalReference?: string;
275
396
  }
276
397
  interface Product {
277
398
  id: number;
@@ -526,6 +647,102 @@ declare class Products {
526
647
  get(uuid: string): Promise<Product>;
527
648
  }
528
649
 
650
+ /**
651
+ * Scheduled charges — bill a customer on a future date.
652
+ *
653
+ * The seller registers a customer (see `garu.customers.create`), then
654
+ * schedules one or more charges (PIX or Boleto). Garu drives the rest:
655
+ * pre-charge customer email on the due date, dunning to the seller team
656
+ * after the due date, and a state machine for postpone/pause/resume/
657
+ * mark-paid actions.
658
+ *
659
+ * Recurring schedules are reserved for a future API version; the current
660
+ * `type` field accepts only `one_time`.
661
+ */
662
+ declare class ScheduledCharges {
663
+ private readonly http;
664
+ constructor(http: HttpClient);
665
+ /**
666
+ * Create a new scheduled charge. Auto-attaches `X-Idempotency-Key`
667
+ * (UUIDv4 if you don't pass `idempotencyKey`) so retries on transient
668
+ * network failures don't silently double-create.
669
+ *
670
+ * @example
671
+ * const charge = await garu.scheduledCharges.create({
672
+ * customerId: 42,
673
+ * amount: 297.50,
674
+ * type: 'one_time',
675
+ * dueDate: '2026-06-15',
676
+ * methods: ['pix', 'boleto'],
677
+ * description: 'Mensalidade Junho'
678
+ * });
679
+ */
680
+ create(params: CreateScheduledChargeParams): Promise<ScheduledChargeRecord>;
681
+ /**
682
+ * List scheduled charges for the authenticated seller, with pagination
683
+ * and filters. Repeat the `status` array to filter on multiple values.
684
+ *
685
+ * @example
686
+ * const overdue = await garu.scheduledCharges.list({ status: 'overdue', limit: 50 });
687
+ *
688
+ * @example
689
+ * const upcoming = await garu.scheduledCharges.list({
690
+ * status: ['scheduled', 'due_today'],
691
+ * dueFrom: '2026-06-01',
692
+ * dueTo: '2026-06-30'
693
+ * });
694
+ */
695
+ list(params?: ListScheduledChargesParams): Promise<ScheduledChargeList>;
696
+ /**
697
+ * Fetch a single scheduled charge by ID, bundled with its event timeline
698
+ * and any linked Garu transactions.
699
+ *
700
+ * @example
701
+ * const { charge, events, transactions } = await garu.scheduledCharges.get('sch_abc123');
702
+ * // charge.status, events[].eventType, transactions[].status
703
+ */
704
+ get(id: string): Promise<ScheduledChargeDetail>;
705
+ /**
706
+ * Postpone a scheduled charge to a new due date. Allowed from
707
+ * `scheduled` / `due_today` / `overdue` / `paused`. Clears any pending
708
+ * dunning so the new dueDate triggers a fresh customer reminder.
709
+ *
710
+ * @example
711
+ * await garu.scheduledCharges.postpone('sch_abc123', {
712
+ * newDueDate: '2026-07-01',
713
+ * reason: 'cliente pediu mais prazo'
714
+ * });
715
+ */
716
+ postpone(id: string, params: PostponeScheduledChargeParams): Promise<ScheduledChargeRecord>;
717
+ /**
718
+ * Pause a scheduled charge. No reminders fire while paused. Resume
719
+ * returns it to `scheduled`. Allowed from
720
+ * `scheduled` / `due_today` / `overdue`.
721
+ *
722
+ * @example
723
+ * await garu.scheduledCharges.pause('sch_abc123', { reason: 'em negociação' });
724
+ */
725
+ pause(id: string, params?: PauseScheduledChargeParams): Promise<ScheduledChargeRecord>;
726
+ /**
727
+ * Resume a paused scheduled charge. Only valid from `paused`.
728
+ *
729
+ * @example
730
+ * await garu.scheduledCharges.resume('sch_abc123');
731
+ */
732
+ resume(id: string): Promise<ScheduledChargeRecord>;
733
+ /**
734
+ * Manually mark a scheduled charge as paid, e.g. when the customer paid
735
+ * outside Garu (bank transfer, cash). Allowed from `due_today` / `overdue`.
736
+ *
737
+ * @example
738
+ * await garu.scheduledCharges.markPaid('sch_abc123', {
739
+ * paymentDate: '2026-06-20',
740
+ * externalReference: 'TED 4472881'
741
+ * });
742
+ */
743
+ markPaid(id: string, params: MarkPaidScheduledChargeParams): Promise<ScheduledChargeRecord>;
744
+ }
745
+
529
746
  interface GaruOptions {
530
747
  /**
531
748
  * Your Garu API key. `sk_live_…` for production, `sk_test_…` for test mode.
@@ -565,6 +782,7 @@ declare class Garu {
565
782
  readonly customers: Customers;
566
783
  readonly meta: Meta;
567
784
  readonly products: Products;
785
+ readonly scheduledCharges: ScheduledCharges;
568
786
  /**
569
787
  * Webhook helpers. Available both as an instance member and as a static —
570
788
  * `Garu.webhooks.verify(...)` works without constructing a client.
@@ -623,4 +841,4 @@ declare class GaruServerError extends GaruAPIError {
623
841
  constructor(message: string, status: number, requestId: string | null, body: unknown);
624
842
  }
625
843
 
626
- export { type CardInfo, type Charge, type ChargeList, type ChargeStatus, type CreateChargeParams, type CreateCustomerParams, type Customer, type CustomerList, type CustomerRecord, Garu, GaruAPIError, GaruAuthenticationError, GaruConnectionError, GaruError, type GaruErrorCode, GaruNotFoundError, type GaruOptions, GaruPermissionError, GaruRateLimitError, GaruServerError, GaruSignatureVerificationError, GaruValidationError, type ListChargesParams, type ListCustomersParams, type ListProductsParams, type MetaFeatures, type MetaResponse, type PaginatedList, type PaymentMethod, type Product, type ProductList, type RefundChargeParams, type UpdateCustomerParams, type VerifiedWebhook, type VerifyWebhookParams, type WirePaymentMethodId, webhooks };
844
+ export { type CardInfo, type Charge, type ChargeList, type ChargeStatus, type CreateChargeParams, type CreateCustomerParams, type CreateScheduledChargeParams, type Customer, type CustomerList, type CustomerRecord, Garu, GaruAPIError, GaruAuthenticationError, GaruConnectionError, GaruError, type GaruErrorCode, GaruNotFoundError, type GaruOptions, GaruPermissionError, GaruRateLimitError, GaruServerError, GaruSignatureVerificationError, GaruValidationError, type ListChargesParams, type ListCustomersParams, type ListProductsParams, type ListScheduledChargesParams, type MarkPaidScheduledChargeParams, type MetaFeatures, type MetaResponse, type PaginatedList, type PauseScheduledChargeParams, type PaymentMethod, type PostponeScheduledChargeParams, type Product, type ProductList, type RefundChargeParams, type ScheduledChargeActor, type ScheduledChargeDetail, type ScheduledChargeEvent, type ScheduledChargeEventType, type ScheduledChargeLinkedTransaction, type ScheduledChargeList, type ScheduledChargeRecord, type ScheduledChargeStatus, type ScheduledChargeType, type ScheduledPaymentMethod, type UpdateCustomerParams, type VerifiedWebhook, type VerifyWebhookParams, type WirePaymentMethodId, webhooks };
package/dist/index.d.ts CHANGED
@@ -272,6 +272,127 @@ interface ListCustomersParams {
272
272
  page?: number;
273
273
  limit?: number;
274
274
  search?: string;
275
+ /** Filter by aggregated status. `overdue` returns customers with at least one overdue scheduled charge. */
276
+ status?: 'overdue';
277
+ }
278
+ type ScheduledChargeStatus = 'scheduled' | 'due_today' | 'overdue' | 'paid' | 'paused' | 'canceled' | 'trial' | 'pending_tokenization' | 'recurrence_canceled';
279
+ type ScheduledChargeType = 'one_time' | 'recurring';
280
+ type ScheduledPaymentMethod = 'pix' | 'boleto';
281
+ type ScheduledChargeEventType = 'created' | 'postponed' | 'paused' | 'resumed' | 'recurrence_canceled' | 'manually_marked_paid' | 'paid' | 'overdue_reminder_sent' | 'd_day_reminder_sent';
282
+ type ScheduledChargeActor = {
283
+ type: 'user';
284
+ id: number;
285
+ } | {
286
+ type: 'api_key';
287
+ id: number;
288
+ } | {
289
+ type: 'system';
290
+ };
291
+ interface ScheduledChargeRecord {
292
+ id: string;
293
+ sellerId: number;
294
+ customerId: number;
295
+ productId: number | null;
296
+ /** Decimal BRL (e.g. `297.50`), never centavos. */
297
+ amount: number;
298
+ description: string | null;
299
+ type: ScheduledChargeType;
300
+ /** YYYY-MM-DD in São Paulo time. */
301
+ dueDate: string;
302
+ methods: ScheduledPaymentMethod[];
303
+ status: ScheduledChargeStatus;
304
+ externalReference: string | null;
305
+ metadata: Record<string, unknown> | null;
306
+ createdAt: string;
307
+ updatedAt: string;
308
+ /** Eager-loaded customer (id/name/email/document only). */
309
+ customer?: {
310
+ id: number;
311
+ name: string;
312
+ email: string;
313
+ document: string;
314
+ } | null;
315
+ /** Eager-loaded product (id/uuid/name only). */
316
+ product?: {
317
+ id: number;
318
+ uuid: string;
319
+ name: string;
320
+ } | null;
321
+ [key: string]: unknown;
322
+ }
323
+ interface ScheduledChargeEvent {
324
+ id: number;
325
+ scheduledChargeId: string;
326
+ eventType: ScheduledChargeEventType;
327
+ actor: ScheduledChargeActor;
328
+ payload: Record<string, unknown> | null;
329
+ createdAt: string;
330
+ }
331
+ interface ScheduledChargeLinkedTransaction {
332
+ id: number;
333
+ /** Centavos (BRL × 100), matching `garu.charges.*` value semantics. */
334
+ value: number;
335
+ paymentMethod: string;
336
+ status: string;
337
+ date: string;
338
+ refundedAt: string | null;
339
+ [key: string]: unknown;
340
+ }
341
+ interface ScheduledChargeDetail {
342
+ charge: ScheduledChargeRecord;
343
+ events: ScheduledChargeEvent[];
344
+ transactions: ScheduledChargeLinkedTransaction[];
345
+ }
346
+ type ScheduledChargeList = PaginatedList<ScheduledChargeRecord>;
347
+ interface CreateScheduledChargeParams {
348
+ customerId: number;
349
+ productId?: number;
350
+ /** Decimal BRL (e.g. `297.50`). */
351
+ amount: number;
352
+ description?: string;
353
+ /**
354
+ * Schedule type. Only `one_time` is accepted by the current API; the
355
+ * literal narrows to that until recurring schedules ship.
356
+ */
357
+ type: 'one_time';
358
+ /** YYYY-MM-DD in São Paulo time. Must be today or future. */
359
+ dueDate: string;
360
+ /** PIX and Boleto are supported now; card requires tokenization (future). */
361
+ methods: ScheduledPaymentMethod[];
362
+ externalReference?: string;
363
+ metadata?: Record<string, unknown>;
364
+ /**
365
+ * Optional idempotency key for safe retries. The SDK auto-generates a
366
+ * UUIDv4 when omitted and forwards it as `X-Idempotency-Key`.
367
+ */
368
+ idempotencyKey?: string;
369
+ }
370
+ interface ListScheduledChargesParams {
371
+ page?: number;
372
+ limit?: number;
373
+ customerId?: number;
374
+ status?: ScheduledChargeStatus | ScheduledChargeStatus[];
375
+ type?: ScheduledChargeType;
376
+ /** YYYY-MM-DD lower bound for `dueDate`. */
377
+ dueFrom?: string;
378
+ /** YYYY-MM-DD upper bound for `dueDate`. */
379
+ dueTo?: string;
380
+ /** Free-text match against customer name / email / document. */
381
+ search?: string;
382
+ }
383
+ interface PostponeScheduledChargeParams {
384
+ /** YYYY-MM-DD in São Paulo time. Must be today or future. */
385
+ newDueDate: string;
386
+ reason?: string;
387
+ }
388
+ interface PauseScheduledChargeParams {
389
+ reason?: string;
390
+ }
391
+ interface MarkPaidScheduledChargeParams {
392
+ /** YYYY-MM-DD in São Paulo time. Must be today or past. */
393
+ paymentDate: string;
394
+ /** Bank reference, internal ID, or any stable string for reconciliation. */
395
+ externalReference?: string;
275
396
  }
276
397
  interface Product {
277
398
  id: number;
@@ -526,6 +647,102 @@ declare class Products {
526
647
  get(uuid: string): Promise<Product>;
527
648
  }
528
649
 
650
+ /**
651
+ * Scheduled charges — bill a customer on a future date.
652
+ *
653
+ * The seller registers a customer (see `garu.customers.create`), then
654
+ * schedules one or more charges (PIX or Boleto). Garu drives the rest:
655
+ * pre-charge customer email on the due date, dunning to the seller team
656
+ * after the due date, and a state machine for postpone/pause/resume/
657
+ * mark-paid actions.
658
+ *
659
+ * Recurring schedules are reserved for a future API version; the current
660
+ * `type` field accepts only `one_time`.
661
+ */
662
+ declare class ScheduledCharges {
663
+ private readonly http;
664
+ constructor(http: HttpClient);
665
+ /**
666
+ * Create a new scheduled charge. Auto-attaches `X-Idempotency-Key`
667
+ * (UUIDv4 if you don't pass `idempotencyKey`) so retries on transient
668
+ * network failures don't silently double-create.
669
+ *
670
+ * @example
671
+ * const charge = await garu.scheduledCharges.create({
672
+ * customerId: 42,
673
+ * amount: 297.50,
674
+ * type: 'one_time',
675
+ * dueDate: '2026-06-15',
676
+ * methods: ['pix', 'boleto'],
677
+ * description: 'Mensalidade Junho'
678
+ * });
679
+ */
680
+ create(params: CreateScheduledChargeParams): Promise<ScheduledChargeRecord>;
681
+ /**
682
+ * List scheduled charges for the authenticated seller, with pagination
683
+ * and filters. Repeat the `status` array to filter on multiple values.
684
+ *
685
+ * @example
686
+ * const overdue = await garu.scheduledCharges.list({ status: 'overdue', limit: 50 });
687
+ *
688
+ * @example
689
+ * const upcoming = await garu.scheduledCharges.list({
690
+ * status: ['scheduled', 'due_today'],
691
+ * dueFrom: '2026-06-01',
692
+ * dueTo: '2026-06-30'
693
+ * });
694
+ */
695
+ list(params?: ListScheduledChargesParams): Promise<ScheduledChargeList>;
696
+ /**
697
+ * Fetch a single scheduled charge by ID, bundled with its event timeline
698
+ * and any linked Garu transactions.
699
+ *
700
+ * @example
701
+ * const { charge, events, transactions } = await garu.scheduledCharges.get('sch_abc123');
702
+ * // charge.status, events[].eventType, transactions[].status
703
+ */
704
+ get(id: string): Promise<ScheduledChargeDetail>;
705
+ /**
706
+ * Postpone a scheduled charge to a new due date. Allowed from
707
+ * `scheduled` / `due_today` / `overdue` / `paused`. Clears any pending
708
+ * dunning so the new dueDate triggers a fresh customer reminder.
709
+ *
710
+ * @example
711
+ * await garu.scheduledCharges.postpone('sch_abc123', {
712
+ * newDueDate: '2026-07-01',
713
+ * reason: 'cliente pediu mais prazo'
714
+ * });
715
+ */
716
+ postpone(id: string, params: PostponeScheduledChargeParams): Promise<ScheduledChargeRecord>;
717
+ /**
718
+ * Pause a scheduled charge. No reminders fire while paused. Resume
719
+ * returns it to `scheduled`. Allowed from
720
+ * `scheduled` / `due_today` / `overdue`.
721
+ *
722
+ * @example
723
+ * await garu.scheduledCharges.pause('sch_abc123', { reason: 'em negociação' });
724
+ */
725
+ pause(id: string, params?: PauseScheduledChargeParams): Promise<ScheduledChargeRecord>;
726
+ /**
727
+ * Resume a paused scheduled charge. Only valid from `paused`.
728
+ *
729
+ * @example
730
+ * await garu.scheduledCharges.resume('sch_abc123');
731
+ */
732
+ resume(id: string): Promise<ScheduledChargeRecord>;
733
+ /**
734
+ * Manually mark a scheduled charge as paid, e.g. when the customer paid
735
+ * outside Garu (bank transfer, cash). Allowed from `due_today` / `overdue`.
736
+ *
737
+ * @example
738
+ * await garu.scheduledCharges.markPaid('sch_abc123', {
739
+ * paymentDate: '2026-06-20',
740
+ * externalReference: 'TED 4472881'
741
+ * });
742
+ */
743
+ markPaid(id: string, params: MarkPaidScheduledChargeParams): Promise<ScheduledChargeRecord>;
744
+ }
745
+
529
746
  interface GaruOptions {
530
747
  /**
531
748
  * Your Garu API key. `sk_live_…` for production, `sk_test_…` for test mode.
@@ -565,6 +782,7 @@ declare class Garu {
565
782
  readonly customers: Customers;
566
783
  readonly meta: Meta;
567
784
  readonly products: Products;
785
+ readonly scheduledCharges: ScheduledCharges;
568
786
  /**
569
787
  * Webhook helpers. Available both as an instance member and as a static —
570
788
  * `Garu.webhooks.verify(...)` works without constructing a client.
@@ -623,4 +841,4 @@ declare class GaruServerError extends GaruAPIError {
623
841
  constructor(message: string, status: number, requestId: string | null, body: unknown);
624
842
  }
625
843
 
626
- export { type CardInfo, type Charge, type ChargeList, type ChargeStatus, type CreateChargeParams, type CreateCustomerParams, type Customer, type CustomerList, type CustomerRecord, Garu, GaruAPIError, GaruAuthenticationError, GaruConnectionError, GaruError, type GaruErrorCode, GaruNotFoundError, type GaruOptions, GaruPermissionError, GaruRateLimitError, GaruServerError, GaruSignatureVerificationError, GaruValidationError, type ListChargesParams, type ListCustomersParams, type ListProductsParams, type MetaFeatures, type MetaResponse, type PaginatedList, type PaymentMethod, type Product, type ProductList, type RefundChargeParams, type UpdateCustomerParams, type VerifiedWebhook, type VerifyWebhookParams, type WirePaymentMethodId, webhooks };
844
+ export { type CardInfo, type Charge, type ChargeList, type ChargeStatus, type CreateChargeParams, type CreateCustomerParams, type CreateScheduledChargeParams, type Customer, type CustomerList, type CustomerRecord, Garu, GaruAPIError, GaruAuthenticationError, GaruConnectionError, GaruError, type GaruErrorCode, GaruNotFoundError, type GaruOptions, GaruPermissionError, GaruRateLimitError, GaruServerError, GaruSignatureVerificationError, GaruValidationError, type ListChargesParams, type ListCustomersParams, type ListProductsParams, type ListScheduledChargesParams, type MarkPaidScheduledChargeParams, type MetaFeatures, type MetaResponse, type PaginatedList, type PauseScheduledChargeParams, type PaymentMethod, type PostponeScheduledChargeParams, type Product, type ProductList, type RefundChargeParams, type ScheduledChargeActor, type ScheduledChargeDetail, type ScheduledChargeEvent, type ScheduledChargeEventType, type ScheduledChargeLinkedTransaction, type ScheduledChargeList, type ScheduledChargeRecord, type ScheduledChargeStatus, type ScheduledChargeType, type ScheduledPaymentMethod, type UpdateCustomerParams, type VerifiedWebhook, type VerifyWebhookParams, type WirePaymentMethodId, webhooks };
package/dist/index.js CHANGED
@@ -361,6 +361,7 @@ var Customers = class {
361
361
  if (params.page !== void 0) query.page = String(params.page);
362
362
  if (params.limit !== void 0) query.limit = String(params.limit);
363
363
  if (params.search) query.search = params.search;
364
+ if (params.status) query.status = params.status;
364
365
  const qs = new URLSearchParams(query).toString();
365
366
  const url = `/api/customers${qs ? `?${qs}` : ""}`;
366
367
  return this.http.call(
@@ -497,6 +498,156 @@ var Products = class {
497
498
  );
498
499
  }
499
500
  };
501
+
502
+ // src/resources/scheduled-charges.ts
503
+ var ScheduledCharges = class {
504
+ constructor(http) {
505
+ this.http = http;
506
+ }
507
+ http;
508
+ /**
509
+ * Create a new scheduled charge. Auto-attaches `X-Idempotency-Key`
510
+ * (UUIDv4 if you don't pass `idempotencyKey`) so retries on transient
511
+ * network failures don't silently double-create.
512
+ *
513
+ * @example
514
+ * const charge = await garu.scheduledCharges.create({
515
+ * customerId: 42,
516
+ * amount: 297.50,
517
+ * type: 'one_time',
518
+ * dueDate: '2026-06-15',
519
+ * methods: ['pix', 'boleto'],
520
+ * description: 'Mensalidade Junho'
521
+ * });
522
+ */
523
+ async create(params) {
524
+ const idempotencyKey = params.idempotencyKey ?? generateIdempotencyKey();
525
+ const { idempotencyKey: _omit, ...body } = params;
526
+ return this.http.call(
527
+ (signal) => this.http.client.POST("/api/scheduled-charges", {
528
+ body,
529
+ headers: { "X-Idempotency-Key": idempotencyKey },
530
+ signal
531
+ }).then((r) => r)
532
+ );
533
+ }
534
+ /**
535
+ * List scheduled charges for the authenticated seller, with pagination
536
+ * and filters. Repeat the `status` array to filter on multiple values.
537
+ *
538
+ * @example
539
+ * const overdue = await garu.scheduledCharges.list({ status: 'overdue', limit: 50 });
540
+ *
541
+ * @example
542
+ * const upcoming = await garu.scheduledCharges.list({
543
+ * status: ['scheduled', 'due_today'],
544
+ * dueFrom: '2026-06-01',
545
+ * dueTo: '2026-06-30'
546
+ * });
547
+ */
548
+ async list(params = {}) {
549
+ const qs = new URLSearchParams();
550
+ if (params.page !== void 0) qs.set("page", String(params.page));
551
+ if (params.limit !== void 0) qs.set("limit", String(params.limit));
552
+ if (params.customerId !== void 0) qs.set("customerId", String(params.customerId));
553
+ if (params.type) qs.set("type", params.type);
554
+ if (params.dueFrom) qs.set("dueFrom", params.dueFrom);
555
+ if (params.dueTo) qs.set("dueTo", params.dueTo);
556
+ if (params.search) qs.set("search", params.search);
557
+ if (params.status) {
558
+ const statuses = Array.isArray(params.status) ? params.status : [params.status];
559
+ for (const s of statuses) qs.append("status", s);
560
+ }
561
+ const query = qs.toString();
562
+ const url = `/api/scheduled-charges${query ? `?${query}` : ""}`;
563
+ return this.http.call(
564
+ (signal) => this.http.client.GET(url, { signal }).then(
565
+ (r) => r
566
+ )
567
+ );
568
+ }
569
+ /**
570
+ * Fetch a single scheduled charge by ID, bundled with its event timeline
571
+ * and any linked Garu transactions.
572
+ *
573
+ * @example
574
+ * const { charge, events, transactions } = await garu.scheduledCharges.get('sch_abc123');
575
+ * // charge.status, events[].eventType, transactions[].status
576
+ */
577
+ async get(id) {
578
+ return this.http.call(
579
+ (signal) => this.http.client.GET(`/api/scheduled-charges/${id}`, { signal }).then(
580
+ (r) => r
581
+ )
582
+ );
583
+ }
584
+ /**
585
+ * Postpone a scheduled charge to a new due date. Allowed from
586
+ * `scheduled` / `due_today` / `overdue` / `paused`. Clears any pending
587
+ * dunning so the new dueDate triggers a fresh customer reminder.
588
+ *
589
+ * @example
590
+ * await garu.scheduledCharges.postpone('sch_abc123', {
591
+ * newDueDate: '2026-07-01',
592
+ * reason: 'cliente pediu mais prazo'
593
+ * });
594
+ */
595
+ async postpone(id, params) {
596
+ return this.http.call(
597
+ (signal) => this.http.client.POST(`/api/scheduled-charges/${id}/postpone`, {
598
+ body: params,
599
+ signal
600
+ }).then((r) => r)
601
+ );
602
+ }
603
+ /**
604
+ * Pause a scheduled charge. No reminders fire while paused. Resume
605
+ * returns it to `scheduled`. Allowed from
606
+ * `scheduled` / `due_today` / `overdue`.
607
+ *
608
+ * @example
609
+ * await garu.scheduledCharges.pause('sch_abc123', { reason: 'em negociação' });
610
+ */
611
+ async pause(id, params = {}) {
612
+ return this.http.call(
613
+ (signal) => this.http.client.POST(`/api/scheduled-charges/${id}/pause`, {
614
+ body: params,
615
+ signal
616
+ }).then((r) => r)
617
+ );
618
+ }
619
+ /**
620
+ * Resume a paused scheduled charge. Only valid from `paused`.
621
+ *
622
+ * @example
623
+ * await garu.scheduledCharges.resume('sch_abc123');
624
+ */
625
+ async resume(id) {
626
+ return this.http.call(
627
+ (signal) => this.http.client.POST(`/api/scheduled-charges/${id}/resume`, {
628
+ signal
629
+ }).then((r) => r)
630
+ );
631
+ }
632
+ /**
633
+ * Manually mark a scheduled charge as paid, e.g. when the customer paid
634
+ * outside Garu (bank transfer, cash). Allowed from `due_today` / `overdue`.
635
+ *
636
+ * @example
637
+ * await garu.scheduledCharges.markPaid('sch_abc123', {
638
+ * paymentDate: '2026-06-20',
639
+ * externalReference: 'TED 4472881'
640
+ * });
641
+ */
642
+ async markPaid(id, params) {
643
+ return this.http.call(
644
+ (signal) => this.http.client.POST(`/api/scheduled-charges/${id}/mark-paid`, {
645
+ body: params,
646
+ signal
647
+ }).then((r) => r)
648
+ );
649
+ }
650
+ };
500
651
  var webhooks = {
501
652
  verify(params) {
502
653
  const { signature, secret, payload } = params;
@@ -562,6 +713,7 @@ var Garu = class {
562
713
  customers;
563
714
  meta;
564
715
  products;
716
+ scheduledCharges;
565
717
  /**
566
718
  * Webhook helpers. Available both as an instance member and as a static —
567
719
  * `Garu.webhooks.verify(...)` works without constructing a client.
@@ -581,6 +733,7 @@ var Garu = class {
581
733
  this.customers = new Customers(http);
582
734
  this.meta = new Meta(http);
583
735
  this.products = new Products(http);
736
+ this.scheduledCharges = new ScheduledCharges(http);
584
737
  }
585
738
  };
586
739
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@garuhq/node",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Official Node.js / TypeScript SDK for the Garu payment gateway.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://garu.com.br",