@billkit-eu/sdk 0.2.1 → 0.4.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 +66 -0
- package/README.md +68 -1
- package/dist/index.cjs +116 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +234 -20
- package/dist/index.d.ts +234 -20
- package/dist/index.js +116 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/client.ts +3 -0
- package/src/index.ts +3 -0
- package/src/resources.ts +302 -20
- package/src/version.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,72 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
8
8
|
Versioning is independent of the Python SDK; the two ship on their own cadence,
|
|
9
9
|
so the numbers will diverge after this first release.
|
|
10
10
|
|
|
11
|
+
## [0.4.0]
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
- **`creditNotes`** — `retrieve`, `list`, `iter` and `retrievePdf`. A credit
|
|
15
|
+
note is the document that reverses an issued invoice; one is created for you
|
|
16
|
+
when a refund settles, so there is no `create` here. `list` takes
|
|
17
|
+
`invoice_id` to answer "was this sale credited, and by how much".
|
|
18
|
+
- **`invoices.void(id)`** — records that an invoice was never owed. It keeps
|
|
19
|
+
its number and stays readable; it just stops being a receivable.
|
|
20
|
+
|
|
21
|
+
A **paid** invoice is refused with a `ConflictError` whose `code` is
|
|
22
|
+
`"invoice_not_voidable"`. Once the money has moved, "never owed" is not
|
|
23
|
+
true — refund the payment instead, and a credit note is issued when the
|
|
24
|
+
refund settles. Voiding twice is a no-op.
|
|
25
|
+
|
|
26
|
+
## [0.3.0]
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
- **Metered pricing below one minor unit.** `prices.create` takes
|
|
30
|
+
`unit_amount_decimal`: a per-unit rate in **minor units** with up to 12
|
|
31
|
+
decimal places, so `"0.02"` (0.02 cents, i.e. EUR 0.0002 per unit) is finally
|
|
32
|
+
expressible. `amount_cents` is an integer and could never say it. Metered
|
|
33
|
+
prices only.
|
|
34
|
+
|
|
35
|
+
It is typed as a `string`, so a `number` is a compile error. A number is also
|
|
36
|
+
refused at runtime with a `TypeError`, for the callers the type system cannot
|
|
37
|
+
reach — plain JavaScript, a value that came through `any`, a parsed JSON body.
|
|
38
|
+
A double cannot hold 0.0002 exactly, so accepting one would work for the rates
|
|
39
|
+
that happen to round-trip and silently mis-price the ones that do not.
|
|
40
|
+
- **Tiered pricing.** `prices.create({ billing_scheme: "tiered", tiers_mode,
|
|
41
|
+
tiers })`, with the new exported `PriceTier` type. `tiers_mode: "graduated"`
|
|
42
|
+
prices the units inside each band; `"volume"` lets the period total pick one
|
|
43
|
+
band which then prices every unit. The same table under the two modes is a
|
|
44
|
+
different bill, so the mode is required rather than defaulted. The last band
|
|
45
|
+
must be `up_to: "inf"`. Each band's `unit_amount_decimal` gets the same
|
|
46
|
+
string-only treatment.
|
|
47
|
+
- **`identifier` on `subscriptions.createUsageRecord`**, for the retry an
|
|
48
|
+
`Idempotency-Key` cannot catch. The key covers a retry of one HTTP request;
|
|
49
|
+
`identifier` covers a retry of *your own* call — a job runner replaying a
|
|
50
|
+
task, a queue delivering twice — which arrives as a genuinely new request with
|
|
51
|
+
a new key. It is unique within the subscription, and a second report of the
|
|
52
|
+
same identifier returns the first record unchanged rather than billing twice.
|
|
53
|
+
If your reporting pipeline is at-least-once, this is the one that matters.
|
|
54
|
+
- **`subscriptions.retrieveUsageSummary(id)`**, the money view of pending usage:
|
|
55
|
+
`pending_quantity`, `net_cents` / `tax_cents` / `gross_cents` computed through
|
|
56
|
+
the same rate or tier table the period close uses, and `will_charge`. Read
|
|
57
|
+
`will_charge` before promising a customer an amount: a period under
|
|
58
|
+
`minimum_charge_cents` (EUR 1.00) is **not** charged, because the provider
|
|
59
|
+
would refuse it, and the usage rolls into the next period instead. Previously
|
|
60
|
+
the only record of that decision was a server log line. `open_invoice_id`
|
|
61
|
+
names an earlier cycle still unsettled.
|
|
62
|
+
- **`refund_on_cancel` on `prices.create`.** Server-side since the `0066`
|
|
63
|
+
migration and unreachable from this SDK until now. `"full"` or `"prorated"`
|
|
64
|
+
issues the refund a cancellation promised without anyone having to remember
|
|
65
|
+
to. Metered prices must leave it at `"none"`.
|
|
66
|
+
|
|
67
|
+
### Changed
|
|
68
|
+
- `CreatePriceParams.amount_cents` is now **optional**, because a price can be
|
|
69
|
+
priced by `unit_amount_decimal` or by `tiers` instead. Exactly one of the
|
|
70
|
+
three is required, and the server refuses a price with none of them. Existing
|
|
71
|
+
calls are unaffected.
|
|
72
|
+
- `prices.create` is now `async`. It was already `Promise`-returning, but the
|
|
73
|
+
new rate guard throws, and a synchronous throw out of a method typed
|
|
74
|
+
`Promise<T>` escapes `.catch()` — so the throw is delivered as a rejection
|
|
75
|
+
instead, and one error path handles both.
|
|
76
|
+
|
|
11
77
|
## [0.2.1]
|
|
12
78
|
|
|
13
79
|
### Changed
|
package/README.md
CHANGED
|
@@ -97,7 +97,7 @@ The client exposes one accessor per resource family. Each mirrors the verbs from
|
|
|
97
97
|
| `client.prices` | `create`, `retrieve`, `update` (archive with `active: false`, restore with `active: true`), `list`, `iter` |
|
|
98
98
|
| `client.checkoutSessions` | `create`, `retrieve` |
|
|
99
99
|
| `client.oneShotPayments` | `create`, `retrieve` |
|
|
100
|
-
| `client.subscriptions` | `retrieve`, `list`, `iter` (filter by `customer_id`, `status`, `renewal_state`), `cancel`, `pause`, `resume`, `previewUpdate`, `update`, `reauthorizePaymentMethod` |
|
|
100
|
+
| `client.subscriptions` | `retrieve`, `list`, `iter` (filter by `customer_id`, `status`, `renewal_state`), `cancel`, `pause`, `resume`, `reactivate`, `previewUpdate`, `update`, `reauthorizePaymentMethod`, `createUsageRecord`, `listUsageRecords`, `iterUsageRecords`, `retrieveUsageSummary` |
|
|
101
101
|
| `client.refunds` | `create`, `retrieve`, `list`, `iter` |
|
|
102
102
|
| `client.webhookEndpoints` | `create`, `retrieve`, `update` (stop delivery with `status: "disabled"`), `delete`, `rotateSecret`, `list`, `iter`, `listDeliveries`, `iterDeliveries`, `getDelivery`, `redeliver` |
|
|
103
103
|
| `client.events` | `retrieve`, `list`, `iter` (filter by `type`) |
|
|
@@ -143,6 +143,73 @@ const paused = await client.subscriptions.list({ renewal_state: "paused" });
|
|
|
143
143
|
|
|
144
144
|
`status: "paused"` is not an accepted value and comes back as `InvalidRequestError`. Both filters take a comma-separated list (`status: "active,past_due"`), and an unrecognised value is rejected rather than silently ignored.
|
|
145
145
|
|
|
146
|
+
### Metered billing
|
|
147
|
+
|
|
148
|
+
A metered price charges for what was consumed. You report usage; at each period close BillKit invoices the period's total and charges the stored mandate.
|
|
149
|
+
|
|
150
|
+
There are three ways to price a unit, and a price uses exactly one of them.
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
// 1. Whole minor units: 5 cents per unit.
|
|
154
|
+
await client.prices.create({
|
|
155
|
+
product_id: product.id, amount_cents: 5,
|
|
156
|
+
currency: "EUR", interval: "month", usage_type: "metered",
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// 2. Finer than a minor unit. "0.02" is 0.02 CENTS, i.e. EUR 0.0002 per unit:
|
|
160
|
+
// the canonical per-API-call price, which no integer can express.
|
|
161
|
+
await client.prices.create({
|
|
162
|
+
product_id: product.id, unit_amount_decimal: "0.02",
|
|
163
|
+
currency: "EUR", interval: "month", usage_type: "metered",
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
// 3. By bands. "graduated" prices the units inside each band; "volume" lets
|
|
167
|
+
// the period total pick one band which then prices every unit. The same
|
|
168
|
+
// table under the two modes is a different bill, so the mode is required.
|
|
169
|
+
await client.prices.create({
|
|
170
|
+
product_id: product.id, currency: "EUR", interval: "month",
|
|
171
|
+
usage_type: "metered", billing_scheme: "tiered", tiers_mode: "graduated",
|
|
172
|
+
tiers: [
|
|
173
|
+
{ up_to: 1000, unit_amount: 1 }, // first 1,000 at EUR 0.01
|
|
174
|
+
{ up_to: "inf", unit_amount_decimal: "0.5" }, // then EUR 0.005
|
|
175
|
+
],
|
|
176
|
+
});
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
`amount_cents` is optional for that reason. Send none of the three and the server refuses the price.
|
|
180
|
+
|
|
181
|
+
**`unit_amount_decimal` is a `string`, and a `number` will not compile.** A JS number is an IEEE-754 double and cannot hold 0.0002 exactly, so accepting one would work for the rates that happen to round-trip and silently mis-price the ones that do not. A number that reaches it anyway (plain JavaScript, a value through `any`, a parsed body) is rejected with a `TypeError` before the request goes out. The same applies to a band's `unit_amount_decimal`.
|
|
182
|
+
|
|
183
|
+
The rate is in **minor units**, so `"0.02"` is two hundredths of a cent, not two cents. The period's whole quantity is multiplied by the rate and rounded once, at the invoice, so a sub-cent rate loses nothing per record.
|
|
184
|
+
|
|
185
|
+
The last band must be `up_to: "inf"`, because a bounded top band cannot price the usage above it. Write a free band as `unit_amount: 0`. Metered prices must use `interval: "month"`, cannot have `trial_days`, and cannot set `refund_on_cancel`.
|
|
186
|
+
|
|
187
|
+
#### Reporting usage exactly once
|
|
188
|
+
|
|
189
|
+
```ts
|
|
190
|
+
await client.subscriptions.createUsageRecord(sub.id, {
|
|
191
|
+
quantity: 1200,
|
|
192
|
+
identifier: "job-2026-09-19T10:00Z", // your id for what you are metering
|
|
193
|
+
});
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Two dedupe mechanisms, and they cover different failures. The `Idempotency-Key` the SDK sends covers a retry of *that HTTP request*, including its own internal retries. `identifier` covers a retry of *your* call — a job runner replaying a task, a queue delivering twice, your code re-invoking after its own timeout — which reaches the API as a genuinely new request with a new key. A second report of the same identifier returns the first record unchanged rather than billing twice. If your reporting pipeline is at-least-once, `identifier` is the one that matters.
|
|
197
|
+
|
|
198
|
+
Records are immutable once written: they are the audit trail behind an invoice line, so there is no update or delete.
|
|
199
|
+
|
|
200
|
+
#### Knowing what the next invoice will be
|
|
201
|
+
|
|
202
|
+
```ts
|
|
203
|
+
const summary = await client.subscriptions.retrieveUsageSummary<{
|
|
204
|
+
pending_quantity: number;
|
|
205
|
+
gross_cents: number;
|
|
206
|
+
will_charge: boolean;
|
|
207
|
+
minimum_charge_cents: number;
|
|
208
|
+
}>(sub.id);
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Check `will_charge` before you promise a customer an amount. A period whose total is under `minimum_charge_cents` (EUR 1.00) is **not** charged, because the payment provider would refuse it. The usage is not lost: it stays pending and rolls into the next period, which is then billed for both. `net_cents` / `tax_cents` / `gross_cents` are computed through the same rate or tier table and the same VAT resolution the close itself uses, so this is a forecast of the real invoice rather than an estimate. `open_invoice_id` names an earlier cycle that is invoiced and still unsettled; while one is open, this period cannot be charged.
|
|
212
|
+
|
|
146
213
|
### Embedded checkout
|
|
147
214
|
|
|
148
215
|
Pass `ui_mode: "embedded"` and the session comes back with a `client_secret` instead of a `url`. Hand that to [`@billkit-eu/js`](https://www.npmjs.com/package/@billkit-eu/js) or [`@billkit-eu/react`](https://www.npmjs.com/package/@billkit-eu/react) and the card fields render on your own page, inside a cross-origin iframe. `cancel_url` is still required.
|
package/dist/index.cjs
CHANGED
|
@@ -37,6 +37,22 @@ function splitIdempotency(params) {
|
|
|
37
37
|
const { idempotencyKey, ...rest } = params;
|
|
38
38
|
return { body: dropUndefined(rest), idempotencyKey };
|
|
39
39
|
}
|
|
40
|
+
function assertDecimalRateIsString(value, field) {
|
|
41
|
+
if (value === void 0 || value === null || typeof value === "string") return;
|
|
42
|
+
throw new TypeError(
|
|
43
|
+
`${field} must be a string, not a ${typeof value}. A JavaScript number cannot hold a rate like 0.0002 exactly, so it would be corrupted before it was ever multiplied by a quantity. Pass it as a string: "${String(value)}".`
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
function assertPriceRatesAreStrings(params) {
|
|
47
|
+
assertDecimalRateIsString(params.unit_amount_decimal, "unit_amount_decimal");
|
|
48
|
+
(params.tiers ?? []).forEach((tier, index) => {
|
|
49
|
+
assertDecimalRateIsString(
|
|
50
|
+
tier?.unit_amount_decimal,
|
|
51
|
+
`tiers[${index}].unit_amount_decimal`
|
|
52
|
+
);
|
|
53
|
+
});
|
|
54
|
+
return params;
|
|
55
|
+
}
|
|
40
56
|
var BaseResource = class {
|
|
41
57
|
constructor(t) {
|
|
42
58
|
this.t = t;
|
|
@@ -100,6 +116,16 @@ var Customers = class extends BaseResource {
|
|
|
100
116
|
delete(id, params = {}) {
|
|
101
117
|
return this.del(`/v1/customers/${id}`, params);
|
|
102
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* List customers, newest first.
|
|
121
|
+
*
|
|
122
|
+
* `provisional` filters on whether the customer ever completed a
|
|
123
|
+
* payment. A checkout that captures an email commits its Customer
|
|
124
|
+
* before the charge, so a checkout nobody finished leaves a row behind:
|
|
125
|
+
* pass `false` for real customers only, `true` for the abandoned ones
|
|
126
|
+
* (the cart-recovery worklist), or omit for both. Abandoned rows are
|
|
127
|
+
* swept after the tenant's retention window.
|
|
128
|
+
*/
|
|
103
129
|
list(params = {}) {
|
|
104
130
|
return this.get("/v1/customers", params);
|
|
105
131
|
}
|
|
@@ -156,9 +182,23 @@ var Products = class extends BaseResource {
|
|
|
156
182
|
}
|
|
157
183
|
};
|
|
158
184
|
var Prices = class extends BaseResource {
|
|
159
|
-
/**
|
|
160
|
-
|
|
161
|
-
|
|
185
|
+
/**
|
|
186
|
+
* Create immutable billing terms for an existing Product.
|
|
187
|
+
*
|
|
188
|
+
* A licensed price sends `amount_cents`. A metered price sends one of
|
|
189
|
+
* `amount_cents`, `unit_amount_decimal` (a rate finer than one minor
|
|
190
|
+
* unit, as a string) or `billing_scheme: "tiered"` with `tiers` and
|
|
191
|
+
* `tiers_mode`. Throws `TypeError` before any HTTP call if a decimal
|
|
192
|
+
* rate arrives as a number — see
|
|
193
|
+
* {@link CreatePriceParams.unit_amount_decimal}.
|
|
194
|
+
*/
|
|
195
|
+
// `async` on purpose. The rate guard throws, and a synchronous throw out
|
|
196
|
+
// of a method typed `Promise<T>` escapes `.catch()` entirely — the caller
|
|
197
|
+
// would have to wrap the call site in try/catch as well, which nobody
|
|
198
|
+
// does for a promise-returning API. Marking it async turns the throw into
|
|
199
|
+
// a rejection, so one error path handles both.
|
|
200
|
+
async create(params) {
|
|
201
|
+
return this.post("/v1/prices", assertPriceRatesAreStrings(params));
|
|
162
202
|
}
|
|
163
203
|
retrieve(id) {
|
|
164
204
|
return this.get(`/v1/prices/${id}`);
|
|
@@ -279,13 +319,16 @@ var Subscriptions = class extends BaseResource {
|
|
|
279
319
|
*
|
|
280
320
|
* Only valid when the subscription's price is `usage_type:
|
|
281
321
|
* "metered"`; a licensed subscription is rejected with `400
|
|
282
|
-
* parameter_invalid`. Records accumulate until the
|
|
283
|
-
* rolls them
|
|
284
|
-
* `
|
|
322
|
+
* parameter_invalid`. Records accumulate until the next period close
|
|
323
|
+
* rolls them into one invoice line; the record's `invoice_id` stays
|
|
324
|
+
* `null` until then. Records are immutable once written — they are the
|
|
325
|
+
* audit trail behind that line — so there is no update or delete.
|
|
285
326
|
*
|
|
286
|
-
*
|
|
287
|
-
*
|
|
288
|
-
*
|
|
327
|
+
* Two dedupe mechanisms, covering different failures. The
|
|
328
|
+
* `Idempotency-Key` the SDK sends covers a retry of this HTTP request,
|
|
329
|
+
* including its own internal retries. `params.identifier` covers a
|
|
330
|
+
* retry of *your* call, which arrives as a new request with a new key.
|
|
331
|
+
* See {@link CreateUsageRecordParams.identifier}.
|
|
289
332
|
*/
|
|
290
333
|
createUsageRecord(id, params) {
|
|
291
334
|
return this.post(`/v1/subscriptions/${id}/usage_records`, params);
|
|
@@ -307,6 +350,27 @@ var Subscriptions = class extends BaseResource {
|
|
|
307
350
|
filters: { invoice_id: options.invoice_id }
|
|
308
351
|
});
|
|
309
352
|
}
|
|
353
|
+
/**
|
|
354
|
+
* Price the pending usage, before the period close bills it.
|
|
355
|
+
*
|
|
356
|
+
* `listUsageRecords({ invoice_id: "pending" })` gives the quantity; this
|
|
357
|
+
* gives the money. `net_cents` / `tax_cents` / `gross_cents` are
|
|
358
|
+
* computed through the same rate or tier table and the same VAT
|
|
359
|
+
* resolution the close itself uses, so it is a forecast of the real
|
|
360
|
+
* invoice rather than an estimate.
|
|
361
|
+
*
|
|
362
|
+
* **Read `will_charge` before promising a customer an amount.** A period
|
|
363
|
+
* whose total is under `minimum_charge_cents` (EUR 1.00) is not charged,
|
|
364
|
+
* because the payment provider would refuse it. The usage is not lost:
|
|
365
|
+
* it stays pending and rolls into the next period, which is then billed
|
|
366
|
+
* for both.
|
|
367
|
+
*
|
|
368
|
+
* `open_invoice_id` names an earlier cycle that is invoiced and still
|
|
369
|
+
* unsettled; while one is open, this period cannot be charged.
|
|
370
|
+
*/
|
|
371
|
+
retrieveUsageSummary(id) {
|
|
372
|
+
return this.get(`/v1/subscriptions/${id}/usage_summary`);
|
|
373
|
+
}
|
|
310
374
|
};
|
|
311
375
|
var Refunds = class extends BaseResource {
|
|
312
376
|
create(params) {
|
|
@@ -556,6 +620,46 @@ var Invoices = class extends BaseResource {
|
|
|
556
620
|
iter(options = {}) {
|
|
557
621
|
return paginate((p) => this.get("/v1/invoices", p), { pageSize: options.pageSize });
|
|
558
622
|
}
|
|
623
|
+
/**
|
|
624
|
+
* Void an invoice: state that the sale was never owed.
|
|
625
|
+
*
|
|
626
|
+
* The invoice keeps its number and stays readable — a gapless series
|
|
627
|
+
* cannot lose a row — and stops being a receivable. Use it for an
|
|
628
|
+
* invoice that should not have been issued.
|
|
629
|
+
*
|
|
630
|
+
* A **paid** invoice is refused with a `ConflictError` whose `code` is
|
|
631
|
+
* `"invoice_not_voidable"`. That is deliberate rather than a
|
|
632
|
+
* limitation: once the money has moved, "never owed" is false, and the
|
|
633
|
+
* document that reverses a real sale is a credit note — refund the
|
|
634
|
+
* payment and one is issued when the refund settles.
|
|
635
|
+
*
|
|
636
|
+
* Idempotent: re-voiding an already-void invoice returns it unchanged.
|
|
637
|
+
*/
|
|
638
|
+
void(id, params = {}) {
|
|
639
|
+
return this.post(`/v1/invoices/${id}/void`, params);
|
|
640
|
+
}
|
|
641
|
+
};
|
|
642
|
+
var CreditNotes = class extends BaseResource {
|
|
643
|
+
retrieve(id) {
|
|
644
|
+
return this.get(`/v1/credit_notes/${id}`);
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Download the rendered credit note PDF as raw bytes. Same storage
|
|
648
|
+
* split as {@link Invoices.retrievePdf}: bytes inline or a followed
|
|
649
|
+
* `302`, and `501 rendering_pending` on a deployment with no renderer.
|
|
650
|
+
*/
|
|
651
|
+
retrievePdf(id) {
|
|
652
|
+
return this.t.requestBinary({ method: "GET", path: `/v1/credit_notes/${id}/pdf` });
|
|
653
|
+
}
|
|
654
|
+
list(params = {}) {
|
|
655
|
+
return this.get("/v1/credit_notes", params);
|
|
656
|
+
}
|
|
657
|
+
iter(options = {}) {
|
|
658
|
+
return paginate((p) => this.get("/v1/credit_notes", p), {
|
|
659
|
+
pageSize: options.pageSize,
|
|
660
|
+
filters: { invoice_id: options.invoice_id, customer_id: options.customer_id }
|
|
661
|
+
});
|
|
662
|
+
}
|
|
559
663
|
};
|
|
560
664
|
var AuditLogs = class extends BaseResource {
|
|
561
665
|
retrieve(id) {
|
|
@@ -733,7 +837,7 @@ function sleep(ms) {
|
|
|
733
837
|
}
|
|
734
838
|
|
|
735
839
|
// src/version.ts
|
|
736
|
-
var VERSION = "0.
|
|
840
|
+
var VERSION = "0.4.0";
|
|
737
841
|
|
|
738
842
|
// src/transport.ts
|
|
739
843
|
var DEFAULT_BASE_URL = "https://api.billkit.eu";
|
|
@@ -967,6 +1071,7 @@ var BillKit = class {
|
|
|
967
1071
|
coupons;
|
|
968
1072
|
taxRates;
|
|
969
1073
|
invoices;
|
|
1074
|
+
creditNotes;
|
|
970
1075
|
auditLogs;
|
|
971
1076
|
payments;
|
|
972
1077
|
billingPortalSessions;
|
|
@@ -989,6 +1094,7 @@ var BillKit = class {
|
|
|
989
1094
|
this.coupons = new Coupons(transport);
|
|
990
1095
|
this.taxRates = new TaxRates(transport);
|
|
991
1096
|
this.invoices = new Invoices(transport);
|
|
1097
|
+
this.creditNotes = new CreditNotes(transport);
|
|
992
1098
|
this.auditLogs = new AuditLogs(transport);
|
|
993
1099
|
this.payments = new Payments(transport);
|
|
994
1100
|
this.billingPortalSessions = new BillingPortalSessions(transport);
|