@clocknext/sdk 0.17.0 → 0.19.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/README.md +77 -2
- package/dist/index.cjs +96 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +195 -21
- package/dist/index.d.ts +195 -21
- package/dist/index.js +96 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/client.ts +4 -0
- package/src/index.ts +9 -1
- package/src/resources/customers.ts +54 -0
- package/src/resources/signals.ts +3 -1
- package/src/resources/taxes.ts +59 -0
- package/src/types.ts +156 -21
package/package.json
CHANGED
package/src/client.ts
CHANGED
|
@@ -12,6 +12,7 @@ import { Portal } from "./resources/portal.js";
|
|
|
12
12
|
import { Purchases } from "./resources/purchases.js";
|
|
13
13
|
import { Signals } from "./resources/signals.js";
|
|
14
14
|
import { Units } from "./resources/units.js";
|
|
15
|
+
import { Taxes } from "./resources/taxes.js";
|
|
15
16
|
import type { ClockNextConfig, ResolvedConfig } from "./types.js";
|
|
16
17
|
|
|
17
18
|
/**
|
|
@@ -46,6 +47,8 @@ export class ClockNext {
|
|
|
46
47
|
readonly units: Units;
|
|
47
48
|
/** Composites: list, get, create, update, archive, unarchive (no delete). */
|
|
48
49
|
readonly composites: Composites;
|
|
50
|
+
/** Tax rates by country: list, get, create, update (archive in the dashboard). */
|
|
51
|
+
readonly taxes: Taxes;
|
|
49
52
|
/** Subscribe customers to plans (purchases). */
|
|
50
53
|
readonly purchases: Purchases;
|
|
51
54
|
/** Read invoices and mint hosted pay links. */
|
|
@@ -76,6 +79,7 @@ export class ClockNext {
|
|
|
76
79
|
this.outcomes = new Outcomes(transport);
|
|
77
80
|
this.units = new Units(transport);
|
|
78
81
|
this.composites = new Composites(transport);
|
|
82
|
+
this.taxes = new Taxes(transport);
|
|
79
83
|
this.purchases = new Purchases(transport);
|
|
80
84
|
this.invoices = new Invoices(transport);
|
|
81
85
|
this.payments = new Payments(transport);
|
package/src/index.ts
CHANGED
|
@@ -56,7 +56,6 @@ export type {
|
|
|
56
56
|
CompositeCompletionInput,
|
|
57
57
|
CompositeCompletionResult,
|
|
58
58
|
SerializedUnitUsage,
|
|
59
|
-
UsageLogPeriod,
|
|
60
59
|
UsageLogListParams,
|
|
61
60
|
UsageLogAppliedRule,
|
|
62
61
|
UsageLogOutcomeAttribution,
|
|
@@ -69,6 +68,10 @@ export type {
|
|
|
69
68
|
CreateCustomerInput,
|
|
70
69
|
CustomerList,
|
|
71
70
|
CustomerBalances,
|
|
71
|
+
WalletLedgerPage,
|
|
72
|
+
WalletLedgerParams,
|
|
73
|
+
WalletTransaction,
|
|
74
|
+
WalletTransactionSource,
|
|
72
75
|
CreditBalance,
|
|
73
76
|
OutcomeBalance,
|
|
74
77
|
UnitBalance,
|
|
@@ -114,6 +117,11 @@ export type {
|
|
|
114
117
|
Unit,
|
|
115
118
|
CreateUnitInput,
|
|
116
119
|
UpdateUnitInput,
|
|
120
|
+
// taxes
|
|
121
|
+
TaxBehavior,
|
|
122
|
+
Tax,
|
|
123
|
+
CreateTaxInput,
|
|
124
|
+
UpdateTaxInput,
|
|
117
125
|
CompositeItem,
|
|
118
126
|
Composite,
|
|
119
127
|
CreateCompositeInput,
|
|
@@ -23,6 +23,9 @@ import type {
|
|
|
23
23
|
UnitBalance,
|
|
24
24
|
UpdateMemberInput,
|
|
25
25
|
WalletAdjustInput,
|
|
26
|
+
WalletLedgerPage,
|
|
27
|
+
WalletLedgerParams,
|
|
28
|
+
WalletTransaction,
|
|
26
29
|
} from "../types.js";
|
|
27
30
|
|
|
28
31
|
/**
|
|
@@ -147,6 +150,57 @@ export class Customers {
|
|
|
147
150
|
});
|
|
148
151
|
}
|
|
149
152
|
|
|
153
|
+
/**
|
|
154
|
+
* One page of the customer's wallet ledger — every movement of wallet
|
|
155
|
+
* money, newest first — plus both wallet balances. Cursor-paginated: pass
|
|
156
|
+
* back `nextCursor` as `cursor`. `GET /api/v1/customers/:id/wallet`.
|
|
157
|
+
*/
|
|
158
|
+
wallet(id: string, params: WalletLedgerParams = {}): Promise<WalletLedgerPage> {
|
|
159
|
+
return this.walletPage(`/api/v1/customers/${encodeURIComponent(id)}/wallet`, params);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/** {@link wallet}, addressing the customer by its `externalId`.
|
|
163
|
+
* `GET /api/v1/customers/ext/:externalId/wallet`. */
|
|
164
|
+
walletByExternalId(
|
|
165
|
+
externalId: string,
|
|
166
|
+
params: WalletLedgerParams = {},
|
|
167
|
+
): Promise<WalletLedgerPage> {
|
|
168
|
+
return this.walletPage(
|
|
169
|
+
`/api/v1/customers/ext/${encodeURIComponent(externalId)}/wallet`,
|
|
170
|
+
params,
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Async iterator over the customer's WHOLE wallet ledger, newest first,
|
|
176
|
+
* following the cursor. `params.cursor` is ignored.
|
|
177
|
+
* `for await (const t of cnk.customers.iterateWallet(id)) { … }`
|
|
178
|
+
*/
|
|
179
|
+
async *iterateWallet(
|
|
180
|
+
id: string,
|
|
181
|
+
params: Omit<WalletLedgerParams, "cursor"> = {},
|
|
182
|
+
): AsyncGenerator<WalletTransaction> {
|
|
183
|
+
let cursor: string | undefined;
|
|
184
|
+
do {
|
|
185
|
+
const page = await this.wallet(id, { ...params, cursor });
|
|
186
|
+
for (const t of page.transactions) yield t;
|
|
187
|
+
cursor = page.nextCursor ?? undefined;
|
|
188
|
+
} while (cursor);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
private walletPage(path: string, params: WalletLedgerParams): Promise<WalletLedgerPage> {
|
|
192
|
+
return this.transport.request<WalletLedgerPage>({
|
|
193
|
+
method: "GET",
|
|
194
|
+
path,
|
|
195
|
+
query: {
|
|
196
|
+
limit: params.limit,
|
|
197
|
+
cursor: params.cursor,
|
|
198
|
+
from: params.from,
|
|
199
|
+
to: params.to,
|
|
200
|
+
},
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
150
204
|
/** {@link balances}, addressing the customer by its `externalId`.
|
|
151
205
|
* `GET /api/v1/customers/ext/:externalId/balances`. */
|
|
152
206
|
balancesByExternalId(externalId: string): Promise<CustomerBalances> {
|
package/src/resources/signals.ts
CHANGED
|
@@ -286,6 +286,7 @@ export class Signals {
|
|
|
286
286
|
...customerRefToWire(input),
|
|
287
287
|
runId: input.runId,
|
|
288
288
|
...(input.member ? { member: input.member } : {}),
|
|
289
|
+
...(input.custom ? { custom: input.custom } : {}),
|
|
289
290
|
idempotencyKey,
|
|
290
291
|
},
|
|
291
292
|
retry: true,
|
|
@@ -328,6 +329,7 @@ export class Signals {
|
|
|
328
329
|
...(input.composite
|
|
329
330
|
? { composite: { [input.composite.ref]: input.composite.value } }
|
|
330
331
|
: {}),
|
|
332
|
+
...(input.custom ? { custom: input.custom } : {}),
|
|
331
333
|
// Assigned HERE, before the send, so the SAME key rides every
|
|
332
334
|
// transport-level retry below. Without it a single 500 followed by a
|
|
333
335
|
// success is TWO un-keyed reports, and the server dedups on the key —
|
|
@@ -391,6 +393,7 @@ export class Signals {
|
|
|
391
393
|
body: {
|
|
392
394
|
...customerRefToWire(input),
|
|
393
395
|
composite: { [input.composite.ref]: input.composite.value },
|
|
396
|
+
...(input.custom ? { custom: input.custom } : {}),
|
|
394
397
|
// Auto-assigned like the others. A retry here could not double-BILL
|
|
395
398
|
// even without it — closing a closed occurrence is a server-side
|
|
396
399
|
// no-op — but that safety comes from occurrence-level dedup, not from
|
|
@@ -436,7 +439,6 @@ export class Signals {
|
|
|
436
439
|
customerId: params.customerId,
|
|
437
440
|
limit: params.limit,
|
|
438
441
|
cursor: params.cursor,
|
|
439
|
-
period: params.period,
|
|
440
442
|
from: params.from,
|
|
441
443
|
to: params.to,
|
|
442
444
|
},
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { activeQuery, filterByActive } from "../filters.js";
|
|
2
|
+
import type { Transport } from "../http.js";
|
|
3
|
+
import type { CreateTaxInput, Tax, UpdateTaxInput } from "../types.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The `taxes` resource — the tax rates charged to customers by billing
|
|
7
|
+
* country (the same rates as Settings → Taxes). `/api/v1/taxes`.
|
|
8
|
+
*
|
|
9
|
+
* Every active tax for a customer's country is applied to their invoices and
|
|
10
|
+
* portal purchases automatically. There is no `delete()`, `archive()` or
|
|
11
|
+
* `unarchive()` — archiving and restoring a tax is done in the dashboard.
|
|
12
|
+
*/
|
|
13
|
+
export class Taxes {
|
|
14
|
+
constructor(private readonly transport: Transport) {}
|
|
15
|
+
|
|
16
|
+
/** List them, oldest first. `{ active: true }` returns only active ones,
|
|
17
|
+
* `{ active: false }` only archived ones; omit it for both. */
|
|
18
|
+
async list(params: { active?: boolean } = {}): Promise<Tax[]> {
|
|
19
|
+
const res = await this.transport.request<{ taxes: Tax[] }>({
|
|
20
|
+
method: "GET",
|
|
21
|
+
path: "/api/v1/taxes",
|
|
22
|
+
query: { active: activeQuery(params.active) },
|
|
23
|
+
});
|
|
24
|
+
return filterByActive(res.taxes, params.active);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** One tax. */
|
|
28
|
+
async get(id: string): Promise<Tax> {
|
|
29
|
+
const res = await this.transport.request<{ tax: Tax }>({
|
|
30
|
+
method: "GET",
|
|
31
|
+
path: `/api/v1/taxes/${encodeURIComponent(id)}`,
|
|
32
|
+
});
|
|
33
|
+
return res.tax;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Create one. It starts active. Two active taxes can't share a name
|
|
37
|
+
* (ignoring case) in the same country — that's a `ConflictError`. Not
|
|
38
|
+
* retried on failure — a retry could create a second row. */
|
|
39
|
+
async create(input: CreateTaxInput): Promise<Tax> {
|
|
40
|
+
const res = await this.transport.request<{ created: true; tax: Tax }>({
|
|
41
|
+
method: "POST",
|
|
42
|
+
path: "/api/v1/taxes",
|
|
43
|
+
body: input,
|
|
44
|
+
});
|
|
45
|
+
return res.tax;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** PARTIAL update: only the fields you send change. Archived taxes can be
|
|
49
|
+
* edited and stay archived. Only invoices issued afterwards use the new
|
|
50
|
+
* values. */
|
|
51
|
+
async update(id: string, input: UpdateTaxInput): Promise<Tax> {
|
|
52
|
+
const res = await this.transport.request<{ updated: true; tax: Tax }>({
|
|
53
|
+
method: "PATCH",
|
|
54
|
+
path: `/api/v1/taxes/${encodeURIComponent(id)}`,
|
|
55
|
+
body: input,
|
|
56
|
+
});
|
|
57
|
+
return res.tax;
|
|
58
|
+
}
|
|
59
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -189,6 +189,8 @@ export type OutcomeCompletionInput = CustomerRef & {
|
|
|
189
189
|
runId: string;
|
|
190
190
|
/** Optional member (email) this completion is attributed to. */
|
|
191
191
|
member?: string;
|
|
192
|
+
/** Free-form metadata, stored as-is with this completion. Never priced. */
|
|
193
|
+
custom?: Record<string, unknown>;
|
|
192
194
|
/** Idempotency key, auto-generated if omitted. Sending this completion twice
|
|
193
195
|
* for the same run is already a safe no-op server-side, so this only
|
|
194
196
|
* collapses a retry into one attempt rather than protecting against a
|
|
@@ -383,9 +385,6 @@ export interface TrackResult {
|
|
|
383
385
|
// Usage log (mirrors GET /api/v1/signal/usage-log)
|
|
384
386
|
// ---------------------------------------------------------------------------
|
|
385
387
|
|
|
386
|
-
/** A preset time window, or `"custom"` for an explicit `from`/`to` range. */
|
|
387
|
-
export type UsageLogPeriod = "all" | "today" | "7d" | "30d" | "90d" | "custom";
|
|
388
|
-
|
|
389
388
|
export interface UsageLogListParams {
|
|
390
389
|
customerId: string;
|
|
391
390
|
/** Default 50, max 200. */
|
|
@@ -393,11 +392,11 @@ export interface UsageLogListParams {
|
|
|
393
392
|
/** Pass back a previous page's `nextCursor` to fetch the next page. Omit for
|
|
394
393
|
* the first page. */
|
|
395
394
|
cursor?: string;
|
|
396
|
-
/**
|
|
397
|
-
|
|
398
|
-
/** `YYYY-MM-DD`, only used when `period` is `"custom"`. */
|
|
395
|
+
/** First day to include, `YYYY-MM-DD` (UTC). The whole day is included.
|
|
396
|
+
* Keep sending the same value while paging with `cursor`. */
|
|
399
397
|
from?: string;
|
|
400
|
-
/** `YYYY-MM-DD
|
|
398
|
+
/** Last day to include, `YYYY-MM-DD` (UTC). The whole day is included.
|
|
399
|
+
* Must not be before `from`. */
|
|
401
400
|
to?: string;
|
|
402
401
|
}
|
|
403
402
|
|
|
@@ -426,13 +425,15 @@ export interface UsageLogOutcomeAttribution {
|
|
|
426
425
|
* One row of a customer's usage history, merged from every meter kind
|
|
427
426
|
* (`UsageLog`, `UnitUsageLog`, completed composite occurrences) into one
|
|
428
427
|
* feed and sorted by time — the same rows the customer portal's own "Usage
|
|
429
|
-
* logs" table shows. `
|
|
430
|
-
*
|
|
428
|
+
* logs" table shows. `credit`, `outcome`, `unit` and `composite` are each
|
|
429
|
+
* `null` unless `type` matches that group.
|
|
431
430
|
*/
|
|
432
431
|
export interface UsageLogEntry {
|
|
433
432
|
id: string;
|
|
434
433
|
createdAt: string;
|
|
435
|
-
|
|
434
|
+
/** Which meter this row is. `"outcome"` is one step of a run;
|
|
435
|
+
* `"outcome_completion"` is the finished run itself (one per run). */
|
|
436
|
+
type: "credit" | "outcome" | "outcome_completion" | "unit" | "wallet" | "composite";
|
|
436
437
|
status: SignalStatus;
|
|
437
438
|
typeName: string | null;
|
|
438
439
|
member: string | null;
|
|
@@ -447,16 +448,33 @@ export interface UsageLogEntry {
|
|
|
447
448
|
};
|
|
448
449
|
/** Formatted USD strings (e.g. `"$0.0064"`). */
|
|
449
450
|
cost: { providedCost: string; customerCost: string };
|
|
450
|
-
/** Populated only when `
|
|
451
|
+
/** Populated only when `type === "credit"`. `amount` is a formatted credit
|
|
451
452
|
* value, honouring the org's credit-decimals display setting. */
|
|
452
453
|
credit: { amount: string; appliedRules: UsageLogAppliedRule[] } | null;
|
|
453
|
-
/** Populated only when `
|
|
454
|
+
/** Populated only when `type === "outcome"`. */
|
|
454
455
|
outcome: UsageLogOutcomeAttribution | null;
|
|
455
|
-
/** Populated only when `
|
|
456
|
+
/** Populated only when `type === "unit"`. `quantity` is formatted. */
|
|
456
457
|
unit: { quantity: string } | null;
|
|
457
|
-
/** Populated only when `
|
|
458
|
+
/** Populated only when `type === "composite"`. `amount` is a formatted USD
|
|
458
459
|
* price — the composite's flat price, read live, not stored per row. */
|
|
459
460
|
composite: { amount: string } | null;
|
|
461
|
+
/** Populated only when `type === "outcome_completion"`. `amount` is the
|
|
462
|
+
* price frozen when the run completed (your plan price, else the catalogue
|
|
463
|
+
* price). */
|
|
464
|
+
outcomeCompletion: {
|
|
465
|
+
runId: string | null;
|
|
466
|
+
amount: string;
|
|
467
|
+
runSignals: number;
|
|
468
|
+
} | null;
|
|
469
|
+
/** The composite that covers this row's billing, by name — the row's price
|
|
470
|
+
* is then included in that composite's own charge, not billed on top. Set
|
|
471
|
+
* on credit / outcome / unit / outcome_completion rows tagged into a
|
|
472
|
+
* composite on the customer's plan; `null` otherwise. */
|
|
473
|
+
coveredByComposite: string | null;
|
|
474
|
+
/** The `custom` object sent, as sent — on the signal itself, or on the
|
|
475
|
+
* `completeComposite()` / `completeOutcome()` call that closed a composite /
|
|
476
|
+
* outcome_completion row. `null` when none was sent. */
|
|
477
|
+
custom: Record<string, unknown> | null;
|
|
460
478
|
}
|
|
461
479
|
|
|
462
480
|
export interface UsageLogPage {
|
|
@@ -490,8 +508,6 @@ export interface ApiCustomer {
|
|
|
490
508
|
taxId: string | null;
|
|
491
509
|
currencyCode: string;
|
|
492
510
|
creditAllowance: number;
|
|
493
|
-
recurringTransactionEmail: boolean;
|
|
494
|
-
autoRecurring: boolean;
|
|
495
511
|
createdAt: string;
|
|
496
512
|
updatedAt: string;
|
|
497
513
|
}
|
|
@@ -522,10 +538,6 @@ export interface CustomerProfileInput {
|
|
|
522
538
|
taxId?: string | null;
|
|
523
539
|
/** ISO 4217 (3 letters); must be enabled for the org. */
|
|
524
540
|
currencyCode?: string;
|
|
525
|
-
/** Send the invoice, payment receipt and card-payment-failed emails for recurring invoices. Defaults to `true` on create. */
|
|
526
|
-
recurringTransactionEmail?: boolean;
|
|
527
|
-
/** Issue every recurring invoice as `AUTO_CLOSED` (applied as if paid, never payable). Defaults to `false` on create. */
|
|
528
|
-
autoRecurring?: boolean;
|
|
529
541
|
}
|
|
530
542
|
|
|
531
543
|
/** `name` and `email` are required on create; every other field is optional. */
|
|
@@ -618,6 +630,83 @@ export interface CustomerBalances {
|
|
|
618
630
|
composites: CompositeBalance[];
|
|
619
631
|
}
|
|
620
632
|
|
|
633
|
+
/** What caused a wallet ledger row (`WalletTransaction.source`). */
|
|
634
|
+
export type WalletTransactionSource =
|
|
635
|
+
/** Wallet money from a new plan purchase. */
|
|
636
|
+
| "SUBSCRIPTION"
|
|
637
|
+
/** Wallet money from a plan renewal, or unused money removed at renewal. */
|
|
638
|
+
| "RENEWAL"
|
|
639
|
+
/** Changed in the ClockNext dashboard. */
|
|
640
|
+
| "MANUAL"
|
|
641
|
+
/** Changed with `customers.adjustWallet()`. */
|
|
642
|
+
| "API"
|
|
643
|
+
/** Top-up paid by the customer in the customer portal. */
|
|
644
|
+
| "CUSTOMER_PORTAL"
|
|
645
|
+
/** Charged by a signal; `usageLogId` links the signal. */
|
|
646
|
+
| "USAGE_LOG"
|
|
647
|
+
/** Usage cleared by a paid pay-as-you-go invoice. */
|
|
648
|
+
| "INVOICE_SETTLEMENT"
|
|
649
|
+
/** Settlement undone by a voided invoice. */
|
|
650
|
+
| "INVOICE_VOID";
|
|
651
|
+
|
|
652
|
+
/** One row of a customer's wallet ledger (`customers.wallet()`). */
|
|
653
|
+
export interface WalletTransaction {
|
|
654
|
+
id: string;
|
|
655
|
+
/** ISO 8601. */
|
|
656
|
+
createdAt: string;
|
|
657
|
+
/** `CREDIT` adds money, `DEBIT` takes it out. */
|
|
658
|
+
type: "CREDIT" | "DEBIT";
|
|
659
|
+
/** Which balance moved: the ordinary wallet or the Reserved Wallet. */
|
|
660
|
+
pool: "main" | "reserved";
|
|
661
|
+
source: WalletTransactionSource;
|
|
662
|
+
/** Always positive — `type` gives the direction. In `currencyCode`. */
|
|
663
|
+
amount: number;
|
|
664
|
+
/** The same amount in USD. */
|
|
665
|
+
amountUsd: number;
|
|
666
|
+
currencyCode: string;
|
|
667
|
+
/** 1 USD = this many units of `currencyCode`, at write time. */
|
|
668
|
+
currencyRateUsd: number;
|
|
669
|
+
/** Only text a person wrote: your own note on an `API` row, the admin's
|
|
670
|
+
* note on a `MANUAL` row. `null` on every row the system writes itself —
|
|
671
|
+
* `source` says what those are. */
|
|
672
|
+
notes: string | null;
|
|
673
|
+
/** On a usage charge for an entitlement: which kind. `null` otherwise. */
|
|
674
|
+
entitlementType: "CREDIT" | "OUTCOME" | "UNIT" | "COMPOSITE" | null;
|
|
675
|
+
/** Id of that credit / outcome / unit / composite. */
|
|
676
|
+
entitlementId: string | null;
|
|
677
|
+
/** Its name when the row was written. */
|
|
678
|
+
entitlementName: string | null;
|
|
679
|
+
/** On a `USAGE_LOG` row: the id of the matching row in
|
|
680
|
+
* `signals.usageLog()`. */
|
|
681
|
+
usageLogId: string | null;
|
|
682
|
+
/** On a `SUBSCRIPTION` / `RENEWAL` grant: the purchase it came from. */
|
|
683
|
+
purchaseId: string | null;
|
|
684
|
+
purchaseNumber: string | null;
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
/** One page of a customer's wallet ledger, newest first. */
|
|
688
|
+
export interface WalletLedgerPage {
|
|
689
|
+
/** Ordinary wallet balance, USD. May be negative. */
|
|
690
|
+
balanceUsd: number;
|
|
691
|
+
/** Reserved Wallet balance, USD; `null` when the workspace hasn't enabled
|
|
692
|
+
* it. */
|
|
693
|
+
reservedBalanceUsd: number | null;
|
|
694
|
+
transactions: WalletTransaction[];
|
|
695
|
+
/** Pass back as `cursor` for the next page; `null` on the last page. */
|
|
696
|
+
nextCursor: string | null;
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
export interface WalletLedgerParams {
|
|
700
|
+
/** Default 50, max 200. */
|
|
701
|
+
limit?: number;
|
|
702
|
+
/** A previous page's `nextCursor`. Omit for the first page. */
|
|
703
|
+
cursor?: string;
|
|
704
|
+
/** First day to include, `YYYY-MM-DD` (UTC). The whole day is included. */
|
|
705
|
+
from?: string;
|
|
706
|
+
/** Last day to include, `YYYY-MM-DD` (UTC). The whole day is included. */
|
|
707
|
+
to?: string;
|
|
708
|
+
}
|
|
709
|
+
|
|
621
710
|
/** The customer's active plan (the `plan` field of `customers.plan()`);
|
|
622
711
|
* `null` when the customer is unsubscribed. */
|
|
623
712
|
export interface CustomerPlanDetails {
|
|
@@ -963,6 +1052,46 @@ export interface CreateUnitInput {
|
|
|
963
1052
|
/** `units.update()` body — PARTIAL. `tiers`, when sent, is the complete list. */
|
|
964
1053
|
export type UpdateUnitInput = Partial<CreateUnitInput>;
|
|
965
1054
|
|
|
1055
|
+
/** How a tax applies: `"inclusive"` — already inside the price;
|
|
1056
|
+
* `"exclusive"` — added on top. Lower case only. */
|
|
1057
|
+
export type TaxBehavior = "inclusive" | "exclusive";
|
|
1058
|
+
|
|
1059
|
+
/** A tax rate, charged to customers whose billing country matches. */
|
|
1060
|
+
export interface Tax {
|
|
1061
|
+
id: string;
|
|
1062
|
+
/** Shown on invoices. Unique among active taxes in the same country,
|
|
1063
|
+
* ignoring case. */
|
|
1064
|
+
name: string;
|
|
1065
|
+
/** A note for your team; not shown to customers. */
|
|
1066
|
+
description: string | null;
|
|
1067
|
+
/** 0–100. */
|
|
1068
|
+
percentage: number;
|
|
1069
|
+
/** ISO 3166-1 alpha-2, upper case (e.g. `"IN"`). */
|
|
1070
|
+
countryCode: string;
|
|
1071
|
+
behavior: TaxBehavior;
|
|
1072
|
+
/** `false` once archived in the dashboard (Settings → Taxes): it no longer
|
|
1073
|
+
* applies to new invoices. */
|
|
1074
|
+
isActive: boolean;
|
|
1075
|
+
createdAt: string;
|
|
1076
|
+
updatedAt: string;
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
/** `taxes.create()` body. */
|
|
1080
|
+
export interface CreateTaxInput {
|
|
1081
|
+
/** 1–100 characters. */
|
|
1082
|
+
name: string;
|
|
1083
|
+
/** 0–100. */
|
|
1084
|
+
percentage: number;
|
|
1085
|
+
/** ISO 3166-1 alpha-2 (lower case is accepted). A country name is refused. */
|
|
1086
|
+
countryCode: string;
|
|
1087
|
+
behavior: TaxBehavior;
|
|
1088
|
+
/** Up to 500 characters. */
|
|
1089
|
+
description?: string | null;
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
/** `taxes.update()` body — PARTIAL: only the fields you send change. */
|
|
1093
|
+
export type UpdateTaxInput = Partial<CreateTaxInput>;
|
|
1094
|
+
|
|
966
1095
|
/** A catalogue item a composite wraps. */
|
|
967
1096
|
export interface CompositeItem {
|
|
968
1097
|
id: string;
|
|
@@ -1079,7 +1208,8 @@ export interface PurchaseDetail {
|
|
|
1079
1208
|
// Invoices & Payments
|
|
1080
1209
|
// ---------------------------------------------------------------------------
|
|
1081
1210
|
|
|
1082
|
-
/** `AUTO_CLOSED` — a recurring invoice
|
|
1211
|
+
/** `AUTO_CLOSED` — a recurring invoice of an organisation with "Auto close
|
|
1212
|
+
* invoices on recurring" on (dashboard: Settings → Organisation → Billing):
|
|
1083
1213
|
* applied as if paid, but never payable. */
|
|
1084
1214
|
export type InvoiceStatus = "OPEN" | "PAID" | "VOID" | "AUTO_CLOSED";
|
|
1085
1215
|
|
|
@@ -1488,6 +1618,8 @@ export type UnitInput = CustomerRef & {
|
|
|
1488
1618
|
quantity?: number;
|
|
1489
1619
|
/** Optional composite this unit report belongs to. See {@link CompositeTag}. */
|
|
1490
1620
|
composite?: CompositeTag;
|
|
1621
|
+
/** Free-form metadata, stored as-is with this unit report. Never priced. */
|
|
1622
|
+
custom?: Record<string, unknown>;
|
|
1491
1623
|
/**
|
|
1492
1624
|
* Idempotency key for safe retries — a repeat carrying the same key returns
|
|
1493
1625
|
* the original result instead of drawing the balance down twice.
|
|
@@ -1539,6 +1671,9 @@ export type CompositeCompletionInput = CustomerRef & {
|
|
|
1539
1671
|
/** Which occurrence to close: the composite's `refId` and the correlation
|
|
1540
1672
|
* value the signals were tagged with. */
|
|
1541
1673
|
composite: CompositeTag;
|
|
1674
|
+
/** Free-form metadata, stored as-is on the occurrence this call closes.
|
|
1675
|
+
* Never priced. */
|
|
1676
|
+
custom?: Record<string, unknown>;
|
|
1542
1677
|
/** Idempotency key, auto-generated if omitted. Closing twice is already a
|
|
1543
1678
|
* safe no-op, so this only collapses retries into one recorded attempt
|
|
1544
1679
|
* rather than protecting against a double charge. */
|