@clocknext/sdk 0.18.0 → 0.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +67 -1
- package/dist/index.cjs +66 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +230 -12
- package/dist/index.d.ts +230 -12
- package/dist/index.js +66 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +7 -0
- package/src/resources/customers.ts +54 -0
- package/src/resources/signals.ts +26 -0
- package/src/types.ts +182 -11
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -61,6 +61,9 @@ export type {
|
|
|
61
61
|
UsageLogOutcomeAttribution,
|
|
62
62
|
UsageLogEntry,
|
|
63
63
|
UsageLogPage,
|
|
64
|
+
UsageLogLookupEntitlementType,
|
|
65
|
+
UsageLogLookupEntry,
|
|
66
|
+
UsageLogLookupResult,
|
|
64
67
|
// customers
|
|
65
68
|
CustomerRef,
|
|
66
69
|
ApiCustomer,
|
|
@@ -68,6 +71,10 @@ export type {
|
|
|
68
71
|
CreateCustomerInput,
|
|
69
72
|
CustomerList,
|
|
70
73
|
CustomerBalances,
|
|
74
|
+
WalletLedgerPage,
|
|
75
|
+
WalletLedgerParams,
|
|
76
|
+
WalletTransaction,
|
|
77
|
+
WalletTransactionSource,
|
|
71
78
|
CreditBalance,
|
|
72
79
|
OutcomeBalance,
|
|
73
80
|
UnitBalance,
|
|
@@ -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
|
@@ -18,6 +18,7 @@ import type {
|
|
|
18
18
|
UnitTrackResult,
|
|
19
19
|
UsageLogListParams,
|
|
20
20
|
UsageLogPage,
|
|
21
|
+
UsageLogLookupResult,
|
|
21
22
|
WalletInput,
|
|
22
23
|
} from "../types.js";
|
|
23
24
|
|
|
@@ -46,6 +47,7 @@ const UNIT_PATH = "/api/v1/signal/unit";
|
|
|
46
47
|
const COMPOSITE_COMPLETE_PATH = "/api/v1/signal/composite/complete";
|
|
47
48
|
const OUTCOME_COMPLETE_PATH = "/api/v1/signal/outcome/complete";
|
|
48
49
|
const USAGE_LOG_PATH = "/api/v1/signal/usage-log";
|
|
50
|
+
const USAGE_LOG_LOOKUP_PATH = "/api/v1/signal/usage-log/lookup";
|
|
49
51
|
|
|
50
52
|
/**
|
|
51
53
|
* Builds the request body for a typed Signal.
|
|
@@ -286,6 +288,7 @@ export class Signals {
|
|
|
286
288
|
...customerRefToWire(input),
|
|
287
289
|
runId: input.runId,
|
|
288
290
|
...(input.member ? { member: input.member } : {}),
|
|
291
|
+
...(input.custom ? { custom: input.custom } : {}),
|
|
289
292
|
idempotencyKey,
|
|
290
293
|
},
|
|
291
294
|
retry: true,
|
|
@@ -328,6 +331,7 @@ export class Signals {
|
|
|
328
331
|
...(input.composite
|
|
329
332
|
? { composite: { [input.composite.ref]: input.composite.value } }
|
|
330
333
|
: {}),
|
|
334
|
+
...(input.custom ? { custom: input.custom } : {}),
|
|
331
335
|
// Assigned HERE, before the send, so the SAME key rides every
|
|
332
336
|
// transport-level retry below. Without it a single 500 followed by a
|
|
333
337
|
// success is TWO un-keyed reports, and the server dedups on the key —
|
|
@@ -391,6 +395,7 @@ export class Signals {
|
|
|
391
395
|
body: {
|
|
392
396
|
...customerRefToWire(input),
|
|
393
397
|
composite: { [input.composite.ref]: input.composite.value },
|
|
398
|
+
...(input.custom ? { custom: input.custom } : {}),
|
|
394
399
|
// Auto-assigned like the others. A retry here could not double-BILL
|
|
395
400
|
// even without it — closing a closed occurrence is a server-side
|
|
396
401
|
// no-op — but that safety comes from occurrence-level dedup, not from
|
|
@@ -441,4 +446,25 @@ export class Signals {
|
|
|
441
446
|
},
|
|
442
447
|
});
|
|
443
448
|
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Fetches up to 100 usage-log rows by id, in one call.
|
|
452
|
+
* `GET /api/v1/signal/usage-log/lookup`.
|
|
453
|
+
*
|
|
454
|
+
* Built for linking a wallet debit to its usage: pass the `usageLogId`s
|
|
455
|
+
* from `customers.wallet()` instead of paging through
|
|
456
|
+
* {@link usageLog}. Scoped to your org, not to one customer — every row
|
|
457
|
+
* carries its own `customerId`.
|
|
458
|
+
*
|
|
459
|
+
* Rows come back in the order of `ids`; duplicates are removed. Ids that
|
|
460
|
+
* match nothing in your org are listed in `notFound`. More than 100
|
|
461
|
+
* distinct ids is a 400.
|
|
462
|
+
*/
|
|
463
|
+
lookupUsageLogs(ids: string[]): Promise<UsageLogLookupResult> {
|
|
464
|
+
return this.transport.request<UsageLogLookupResult>({
|
|
465
|
+
method: "GET",
|
|
466
|
+
path: USAGE_LOG_LOOKUP_PATH,
|
|
467
|
+
query: { ids: ids.join(",") },
|
|
468
|
+
});
|
|
469
|
+
}
|
|
444
470
|
}
|
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
|
|
@@ -429,8 +431,9 @@ export interface UsageLogOutcomeAttribution {
|
|
|
429
431
|
export interface UsageLogEntry {
|
|
430
432
|
id: string;
|
|
431
433
|
createdAt: string;
|
|
432
|
-
/** Which meter this row is.
|
|
433
|
-
|
|
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";
|
|
434
437
|
status: SignalStatus;
|
|
435
438
|
typeName: string | null;
|
|
436
439
|
member: string | null;
|
|
@@ -455,8 +458,22 @@ export interface UsageLogEntry {
|
|
|
455
458
|
/** Populated only when `type === "composite"`. `amount` is a formatted USD
|
|
456
459
|
* price — the composite's flat price, read live, not stored per row. */
|
|
457
460
|
composite: { amount: string } | null;
|
|
458
|
-
/**
|
|
459
|
-
*
|
|
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. */
|
|
460
477
|
custom: Record<string, unknown> | null;
|
|
461
478
|
}
|
|
462
479
|
|
|
@@ -467,6 +484,83 @@ export interface UsageLogPage {
|
|
|
467
484
|
nextCursor: string | null;
|
|
468
485
|
}
|
|
469
486
|
|
|
487
|
+
// ---------------------------------------------------------------------------
|
|
488
|
+
// Usage log lookup (mirrors GET /api/v1/signal/usage-log/lookup)
|
|
489
|
+
// ---------------------------------------------------------------------------
|
|
490
|
+
|
|
491
|
+
/** What a {@link UsageLogLookupEntry} row is. `"outcome"` is one step of a
|
|
492
|
+
* run; `"outcome_completion"` and `"composite_completion"` are the finished
|
|
493
|
+
* runs themselves. */
|
|
494
|
+
export type UsageLogLookupEntitlementType =
|
|
495
|
+
| "credit"
|
|
496
|
+
| "outcome"
|
|
497
|
+
| "outcome_completion"
|
|
498
|
+
| "unit"
|
|
499
|
+
| "composite_completion"
|
|
500
|
+
| "wallet";
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* One row of `signals.lookupUsageLogs()`. Only the group that matches
|
|
504
|
+
* `entitlement.type` holds data; the others are `null`.
|
|
505
|
+
*/
|
|
506
|
+
export interface UsageLogLookupEntry {
|
|
507
|
+
id: string;
|
|
508
|
+
/** The customer this row belongs to — a lookup can span customers. */
|
|
509
|
+
customerId: string;
|
|
510
|
+
/** For a finished run (`outcome_completion`, `composite_completion`), when
|
|
511
|
+
* it completed. */
|
|
512
|
+
createdAt: string;
|
|
513
|
+
status: SignalStatus;
|
|
514
|
+
/** The credit / outcome / unit / composite this row is for. A wallet row has
|
|
515
|
+
* `id: null` and `name: "Wallet"`. */
|
|
516
|
+
entitlement: { type: UsageLogLookupEntitlementType; id: string | null; name: string | null };
|
|
517
|
+
member: string | null;
|
|
518
|
+
model: { name: string | null; provider: string | null } | null;
|
|
519
|
+
usage: {
|
|
520
|
+
inputTokens: number;
|
|
521
|
+
outputTokens: number;
|
|
522
|
+
/** Cache-read tokens. */
|
|
523
|
+
cacheTokens: number;
|
|
524
|
+
/** Cache-write tokens, priced separately from cache reads. */
|
|
525
|
+
cacheWriteTokens: number;
|
|
526
|
+
};
|
|
527
|
+
/** Formatted USD strings. `customerCost` is what this row charged:
|
|
528
|
+
* `"$0.00"` on an outcome step (the run is billed at completion) and on any
|
|
529
|
+
* row a composite pays for. On a unit row it is what the wallet paid for
|
|
530
|
+
* that report (debits minus refunds), `"$0.00"` when the wallet paid
|
|
531
|
+
* nothing. */
|
|
532
|
+
cost: { providedCost: string; customerCost: string };
|
|
533
|
+
/** `entitlement.type === "credit"`. */
|
|
534
|
+
credit: { amount: string; appliedRules: UsageLogAppliedRule[] } | null;
|
|
535
|
+
/** `entitlement.type === "outcome"`. `runCompleted` is true once the run is
|
|
536
|
+
* finished — on every step row of that run. */
|
|
537
|
+
outcome: { step: string | null; stepName: string | null; runId: string | null; runCompleted: boolean } | null;
|
|
538
|
+
/** `entitlement.type === "outcome_completion"`. `amount` is the price frozen
|
|
539
|
+
* when the run completed. */
|
|
540
|
+
outcomeCompletion: { runId: string | null; amount: string } | null;
|
|
541
|
+
/** `entitlement.type === "unit"`. `quantity` is formatted. */
|
|
542
|
+
unit: { quantity: string } | null;
|
|
543
|
+
/** `entitlement.type === "composite_completion"`. `refId` is the
|
|
544
|
+
* composite's tag key, `runId` the tag value you sent. */
|
|
545
|
+
compositeCompletion: { refId: string | null; runId: string | null; amount: string; startedAt: string } | null;
|
|
546
|
+
/** `entitlement.type === "wallet"`. What the wallet paid, formatted USD —
|
|
547
|
+
* the same value as `cost.customerCost`. */
|
|
548
|
+
wallet: { amount: string } | null;
|
|
549
|
+
/** The composite that pays for this row — its id, its tag key (`refId`) and
|
|
550
|
+
* the tag value you sent (`runId`). `null` when the row is billed by
|
|
551
|
+
* itself. */
|
|
552
|
+
composite: { id: string | null; refId: string | null; runId: string | null } | null;
|
|
553
|
+
/** The `custom` object sent, as sent. `null` when none was sent. */
|
|
554
|
+
custom: Record<string, unknown> | null;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
export interface UsageLogLookupResult {
|
|
558
|
+
/** The rows found, in the order of the ids you asked for. */
|
|
559
|
+
usageLogs: UsageLogLookupEntry[];
|
|
560
|
+
/** The ids that matched nothing in your org, in the order you asked. */
|
|
561
|
+
notFound: string[];
|
|
562
|
+
}
|
|
563
|
+
|
|
470
564
|
// ---------------------------------------------------------------------------
|
|
471
565
|
// Customers (mirrors src/lib/customers/api.ts)
|
|
472
566
|
// ---------------------------------------------------------------------------
|
|
@@ -491,8 +585,6 @@ export interface ApiCustomer {
|
|
|
491
585
|
taxId: string | null;
|
|
492
586
|
currencyCode: string;
|
|
493
587
|
creditAllowance: number;
|
|
494
|
-
recurringTransactionEmail: boolean;
|
|
495
|
-
autoRecurring: boolean;
|
|
496
588
|
createdAt: string;
|
|
497
589
|
updatedAt: string;
|
|
498
590
|
}
|
|
@@ -523,10 +615,6 @@ export interface CustomerProfileInput {
|
|
|
523
615
|
taxId?: string | null;
|
|
524
616
|
/** ISO 4217 (3 letters); must be enabled for the org. */
|
|
525
617
|
currencyCode?: string;
|
|
526
|
-
/** Send the invoice, payment receipt and card-payment-failed emails for recurring invoices. Defaults to `true` on create. */
|
|
527
|
-
recurringTransactionEmail?: boolean;
|
|
528
|
-
/** Issue every recurring invoice as `AUTO_CLOSED` (applied as if paid, never payable). Defaults to `false` on create. */
|
|
529
|
-
autoRecurring?: boolean;
|
|
530
618
|
}
|
|
531
619
|
|
|
532
620
|
/** `name` and `email` are required on create; every other field is optional. */
|
|
@@ -619,6 +707,83 @@ export interface CustomerBalances {
|
|
|
619
707
|
composites: CompositeBalance[];
|
|
620
708
|
}
|
|
621
709
|
|
|
710
|
+
/** What caused a wallet ledger row (`WalletTransaction.source`). */
|
|
711
|
+
export type WalletTransactionSource =
|
|
712
|
+
/** Wallet money from a new plan purchase. */
|
|
713
|
+
| "SUBSCRIPTION"
|
|
714
|
+
/** Wallet money from a plan renewal, or unused money removed at renewal. */
|
|
715
|
+
| "RENEWAL"
|
|
716
|
+
/** Changed in the ClockNext dashboard. */
|
|
717
|
+
| "MANUAL"
|
|
718
|
+
/** Changed with `customers.adjustWallet()`. */
|
|
719
|
+
| "API"
|
|
720
|
+
/** Top-up paid by the customer in the customer portal. */
|
|
721
|
+
| "CUSTOMER_PORTAL"
|
|
722
|
+
/** Charged by a signal; `usageLogId` links the signal. */
|
|
723
|
+
| "USAGE_LOG"
|
|
724
|
+
/** Usage cleared by a paid pay-as-you-go invoice. */
|
|
725
|
+
| "INVOICE_SETTLEMENT"
|
|
726
|
+
/** Settlement undone by a voided invoice. */
|
|
727
|
+
| "INVOICE_VOID";
|
|
728
|
+
|
|
729
|
+
/** One row of a customer's wallet ledger (`customers.wallet()`). */
|
|
730
|
+
export interface WalletTransaction {
|
|
731
|
+
id: string;
|
|
732
|
+
/** ISO 8601. */
|
|
733
|
+
createdAt: string;
|
|
734
|
+
/** `CREDIT` adds money, `DEBIT` takes it out. */
|
|
735
|
+
type: "CREDIT" | "DEBIT";
|
|
736
|
+
/** Which balance moved: the ordinary wallet or the Reserved Wallet. */
|
|
737
|
+
pool: "main" | "reserved";
|
|
738
|
+
source: WalletTransactionSource;
|
|
739
|
+
/** Always positive — `type` gives the direction. In `currencyCode`. */
|
|
740
|
+
amount: number;
|
|
741
|
+
/** The same amount in USD. */
|
|
742
|
+
amountUsd: number;
|
|
743
|
+
currencyCode: string;
|
|
744
|
+
/** 1 USD = this many units of `currencyCode`, at write time. */
|
|
745
|
+
currencyRateUsd: number;
|
|
746
|
+
/** Only text a person wrote: your own note on an `API` row, the admin's
|
|
747
|
+
* note on a `MANUAL` row. `null` on every row the system writes itself —
|
|
748
|
+
* `source` says what those are. */
|
|
749
|
+
notes: string | null;
|
|
750
|
+
/** On a usage charge for an entitlement: which kind. `null` otherwise. */
|
|
751
|
+
entitlementType: "CREDIT" | "OUTCOME" | "UNIT" | "COMPOSITE" | null;
|
|
752
|
+
/** Id of that credit / outcome / unit / composite. */
|
|
753
|
+
entitlementId: string | null;
|
|
754
|
+
/** Its name when the row was written. */
|
|
755
|
+
entitlementName: string | null;
|
|
756
|
+
/** On a `USAGE_LOG` row: the id of the matching row in
|
|
757
|
+
* `signals.usageLog()`. */
|
|
758
|
+
usageLogId: string | null;
|
|
759
|
+
/** On a `SUBSCRIPTION` / `RENEWAL` grant: the purchase it came from. */
|
|
760
|
+
purchaseId: string | null;
|
|
761
|
+
purchaseNumber: string | null;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
/** One page of a customer's wallet ledger, newest first. */
|
|
765
|
+
export interface WalletLedgerPage {
|
|
766
|
+
/** Ordinary wallet balance, USD. May be negative. */
|
|
767
|
+
balanceUsd: number;
|
|
768
|
+
/** Reserved Wallet balance, USD; `null` when the workspace hasn't enabled
|
|
769
|
+
* it. */
|
|
770
|
+
reservedBalanceUsd: number | null;
|
|
771
|
+
transactions: WalletTransaction[];
|
|
772
|
+
/** Pass back as `cursor` for the next page; `null` on the last page. */
|
|
773
|
+
nextCursor: string | null;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
export interface WalletLedgerParams {
|
|
777
|
+
/** Default 50, max 200. */
|
|
778
|
+
limit?: number;
|
|
779
|
+
/** A previous page's `nextCursor`. Omit for the first page. */
|
|
780
|
+
cursor?: string;
|
|
781
|
+
/** First day to include, `YYYY-MM-DD` (UTC). The whole day is included. */
|
|
782
|
+
from?: string;
|
|
783
|
+
/** Last day to include, `YYYY-MM-DD` (UTC). The whole day is included. */
|
|
784
|
+
to?: string;
|
|
785
|
+
}
|
|
786
|
+
|
|
622
787
|
/** The customer's active plan (the `plan` field of `customers.plan()`);
|
|
623
788
|
* `null` when the customer is unsubscribed. */
|
|
624
789
|
export interface CustomerPlanDetails {
|
|
@@ -1120,7 +1285,8 @@ export interface PurchaseDetail {
|
|
|
1120
1285
|
// Invoices & Payments
|
|
1121
1286
|
// ---------------------------------------------------------------------------
|
|
1122
1287
|
|
|
1123
|
-
/** `AUTO_CLOSED` — a recurring invoice
|
|
1288
|
+
/** `AUTO_CLOSED` — a recurring invoice of an organisation with "Auto close
|
|
1289
|
+
* invoices on recurring" on (dashboard: Settings → Organisation → Billing):
|
|
1124
1290
|
* applied as if paid, but never payable. */
|
|
1125
1291
|
export type InvoiceStatus = "OPEN" | "PAID" | "VOID" | "AUTO_CLOSED";
|
|
1126
1292
|
|
|
@@ -1529,6 +1695,8 @@ export type UnitInput = CustomerRef & {
|
|
|
1529
1695
|
quantity?: number;
|
|
1530
1696
|
/** Optional composite this unit report belongs to. See {@link CompositeTag}. */
|
|
1531
1697
|
composite?: CompositeTag;
|
|
1698
|
+
/** Free-form metadata, stored as-is with this unit report. Never priced. */
|
|
1699
|
+
custom?: Record<string, unknown>;
|
|
1532
1700
|
/**
|
|
1533
1701
|
* Idempotency key for safe retries — a repeat carrying the same key returns
|
|
1534
1702
|
* the original result instead of drawing the balance down twice.
|
|
@@ -1580,6 +1748,9 @@ export type CompositeCompletionInput = CustomerRef & {
|
|
|
1580
1748
|
/** Which occurrence to close: the composite's `refId` and the correlation
|
|
1581
1749
|
* value the signals were tagged with. */
|
|
1582
1750
|
composite: CompositeTag;
|
|
1751
|
+
/** Free-form metadata, stored as-is on the occurrence this call closes.
|
|
1752
|
+
* Never priced. */
|
|
1753
|
+
custom?: Record<string, unknown>;
|
|
1583
1754
|
/** Idempotency key, auto-generated if omitted. Closing twice is already a
|
|
1584
1755
|
* safe no-op, so this only collapses retries into one recorded attempt
|
|
1585
1756
|
* rather than protecting against a double charge. */
|