@clocknext/sdk 0.13.0 → 0.15.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 +200 -140
- package/dist/index.cjs +213 -438
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +394 -812
- package/dist/index.d.ts +394 -812
- package/dist/index.js +213 -438
- package/dist/index.js.map +1 -1
- package/examples/node-basic.ts +24 -32
- package/package.json +1 -1
- package/src/client.ts +3 -27
- package/src/customer-ref.ts +14 -0
- package/src/errors.ts +8 -1
- package/src/filters.ts +1 -1
- package/src/index.ts +13 -59
- package/src/resources/customers.ts +201 -82
- package/src/resources/invoices.ts +1 -1
- package/src/resources/plans.ts +4 -56
- package/src/resources/signals.ts +33 -38
- package/src/types.ts +301 -610
- package/src/resources/composites.ts +0 -47
- package/src/resources/credits.ts +0 -76
- package/src/resources/outcomes.ts +0 -82
- package/src/resources/units.ts +0 -76
- package/src/resources/webhooks.ts +0 -37
- package/src/resources/workspace.ts +0 -33
package/src/types.ts
CHANGED
|
@@ -65,42 +65,40 @@ export interface CompositeTag {
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
// ---------------------------------------------------------------------------
|
|
68
|
-
//
|
|
68
|
+
// Naming a customer
|
|
69
69
|
// ---------------------------------------------------------------------------
|
|
70
70
|
|
|
71
|
-
/**
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
71
|
+
/**
|
|
72
|
+
* How a request names its customer: by OUR id (`customerId`) or by YOUR id for
|
|
73
|
+
* them (`externalId` — the value set on the customer via
|
|
74
|
+
* `customers.create()` / `customers.update()`). At least one is required.
|
|
75
|
+
*
|
|
76
|
+
* When both are sent, `customerId` wins and `externalId` is ignored — the
|
|
77
|
+
* server does not check that they agree. An `externalId` matching no active
|
|
78
|
+
* customer is a `NotFoundError` (or, on an async signal, leaves it Pending
|
|
79
|
+
* with that reason — retry once the customer exists).
|
|
80
|
+
*/
|
|
81
|
+
export type CustomerRef =
|
|
82
|
+
| {
|
|
83
|
+
/** Our customer id. Wins over `externalId` when both are sent. */
|
|
84
|
+
customerId: string;
|
|
85
|
+
externalId?: string;
|
|
86
|
+
}
|
|
87
|
+
| {
|
|
88
|
+
customerId?: undefined;
|
|
89
|
+
/** Your id for the customer: 1–32 letters, numbers or "-", matched
|
|
90
|
+
* exactly (case-sensitive). */
|
|
91
|
+
externalId: string;
|
|
92
|
+
};
|
|
87
93
|
|
|
88
|
-
/**
|
|
89
|
-
*
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
provider: string;
|
|
94
|
-
providerName: string;
|
|
95
|
-
isActive: boolean;
|
|
96
|
-
inputPrice: number;
|
|
97
|
-
outputPrice: number;
|
|
98
|
-
cachePrice: number;
|
|
99
|
-
}
|
|
94
|
+
/** `Omit` that keeps a union a union (plain `Omit` flattens it to the
|
|
95
|
+
* members' shared keys, losing the {@link CustomerRef} either/or). */
|
|
96
|
+
type DistributiveOmit<T, K extends PropertyKey> = T extends unknown
|
|
97
|
+
? Omit<T, K>
|
|
98
|
+
: never;
|
|
100
99
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
customerId: string;
|
|
100
|
+
/** Every signal names its customer — see {@link CustomerRef}. */
|
|
101
|
+
interface SignalFields {
|
|
104
102
|
/**
|
|
105
103
|
* The model's catalog id — must be enabled in your ClockNext org
|
|
106
104
|
* (Settings → Models). Matched case-insensitively against `OrgModel.modelId`.
|
|
@@ -123,19 +121,21 @@ interface SignalBase {
|
|
|
123
121
|
idempotencyKey?: string;
|
|
124
122
|
}
|
|
125
123
|
|
|
124
|
+
type SignalBase = CustomerRef & SignalFields;
|
|
125
|
+
|
|
126
126
|
/** Meters a credit, identified by the credit's stable `agentKey`. */
|
|
127
|
-
export
|
|
127
|
+
export type CreditSignal = SignalBase & {
|
|
128
128
|
type: "credit";
|
|
129
129
|
/** The Credit's stable agent key (assigned when the credit was created). */
|
|
130
130
|
agentKey: string;
|
|
131
131
|
/** Optional composite this signal belongs to. See {@link CompositeTag}. */
|
|
132
132
|
composite?: CompositeTag;
|
|
133
|
-
}
|
|
133
|
+
};
|
|
134
134
|
|
|
135
135
|
/** Debits the customer's wallet in USD at the model's cost. */
|
|
136
|
-
export
|
|
136
|
+
export type WalletSignal = SignalBase & {
|
|
137
137
|
type: "wallet";
|
|
138
|
-
}
|
|
138
|
+
};
|
|
139
139
|
|
|
140
140
|
/**
|
|
141
141
|
* Records one step of a multi-call outcome run. The `agentKey` identifies the
|
|
@@ -149,7 +149,7 @@ export interface WalletSignal extends SignalBase {
|
|
|
149
149
|
* carries `complete` — see {@link OutcomeCompletionInput} /
|
|
150
150
|
* `signals.completeOutcome()`, its own dedicated route.
|
|
151
151
|
*/
|
|
152
|
-
export
|
|
152
|
+
export type OutcomeSignal = SignalBase & {
|
|
153
153
|
type: "outcome";
|
|
154
154
|
/** The OutcomeStep's stable agent key — identifies the outcome AND the step. */
|
|
155
155
|
agentKey: string;
|
|
@@ -161,14 +161,14 @@ export interface OutcomeSignal extends SignalBase {
|
|
|
161
161
|
runId: string;
|
|
162
162
|
/** Optional composite this signal belongs to. See {@link CompositeTag}. */
|
|
163
163
|
composite?: CompositeTag;
|
|
164
|
-
}
|
|
164
|
+
};
|
|
165
165
|
|
|
166
166
|
export type Signal = CreditSignal | WalletSignal | OutcomeSignal;
|
|
167
167
|
|
|
168
168
|
/** Helper input shapes for the per-type convenience methods. */
|
|
169
|
-
export type CreditInput =
|
|
170
|
-
export type WalletInput =
|
|
171
|
-
export type OutcomeInput =
|
|
169
|
+
export type CreditInput = DistributiveOmit<CreditSignal, "type">;
|
|
170
|
+
export type WalletInput = DistributiveOmit<WalletSignal, "type">;
|
|
171
|
+
export type OutcomeInput = DistributiveOmit<OutcomeSignal, "type">;
|
|
172
172
|
|
|
173
173
|
/**
|
|
174
174
|
* Input for `signals.completeOutcome()` — closes ONE outcome run, the outcome
|
|
@@ -181,17 +181,17 @@ export type OutcomeInput = Omit<OutcomeSignal, "type">;
|
|
|
181
181
|
* `signals.completeComposite()` — the two completions are independent, and
|
|
182
182
|
* neither implies the other.
|
|
183
183
|
*/
|
|
184
|
-
export
|
|
185
|
-
customerId: string;
|
|
184
|
+
export type OutcomeCompletionInput = CustomerRef & {
|
|
186
185
|
/** The same `runId` the run's step signals were sent with. */
|
|
187
186
|
runId: string;
|
|
188
187
|
/** Optional member (email) this completion is attributed to. */
|
|
189
188
|
member?: string;
|
|
190
|
-
/** Idempotency key, auto-generated if omitted. Sending
|
|
191
|
-
* the same run is already a safe no-op server-side, so this only
|
|
192
|
-
* a retry into one attempt rather than protecting against a
|
|
189
|
+
/** Idempotency key, auto-generated if omitted. Sending this completion twice
|
|
190
|
+
* for the same run is already a safe no-op server-side, so this only
|
|
191
|
+
* collapses a retry into one attempt rather than protecting against a
|
|
192
|
+
* double bill. */
|
|
193
193
|
idempotencyKey?: string;
|
|
194
|
-
}
|
|
194
|
+
};
|
|
195
195
|
|
|
196
196
|
/**
|
|
197
197
|
* The result of `signals.completeOutcome()`.
|
|
@@ -304,7 +304,7 @@ export interface SerializedUsageLog {
|
|
|
304
304
|
* exhausted allowance is detected by the worker LATER and never surfaces here —
|
|
305
305
|
* the signal is simply dropped. A `202` therefore means "accepted", never
|
|
306
306
|
* "recorded". To confirm a signal actually landed, read it back with
|
|
307
|
-
* `signals.
|
|
307
|
+
* `signals.usageLog({ customerId })`.
|
|
308
308
|
*
|
|
309
309
|
* When the server has no queue configured it prices inline instead and returns
|
|
310
310
|
* `queued: false` with a populated `usageLog`, validating synchronously.
|
|
@@ -327,7 +327,7 @@ export interface TrackResult {
|
|
|
327
327
|
* and will price it shortly. It can no longer be lost, but
|
|
328
328
|
* it is not billed yet and `usageLog` is null. A rejection
|
|
329
329
|
* discovered during pricing will NOT come back to you here,
|
|
330
|
-
* nor on `onError`. `signals.
|
|
330
|
+
* nor on `onError`. `signals.usageLog()` shows what got priced;
|
|
331
331
|
* the dashboard's signal log — owner-only, by design — is
|
|
332
332
|
* where an individual rejection says why.
|
|
333
333
|
* `"recorded"` — the server priced it inline and `usageLog` is populated.
|
|
@@ -373,16 +373,84 @@ export interface TrackResult {
|
|
|
373
373
|
rawId?: string;
|
|
374
374
|
}
|
|
375
375
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
376
|
+
// ---------------------------------------------------------------------------
|
|
377
|
+
// Usage log (mirrors GET /api/v1/signal/usage-log)
|
|
378
|
+
// ---------------------------------------------------------------------------
|
|
379
|
+
|
|
380
|
+
/** A preset time window, or `"custom"` for an explicit `from`/`to` range. */
|
|
381
|
+
export type UsageLogPeriod = "all" | "today" | "7d" | "30d" | "90d" | "custom";
|
|
382
|
+
|
|
383
|
+
export interface UsageLogListParams {
|
|
384
|
+
customerId: string;
|
|
385
|
+
/** Default 50, max 200. */
|
|
386
|
+
limit?: number;
|
|
387
|
+
/** Pass back a previous page's `nextCursor` to fetch the next page. Omit for
|
|
388
|
+
* the first page. */
|
|
389
|
+
cursor?: string;
|
|
390
|
+
/** Default `"all"`. Pair `"custom"` with `from`/`to`. */
|
|
391
|
+
period?: UsageLogPeriod;
|
|
392
|
+
/** `YYYY-MM-DD`, only used when `period` is `"custom"`. */
|
|
393
|
+
from?: string;
|
|
394
|
+
/** `YYYY-MM-DD`, only used when `period` is `"custom"`. */
|
|
395
|
+
to?: string;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
export interface UsageLogAppliedRule {
|
|
399
|
+
ruleId: string | null;
|
|
400
|
+
ruleName: string;
|
|
401
|
+
mode: "MARGIN" | "CREDIT" | null;
|
|
402
|
+
marginPercentApplied: number | null;
|
|
403
|
+
/** Formatted, same as {@link UsageLogEntry.credit}'s `amount`. */
|
|
404
|
+
creditsApplied: string;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
export interface UsageLogOutcomeAttribution {
|
|
408
|
+
/** "2 / 4" — the step this call performed, and the outcome's total step
|
|
409
|
+
* count. Not a progress target: a step may repeat within a run. */
|
|
410
|
+
step: string | null;
|
|
411
|
+
stepName: string | null;
|
|
412
|
+
runId: string | null;
|
|
413
|
+
/** How many signals the run holds. */
|
|
414
|
+
runSignals: number;
|
|
415
|
+
/** True once the run closed (`complete: true` was sent for it). */
|
|
416
|
+
closedRun: boolean;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* One row of a customer's usage history, merged from every meter kind
|
|
421
|
+
* (`UsageLog`, `UnitUsageLog`, completed composite occurrences) into one
|
|
422
|
+
* feed and sorted by time — the same rows the customer portal's own "Usage
|
|
423
|
+
* logs" table shows. `model`, `credit`, `outcome`, `unit` and `composite` are
|
|
424
|
+
* each `null` unless `kind` matches that group.
|
|
425
|
+
*/
|
|
426
|
+
export interface UsageLogEntry {
|
|
427
|
+
id: string;
|
|
428
|
+
createdAt: string;
|
|
429
|
+
kind: "credit" | "outcome" | "unit" | "wallet" | "composite";
|
|
430
|
+
status: SignalStatus;
|
|
431
|
+
typeName: string | null;
|
|
432
|
+
member: string | null;
|
|
433
|
+
model: { name: string | null; provider: string | null } | null;
|
|
434
|
+
usage: { inputTokens: number; outputTokens: number; cacheTokens: number };
|
|
435
|
+
/** Formatted USD strings (e.g. `"$0.0064"`). */
|
|
436
|
+
cost: { providedCost: string; customerCost: string };
|
|
437
|
+
/** Populated only when `kind === "credit"`. `amount` is a formatted credit
|
|
438
|
+
* value, honouring the org's credit-decimals display setting. */
|
|
439
|
+
credit: { amount: string; appliedRules: UsageLogAppliedRule[] } | null;
|
|
440
|
+
/** Populated only when `kind === "outcome"`. */
|
|
441
|
+
outcome: UsageLogOutcomeAttribution | null;
|
|
442
|
+
/** Populated only when `kind === "unit"`. `quantity` is formatted. */
|
|
443
|
+
unit: { quantity: string } | null;
|
|
444
|
+
/** Populated only when `kind === "composite"`. `amount` is a formatted USD
|
|
445
|
+
* price — the composite's flat price, read live, not stored per row. */
|
|
446
|
+
composite: { amount: string } | null;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
export interface UsageLogPage {
|
|
450
|
+
usageLogs: UsageLogEntry[];
|
|
451
|
+
/** Pass this back as `cursor` to fetch the next page; `null` on the last
|
|
452
|
+
* page. */
|
|
453
|
+
nextCursor: string | null;
|
|
386
454
|
}
|
|
387
455
|
|
|
388
456
|
// ---------------------------------------------------------------------------
|
|
@@ -391,6 +459,9 @@ export interface UsageList {
|
|
|
391
459
|
|
|
392
460
|
export interface ApiCustomer {
|
|
393
461
|
id: string;
|
|
462
|
+
/** Your own id for this customer, or `null` when unset. See
|
|
463
|
+
* {@link CustomerProfileInput.externalId}. */
|
|
464
|
+
externalId: string | null;
|
|
394
465
|
slug: string;
|
|
395
466
|
name: string;
|
|
396
467
|
description: string | null;
|
|
@@ -406,12 +477,24 @@ export interface ApiCustomer {
|
|
|
406
477
|
taxId: string | null;
|
|
407
478
|
currencyCode: string;
|
|
408
479
|
creditAllowance: number;
|
|
480
|
+
recurringTransactionEmail: boolean;
|
|
481
|
+
autoRecurring: boolean;
|
|
409
482
|
createdAt: string;
|
|
410
483
|
updatedAt: string;
|
|
411
484
|
}
|
|
412
485
|
|
|
413
486
|
/** Writable customer profile fields. `null` clears a column; omit to leave it. */
|
|
414
487
|
export interface CustomerProfileInput {
|
|
488
|
+
/**
|
|
489
|
+
* The id YOUR product uses for this customer: 1–32 letters, numbers or "-",
|
|
490
|
+
* case-sensitive. Unique among the org's active customers (a clash is a
|
|
491
|
+
* `ConflictError`; an archived customer's id can be reused). Once set,
|
|
492
|
+
* signals and `purchases.create()` can take `externalId` instead of
|
|
493
|
+
* `customerId`, and `customers.getByExternalId()` / `updateByExternalId()` /
|
|
494
|
+
* `updateRecurringGrantByExternalId()` address the customer by it. `null`
|
|
495
|
+
* clears it on update.
|
|
496
|
+
*/
|
|
497
|
+
externalId?: string | null;
|
|
415
498
|
name?: string;
|
|
416
499
|
description?: string | null;
|
|
417
500
|
email?: string | null;
|
|
@@ -426,6 +509,10 @@ export interface CustomerProfileInput {
|
|
|
426
509
|
taxId?: string | null;
|
|
427
510
|
/** ISO 4217 (3 letters); must be enabled for the org. */
|
|
428
511
|
currencyCode?: string;
|
|
512
|
+
/** Send the invoice, payment receipt and card-payment-failed emails for recurring invoices. Defaults to `true` on create. */
|
|
513
|
+
recurringTransactionEmail?: boolean;
|
|
514
|
+
/** Issue every recurring invoice as `AUTO_CLOSED` (applied as if paid, never payable). Defaults to `false` on create. */
|
|
515
|
+
autoRecurring?: boolean;
|
|
429
516
|
}
|
|
430
517
|
|
|
431
518
|
/** `name` and `email` are required on create; every other field is optional. */
|
|
@@ -461,7 +548,7 @@ export interface OutcomeBalance {
|
|
|
461
548
|
remaining: number;
|
|
462
549
|
/** Each step's `agentKey` is what `signals.outcome()` and the outcome adjust
|
|
463
550
|
* API use to address this outcome at runtime. The outcome also has its own
|
|
464
|
-
* separate key (
|
|
551
|
+
* separate key (the outcome's own `agentKey`), but neither of those APIs accepts
|
|
465
552
|
* it — it identifies the outcome in the catalogue, not in a signal. */
|
|
466
553
|
steps: { id: string; name: string; agentKey: string }[];
|
|
467
554
|
}
|
|
@@ -483,7 +570,11 @@ export interface CustomerBalances {
|
|
|
483
570
|
customerId: string;
|
|
484
571
|
currency: { code: string; rateUsd: number };
|
|
485
572
|
hasPlan: boolean;
|
|
573
|
+
/** `null` when the plan has no Wallet component. */
|
|
486
574
|
wallet: { balanceUsd: number } | null;
|
|
575
|
+
/** The Reserved Wallet; `null` when the org hasn't enabled it. Independent
|
|
576
|
+
* of `wallet` — present whether or not the plan has a Wallet. */
|
|
577
|
+
reservedWallet: { balanceUsd: number } | null;
|
|
487
578
|
credits: CreditBalance[];
|
|
488
579
|
outcomes: OutcomeBalance[];
|
|
489
580
|
units: UnitBalance[];
|
|
@@ -545,7 +636,6 @@ export type BillingCycle =
|
|
|
545
636
|
| "FREE";
|
|
546
637
|
export type PlanType = "WALLET" | "BUNDLE";
|
|
547
638
|
export type PlanKind = "FLAT_PRICE" | "PAY_AS_YOU_GO" | "PAY_PER_SEAT";
|
|
548
|
-
/** A plan component's meter type. */
|
|
549
639
|
/**
|
|
550
640
|
* A plan component's kind.
|
|
551
641
|
*
|
|
@@ -564,109 +654,6 @@ export type ComponentType =
|
|
|
564
654
|
/** ADVANCE bills up-front for the cycle; ARREAR bills for what was consumed. */
|
|
565
655
|
export type BillingMode = "ADVANCE" | "ARREAR";
|
|
566
656
|
|
|
567
|
-
/** Prepaid USD wallet. `amount` is the funded balance (required). Max one
|
|
568
|
-
* wallet component per plan. */
|
|
569
|
-
export interface WalletComponentInput {
|
|
570
|
-
type: "WALLET";
|
|
571
|
-
billingMode: BillingMode;
|
|
572
|
-
amount: number;
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
/** A one-off flat fee — `amount` is required. Max one flat component per plan;
|
|
576
|
-
* not allowed on FREE plans. */
|
|
577
|
-
export interface FlatComponentInput {
|
|
578
|
-
type: "FLAT";
|
|
579
|
-
billingMode: BillingMode;
|
|
580
|
-
amount: number;
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
/** A credit entitlement, referenced by `creditId`. Billed ADVANCE it needs a
|
|
584
|
-
* granted `quantity`; billed ARREAR it meters usage with no upfront grant. */
|
|
585
|
-
export type CreditComponentInput =
|
|
586
|
-
| { type: "CREDIT"; billingMode: "ADVANCE"; creditId: string; quantity: number }
|
|
587
|
-
| { type: "CREDIT"; billingMode: "ARREAR"; creditId: string; quantity?: number | null };
|
|
588
|
-
|
|
589
|
-
/** An outcome entitlement, referenced by `outcomeId`. ADVANCE needs a granted
|
|
590
|
-
* `quantity`; ARREAR meters usage. */
|
|
591
|
-
export type OutcomeComponentInput =
|
|
592
|
-
| { type: "OUTCOME"; billingMode: "ADVANCE"; outcomeId: string; quantity: number }
|
|
593
|
-
| { type: "OUTCOME"; billingMode: "ARREAR"; outcomeId: string; quantity?: number | null };
|
|
594
|
-
|
|
595
|
-
/** A unit entitlement, referenced by `unitId`. ADVANCE needs a granted
|
|
596
|
-
* `quantity`; ARREAR meters usage. */
|
|
597
|
-
export type UnitComponentInput =
|
|
598
|
-
| { type: "UNIT"; billingMode: "ADVANCE"; unitId: string; quantity: number }
|
|
599
|
-
| { type: "UNIT"; billingMode: "ARREAR"; unitId: string; quantity?: number | null };
|
|
600
|
-
|
|
601
|
-
/**
|
|
602
|
-
* A COMPOSITE sold on the plan, referenced by `pricingMetricId` (the id from
|
|
603
|
-
* `composites.list()`). This is the line that makes a composite bill: the
|
|
604
|
-
* catalogue entry on its own charges nobody, and this component is what turns
|
|
605
|
-
* it into money — `quantity × the composite's price`, frozen into the purchase
|
|
606
|
-
* snapshot at buy time.
|
|
607
|
-
*
|
|
608
|
-
* The two billing modes differ in what `quantity` means:
|
|
609
|
-
* - **ADVANCE** — a PREPAID POOL of `quantity` flat-rate slots, shared
|
|
610
|
-
* across whichever credits / outcomes / units the composite wraps. Each
|
|
611
|
-
* distinct tag value claims one slot on completion; repeat signals under a
|
|
612
|
-
* value reuse the slot they already claimed, at no extra cost. Once every
|
|
613
|
-
* slot is claimed, further occurrences are refused rather than billed.
|
|
614
|
-
* - **ARREAR** — nothing prepaid; completed occurrences are counted on the
|
|
615
|
-
* cycle-end line.
|
|
616
|
-
*
|
|
617
|
-
* `type` is the wire value `"PRICING_METRIC"`, not `"COMPOSITE"`: the product
|
|
618
|
-
* word changed but the stored enum did not, and the API still speaks the old
|
|
619
|
-
* one. That mismatch is the server's, and it is surfaced rather than hidden so
|
|
620
|
-
* a response and a request read the same.
|
|
621
|
-
*/
|
|
622
|
-
export type CompositeComponentInput =
|
|
623
|
-
| {
|
|
624
|
-
type: "PRICING_METRIC";
|
|
625
|
-
billingMode: "ADVANCE";
|
|
626
|
-
pricingMetricId: string;
|
|
627
|
-
quantity: number;
|
|
628
|
-
}
|
|
629
|
-
| {
|
|
630
|
-
type: "PRICING_METRIC";
|
|
631
|
-
billingMode: "ARREAR";
|
|
632
|
-
pricingMetricId: string;
|
|
633
|
-
quantity?: number | null;
|
|
634
|
-
};
|
|
635
|
-
|
|
636
|
-
/**
|
|
637
|
-
* One entitlement line in a plan — a discriminated union on `type` (and, where
|
|
638
|
-
* it matters, `billingMode`) so the per-type fields the server requires are
|
|
639
|
-
* enforced at compile time instead of surfacing as runtime 422s:
|
|
640
|
-
* - CREDIT / OUTCOME / UNIT require their matching id;
|
|
641
|
-
* - PRICING_METRIC (a composite) requires `pricingMetricId`;
|
|
642
|
-
* - CREDIT / OUTCOME / UNIT / PRICING_METRIC require `quantity` when billed
|
|
643
|
-
* ADVANCE;
|
|
644
|
-
* - WALLET / FLAT require `amount`.
|
|
645
|
-
*/
|
|
646
|
-
export type PlanComponentInput =
|
|
647
|
-
| WalletComponentInput
|
|
648
|
-
| FlatComponentInput
|
|
649
|
-
| CreditComponentInput
|
|
650
|
-
| OutcomeComponentInput
|
|
651
|
-
| UnitComponentInput
|
|
652
|
-
| CompositeComponentInput;
|
|
653
|
-
|
|
654
|
-
export interface CreatePlanInput {
|
|
655
|
-
name: string;
|
|
656
|
-
description?: string | null;
|
|
657
|
-
billingCycle: BillingCycle;
|
|
658
|
-
/** Carry an unused balance into the next cycle. Default true. */
|
|
659
|
-
carryForward?: boolean;
|
|
660
|
-
/** ISO 4217 (3 letters). Default "USD". */
|
|
661
|
-
currencyCode?: string;
|
|
662
|
-
isActive?: boolean;
|
|
663
|
-
/** At least one component. FREE plans must be ADVANCE-only with no FLAT component. */
|
|
664
|
-
components: PlanComponentInput[];
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
/** A full-rewrite update carries the complete plan (same shape as create). */
|
|
668
|
-
export type UpdatePlanInput = CreatePlanInput;
|
|
669
|
-
|
|
670
657
|
export interface PlanComponent {
|
|
671
658
|
id: string;
|
|
672
659
|
type: ComponentType;
|
|
@@ -674,11 +661,9 @@ export interface PlanComponent {
|
|
|
674
661
|
creditId: string | null;
|
|
675
662
|
outcomeId: string | null;
|
|
676
663
|
unitId: string | null;
|
|
677
|
-
/** The composite this component sells, on a `PRICING_METRIC`
|
|
678
|
-
*
|
|
679
|
-
|
|
680
|
-
* silently dropped every composite component. */
|
|
681
|
-
pricingMetricId: string | null;
|
|
664
|
+
/** The id of the composite this component sells, on a `PRICING_METRIC`
|
|
665
|
+
* component. */
|
|
666
|
+
compositeId: string | null;
|
|
682
667
|
targetName: string | null;
|
|
683
668
|
quantity: number | null;
|
|
684
669
|
amount: number | null;
|
|
@@ -702,24 +687,13 @@ export interface Plan {
|
|
|
702
687
|
components: PlanComponent[];
|
|
703
688
|
}
|
|
704
689
|
|
|
705
|
-
/** The richer plan returned by `plans.get()` (adds aggregate stats). */
|
|
706
|
-
export interface PlanDetail extends Plan {
|
|
707
|
-
createdAt: string;
|
|
708
|
-
createdByName: string | null;
|
|
709
|
-
customerCount: number;
|
|
710
|
-
invoiceCount: number;
|
|
711
|
-
openInvoiceCount: number;
|
|
712
|
-
stats: { totalInvoiced: number; totalCollected: number; openBalance: number };
|
|
713
|
-
}
|
|
714
|
-
|
|
715
690
|
// ---------------------------------------------------------------------------
|
|
716
691
|
// Purchases (subscriptions)
|
|
717
692
|
// ---------------------------------------------------------------------------
|
|
718
693
|
|
|
719
694
|
export type PurchaseStatus = "SCHEDULED" | "ACTIVE" | "CANCELLED";
|
|
720
695
|
|
|
721
|
-
export
|
|
722
|
-
customerId: string;
|
|
696
|
+
export type CreatePurchaseInput = CustomerRef & {
|
|
723
697
|
planId: string;
|
|
724
698
|
/** `YYYY-MM-DD`. Defaults to today; must be a valid non-past date. */
|
|
725
699
|
billingDate?: string;
|
|
@@ -727,7 +701,7 @@ export interface CreatePurchaseInput {
|
|
|
727
701
|
autoPayment?: boolean;
|
|
728
702
|
/** Auto-void the purchase if unpaid after N minutes. */
|
|
729
703
|
voidAfterMinutes?: number;
|
|
730
|
-
}
|
|
704
|
+
};
|
|
731
705
|
|
|
732
706
|
export interface Purchase {
|
|
733
707
|
id: string;
|
|
@@ -783,7 +757,9 @@ export interface PurchaseDetail {
|
|
|
783
757
|
// Invoices & Payments
|
|
784
758
|
// ---------------------------------------------------------------------------
|
|
785
759
|
|
|
786
|
-
|
|
760
|
+
/** `AUTO_CLOSED` — a recurring invoice for a customer with `autoRecurring` on:
|
|
761
|
+
* applied as if paid, but never payable. */
|
|
762
|
+
export type InvoiceStatus = "OPEN" | "PAID" | "VOID" | "AUTO_CLOSED";
|
|
787
763
|
|
|
788
764
|
/** Trimmed row from `invoices.list()`. */
|
|
789
765
|
export interface InvoiceListRow {
|
|
@@ -968,78 +944,82 @@ export interface UpdateMemberInput {
|
|
|
968
944
|
}
|
|
969
945
|
|
|
970
946
|
// ---------------------------------------------------------------------------
|
|
971
|
-
//
|
|
947
|
+
// Balance adjustments (customer-scoped)
|
|
972
948
|
// ---------------------------------------------------------------------------
|
|
973
949
|
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
*
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
type: WalletTransactionType;
|
|
990
|
-
/** What produced the entry. Null on rows older than the column. */
|
|
991
|
-
source: WalletTransactionSource | null;
|
|
992
|
-
amount: number;
|
|
993
|
-
amountUsd: number;
|
|
994
|
-
currencyCode: string;
|
|
995
|
-
currencyRateUsd: number;
|
|
996
|
-
notes: string | null;
|
|
997
|
-
batchId: string | null;
|
|
998
|
-
createdAt: string;
|
|
999
|
-
createdByName: string | null;
|
|
1000
|
-
/** Set only on a wallet-funded metering debit: which kind of entitlement was
|
|
1001
|
-
* consumed. Null on top-ups and manual adjustments. */
|
|
1002
|
-
entitlementType: WalletEntitlementKind | null;
|
|
1003
|
-
/** Id of the credit / outcome / unit consumed. Null unless
|
|
1004
|
-
* `entitlementType` is set. */
|
|
1005
|
-
targetId: string | null;
|
|
1006
|
-
/** Its name at the time of the debit. */
|
|
1007
|
-
targetName: string | null;
|
|
1008
|
-
/** The signal this debit paid for (credit / outcome). In wallet-funded mode
|
|
1009
|
-
* no invoice exists, so this is the only trail from a charge to its cause. */
|
|
1010
|
-
usageLogId: string | null;
|
|
1011
|
-
/** The unit event this debit paid for. */
|
|
1012
|
-
unitUsageLogId: string | null;
|
|
1013
|
-
}
|
|
1014
|
-
|
|
1015
|
-
export interface WalletList {
|
|
1016
|
-
balanceUsd: number;
|
|
1017
|
-
transactions: WalletTransaction[];
|
|
1018
|
-
}
|
|
1019
|
-
|
|
1020
|
-
export interface WalletEntryInput {
|
|
1021
|
-
/** DEBIT spends, CREDIT tops up. */
|
|
1022
|
-
type: WalletTransactionType;
|
|
1023
|
-
/** Always positive; the sign comes from `type`. */
|
|
1024
|
-
amount: number;
|
|
950
|
+
/**
|
|
951
|
+
* Which of a customer's two wallet balances an entry moves: `MAIN` (the
|
|
952
|
+
* ordinary wallet) or `RESERVED` (the Reserved Wallet — an org-gated second
|
|
953
|
+
* balance behind it; see {@link WalletAdjustInput.pool}).
|
|
954
|
+
*/
|
|
955
|
+
export type WalletPool = "MAIN" | "RESERVED";
|
|
956
|
+
|
|
957
|
+
/** Top up (positive) or draw down (negative) a customer's wallet. `delta` is
|
|
958
|
+
* a non-zero amount in USD (cents allowed); absolute value ≤ 10,000,000. No
|
|
959
|
+
* `agentKey` — a customer has exactly one wallet. The wallet can always be
|
|
960
|
+
* adjusted, whatever the customer's plan (even with no plan). A draw-down is
|
|
961
|
+
* never rejected or floored for going below 0 — the wallet may read negative. */
|
|
962
|
+
export interface WalletAdjustInput {
|
|
963
|
+
/** Signed change in USD: positive tops up, negative draws down. */
|
|
964
|
+
delta: number;
|
|
1025
965
|
notes?: string;
|
|
966
|
+
/**
|
|
967
|
+
* Which balance to move. Default `"MAIN"`, the ordinary wallet.
|
|
968
|
+
*
|
|
969
|
+
* `"RESERVED"` moves the Reserved Wallet instead — a second balance behind
|
|
970
|
+
* the wallet that a wallet-funded Arrear charge draws on once the wallet
|
|
971
|
+
* runs out (Wallet → Reserved down to 0 → Wallet goes negative). It must be
|
|
972
|
+
* switched on for the org (Settings → Organisation → "Enable Reserved
|
|
973
|
+
* balance in wallet"), else this is a `PlanError`. It never goes negative:
|
|
974
|
+
* a reduce below zero is refused (an `AllowanceError`), not capped — drawing
|
|
975
|
+
* down to exactly 0 is fine. `remaining` is then the Reserved balance. A
|
|
976
|
+
* `"MAIN"` adjustment never touches it.
|
|
977
|
+
*/
|
|
978
|
+
pool?: WalletPool;
|
|
979
|
+
/**
|
|
980
|
+
* Optional idempotency key (1–255 characters) that makes this adjustment
|
|
981
|
+
* safe to retry. The first call with a key adjusts; any repeat with the
|
|
982
|
+
* same key and the same request adjusts nothing and comes back with
|
|
983
|
+
* `replayed: true` (and when the original happened, `adjustedAt`). The same
|
|
984
|
+
* key with a different request is a `ConflictError`. Keys are unique per
|
|
985
|
+
* workspace and per adjust endpoint. **Auto-generated (UUID v4) if
|
|
986
|
+
* omitted** and reused across every retry of this call, so a network blip
|
|
987
|
+
* never adjusts twice — same as signals. Supply your own (e.g. your order
|
|
988
|
+
* id) to also dedupe your OWN retries, across restarts or redelivery.
|
|
989
|
+
*/
|
|
990
|
+
idempotencyKey?: string;
|
|
1026
991
|
}
|
|
1027
992
|
|
|
1028
993
|
/** Grant (positive) or claw back (negative) a credit balance. `delta` must be a
|
|
1029
|
-
* non-zero whole number. The credit is addressed by its stable `agentKey
|
|
1030
|
-
*
|
|
1031
|
-
*
|
|
994
|
+
* non-zero whole number. The credit is addressed by its stable `agentKey`,
|
|
995
|
+
* and must be a prepaid (ADVANCE) part of the customer's current plan — else
|
|
996
|
+
* a `PlanError` ("… is not part of this customer's plan"). A reduce is never
|
|
997
|
+
* rejected or floored for going below 0 — the resulting balance may read
|
|
998
|
+
* negative, same as a real-usage overdraft already can. */
|
|
1032
999
|
export interface CreditAdjustInput {
|
|
1033
1000
|
/** The credit's stable agent key (the same key used to record usage). */
|
|
1034
1001
|
agentKey: string;
|
|
1035
1002
|
delta: number;
|
|
1036
1003
|
notes?: string;
|
|
1004
|
+
/**
|
|
1005
|
+
* Optional idempotency key (1–255 characters) that makes this adjustment
|
|
1006
|
+
* safe to retry. The first call with a key adjusts; any repeat with the
|
|
1007
|
+
* same key and the same request adjusts nothing and comes back with
|
|
1008
|
+
* `replayed: true` (and when the original happened, `adjustedAt`). The same
|
|
1009
|
+
* key with a different request is a `ConflictError`. Keys are unique per
|
|
1010
|
+
* workspace and per adjust endpoint. **Auto-generated (UUID v4) if
|
|
1011
|
+
* omitted** and reused across every retry of this call, so a network blip
|
|
1012
|
+
* never adjusts twice — same as signals. Supply your own (e.g. your order
|
|
1013
|
+
* id) to also dedupe your OWN retries, across restarts or redelivery.
|
|
1014
|
+
*/
|
|
1015
|
+
idempotencyKey?: string;
|
|
1037
1016
|
}
|
|
1038
1017
|
|
|
1039
1018
|
/** Grant/claw an outcome balance. `delta` is a non-zero whole number. The
|
|
1040
1019
|
* outcome is addressed here by a STEP's `agentKey`, which resolves to its
|
|
1041
|
-
* parent outcome — NOT by the outcome's own `agentKey
|
|
1042
|
-
* which this endpoint does not accept.
|
|
1020
|
+
* parent outcome — NOT by the outcome's own `agentKey`,
|
|
1021
|
+
* which this endpoint does not accept. The outcome must be a prepaid
|
|
1022
|
+
* (ADVANCE) part of the customer's current plan — else a `PlanError`. A reduce is never rejected or floored
|
|
1043
1023
|
* for going below 0 — the resulting balance may read negative, same as a
|
|
1044
1024
|
* real-usage overdraft already can. */
|
|
1045
1025
|
export interface OutcomeAdjustInput {
|
|
@@ -1048,17 +1028,42 @@ export interface OutcomeAdjustInput {
|
|
|
1048
1028
|
agentKey: string;
|
|
1049
1029
|
delta: number;
|
|
1050
1030
|
notes?: string;
|
|
1031
|
+
/**
|
|
1032
|
+
* Optional idempotency key (1–255 characters) that makes this adjustment
|
|
1033
|
+
* safe to retry. The first call with a key adjusts; any repeat with the
|
|
1034
|
+
* same key and the same request adjusts nothing and comes back with
|
|
1035
|
+
* `replayed: true` (and when the original happened, `adjustedAt`). The same
|
|
1036
|
+
* key with a different request is a `ConflictError`. Keys are unique per
|
|
1037
|
+
* workspace and per adjust endpoint. **Auto-generated (UUID v4) if
|
|
1038
|
+
* omitted** and reused across every retry of this call, so a network blip
|
|
1039
|
+
* never adjusts twice — same as signals. Supply your own (e.g. your order
|
|
1040
|
+
* id) to also dedupe your OWN retries, across restarts or redelivery.
|
|
1041
|
+
*/
|
|
1042
|
+
idempotencyKey?: string;
|
|
1051
1043
|
}
|
|
1052
1044
|
|
|
1053
1045
|
/** Grant/claw a unit balance. `delta` is non-zero (fractional allowed). The
|
|
1054
|
-
* unit is addressed by its stable `agentKey
|
|
1055
|
-
*
|
|
1056
|
-
*
|
|
1046
|
+
* unit is addressed by its stable `agentKey`, and must be a prepaid
|
|
1047
|
+
* (ADVANCE) part of the customer's current plan — else a `PlanError`. A
|
|
1048
|
+
* reduce is never rejected or floored for going below 0 — the resulting
|
|
1049
|
+
* balance may read negative, same as a real-usage overdraft already can. */
|
|
1057
1050
|
export interface UnitAdjustInput {
|
|
1058
1051
|
/** The unit's stable agent key (the same key used to record usage). */
|
|
1059
1052
|
agentKey: string;
|
|
1060
1053
|
delta: number;
|
|
1061
1054
|
notes?: string;
|
|
1055
|
+
/**
|
|
1056
|
+
* Optional idempotency key (1–255 characters) that makes this adjustment
|
|
1057
|
+
* safe to retry. The first call with a key adjusts; any repeat with the
|
|
1058
|
+
* same key and the same request adjusts nothing and comes back with
|
|
1059
|
+
* `replayed: true` (and when the original happened, `adjustedAt`). The same
|
|
1060
|
+
* key with a different request is a `ConflictError`. Keys are unique per
|
|
1061
|
+
* workspace and per adjust endpoint. **Auto-generated (UUID v4) if
|
|
1062
|
+
* omitted** and reused across every retry of this call, so a network blip
|
|
1063
|
+
* never adjusts twice — same as signals. Supply your own (e.g. your order
|
|
1064
|
+
* id) to also dedupe your OWN retries, across restarts or redelivery.
|
|
1065
|
+
*/
|
|
1066
|
+
idempotencyKey?: string;
|
|
1062
1067
|
}
|
|
1063
1068
|
|
|
1064
1069
|
/**
|
|
@@ -1071,7 +1076,7 @@ export interface UnitAdjustInput {
|
|
|
1071
1076
|
*/
|
|
1072
1077
|
export interface CompositeAdjustInput {
|
|
1073
1078
|
/**
|
|
1074
|
-
* The composite's stable identifier — its `refId
|
|
1079
|
+
* The composite's stable identifier — its `refId`,
|
|
1075
1080
|
* the same value signals tag it with, NOT `agentKey` (a composite has no
|
|
1076
1081
|
* `agentKey` column of its own). Named `agentKey` on the wire only so the
|
|
1077
1082
|
* four adjust endpoints share one request shape.
|
|
@@ -1079,266 +1084,64 @@ export interface CompositeAdjustInput {
|
|
|
1079
1084
|
agentKey: string;
|
|
1080
1085
|
delta: number;
|
|
1081
1086
|
notes?: string;
|
|
1082
|
-
}
|
|
1083
|
-
|
|
1084
|
-
// ---------------------------------------------------------------------------
|
|
1085
|
-
// Entitlement catalogs: Credits, Outcomes, Units
|
|
1086
|
-
// ---------------------------------------------------------------------------
|
|
1087
|
-
|
|
1088
|
-
/** A per-model token bundle attached to a credit or outcome step. */
|
|
1089
|
-
export interface ModelBundleEntry {
|
|
1090
|
-
orgModelId: string;
|
|
1091
|
-
/** Display label; the server defaults it from the model when omitted. */
|
|
1092
|
-
modelName?: string;
|
|
1093
|
-
tokens: number;
|
|
1094
|
-
input: number;
|
|
1095
|
-
output: number;
|
|
1096
|
-
cache: number;
|
|
1097
|
-
}
|
|
1098
|
-
|
|
1099
|
-
/** One point on a cost-over-time analytics series. */
|
|
1100
|
-
export interface CostPoint {
|
|
1101
|
-
/** UTC day, `YYYY-MM-DD`. */
|
|
1102
|
-
dateIso: string;
|
|
1103
|
-
/** Short display label, e.g. "Jun 24". */
|
|
1104
|
-
label: string;
|
|
1105
|
-
/** Average cost that day, or `null` on days with no usage. */
|
|
1106
|
-
cost: number | null;
|
|
1107
|
-
reqs: number;
|
|
1108
|
-
}
|
|
1109
|
-
|
|
1110
|
-
/** Summary stats across a cost-over-time series. */
|
|
1111
|
-
export interface CostStats {
|
|
1112
|
-
activeDays: number;
|
|
1113
|
-
avgCost: number | null;
|
|
1114
|
-
peakCost: number | null;
|
|
1115
|
-
troughCost: number | null;
|
|
1116
|
-
deviationPct: number | null;
|
|
1117
|
-
}
|
|
1118
|
-
|
|
1119
|
-
/** Cost-over-time analytics for a credit (`credits.get().analytics`). */
|
|
1120
|
-
export interface CreditAnalytics {
|
|
1121
|
-
basePrice: number;
|
|
1122
|
-
pricePerCredit: number;
|
|
1123
|
-
marginPercent: number;
|
|
1124
|
-
points: CostPoint[];
|
|
1125
|
-
stats: CostStats;
|
|
1126
|
-
}
|
|
1127
|
-
|
|
1128
|
-
/** Cost-over-time analytics for an outcome (`outcomes.get().analytics`).
|
|
1129
|
-
* Each point adds `completions` (workflows finished that day). */
|
|
1130
|
-
export interface OutcomeAnalytics {
|
|
1131
|
-
basePrice: number;
|
|
1132
|
-
pricePerOutcome: number;
|
|
1133
|
-
marginPercent: number;
|
|
1134
|
-
points: (CostPoint & { completions: number })[];
|
|
1135
|
-
stats: CostStats;
|
|
1136
|
-
}
|
|
1137
|
-
|
|
1138
|
-
export interface Credit {
|
|
1139
|
-
id: string;
|
|
1140
|
-
name: string;
|
|
1141
|
-
agentKey: string;
|
|
1142
|
-
description: string | null;
|
|
1143
|
-
tokensPerCredit: number;
|
|
1144
|
-
basePrice: number;
|
|
1145
|
-
marginPercent: number;
|
|
1146
|
-
pricePerCredit: number;
|
|
1147
|
-
isActive: boolean;
|
|
1148
|
-
createdAt: string;
|
|
1149
|
-
}
|
|
1150
|
-
|
|
1151
|
-
/** `credits.get()` — adds the model bundle plus usage stats/analytics. */
|
|
1152
|
-
export interface CreditDetail extends Credit {
|
|
1153
|
-
modelBundle: ModelBundleEntry[];
|
|
1154
|
-
createdByName: string;
|
|
1155
|
-
stats: {
|
|
1156
|
-
customerCount: number;
|
|
1157
|
-
planCount: number;
|
|
1158
|
-
totalGranted: number;
|
|
1159
|
-
totalUsed: number;
|
|
1160
|
-
revenue: number;
|
|
1161
|
-
usageLogCount: number;
|
|
1162
|
-
};
|
|
1163
|
-
analytics: CreditAnalytics;
|
|
1164
|
-
}
|
|
1165
|
-
|
|
1166
|
-
export interface CreateCreditInput {
|
|
1167
|
-
name: string;
|
|
1168
|
-
/** Lowercased stable key used by `signals.credit({ agentKey })`. */
|
|
1169
|
-
agentKey: string;
|
|
1170
|
-
basePrice: number;
|
|
1171
|
-
marginPercent: number;
|
|
1172
|
-
pricePerCredit: number;
|
|
1173
|
-
description?: string;
|
|
1174
|
-
tokensPerCredit?: number;
|
|
1175
|
-
modelBundle?: ModelBundleEntry[];
|
|
1176
|
-
}
|
|
1177
|
-
|
|
1178
|
-
export type UpdateCreditInput = CreateCreditInput;
|
|
1179
|
-
|
|
1180
|
-
export interface OutcomeStepInput {
|
|
1181
|
-
id?: string;
|
|
1182
|
-
name: string;
|
|
1183
|
-
/** Lowercased stable key used by `signals.outcome({ agentKey })`. */
|
|
1184
|
-
agentKey: string;
|
|
1185
|
-
basePrice: number;
|
|
1186
|
-
modelBundle?: ModelBundleEntry[];
|
|
1187
|
-
}
|
|
1188
|
-
|
|
1189
|
-
export interface Outcome {
|
|
1190
|
-
id: string;
|
|
1191
|
-
name: string;
|
|
1192
|
-
/**
|
|
1193
|
-
* The OUTCOME's own stable agent key — its durable identity, mirroring
|
|
1194
|
-
* {@link Credit.agentKey}. Lowercased `[a-z0-9._-]`, max 80 chars, unique per
|
|
1195
|
-
* organisation. A rename never changes it.
|
|
1196
|
-
*
|
|
1197
|
-
* Distinct from each step's `agentKey` in `steps`, and in a SEPARATE
|
|
1198
|
-
* namespace: usage is always reported against a STEP's key
|
|
1199
|
-
* (`signals.outcome({ agentKey })`), never this one. This key identifies the
|
|
1200
|
-
* outcome itself when creating or updating it.
|
|
1201
|
-
*/
|
|
1202
|
-
agentKey: string;
|
|
1203
|
-
description: string | null;
|
|
1204
|
-
isActive: boolean;
|
|
1205
|
-
marginPercent: number;
|
|
1206
|
-
pricePerOutcome: number;
|
|
1207
|
-
}
|
|
1208
|
-
|
|
1209
|
-
/** `outcomes.get()` — adds steps plus in-flight/completed stats. */
|
|
1210
|
-
export interface OutcomeDetail extends Outcome {
|
|
1211
|
-
/** Only the DETAIL row carries these — `outcomes.list()` returns neither.
|
|
1212
|
-
* They were previously declared on {@link Outcome} itself, where
|
|
1213
|
-
* `createdAt` was typed as a required `string` that is always `undefined`
|
|
1214
|
-
* in practice. */
|
|
1215
|
-
createdAt: string;
|
|
1216
|
-
createdByName: string | null;
|
|
1217
|
-
steps: { name: string; agentKey: string }[];
|
|
1218
|
-
stats: {
|
|
1219
|
-
stepCount: number;
|
|
1220
|
-
customerCount: number;
|
|
1221
|
-
inFlight: number;
|
|
1222
|
-
completed: number;
|
|
1223
|
-
totalRemaining: number;
|
|
1224
|
-
};
|
|
1225
|
-
analytics: OutcomeAnalytics;
|
|
1226
|
-
}
|
|
1227
|
-
|
|
1228
|
-
export interface CreateOutcomeInput {
|
|
1229
|
-
name: string;
|
|
1230
1087
|
/**
|
|
1231
|
-
*
|
|
1232
|
-
*
|
|
1233
|
-
*
|
|
1234
|
-
*
|
|
1235
|
-
* key
|
|
1236
|
-
*
|
|
1088
|
+
* Optional idempotency key (1–255 characters) that makes this adjustment
|
|
1089
|
+
* safe to retry. The first call with a key adjusts; any repeat with the
|
|
1090
|
+
* same key and the same request adjusts nothing and comes back with
|
|
1091
|
+
* `replayed: true` (and when the original happened, `adjustedAt`). The same
|
|
1092
|
+
* key with a different request is a `ConflictError`. Keys are unique per
|
|
1093
|
+
* workspace and per adjust endpoint. **Auto-generated (UUID v4) if
|
|
1094
|
+
* omitted** and reused across every retry of this call, so a network blip
|
|
1095
|
+
* never adjusts twice — same as signals. Supply your own (e.g. your order
|
|
1096
|
+
* id) to also dedupe your OWN retries, across restarts or redelivery.
|
|
1237
1097
|
*/
|
|
1238
|
-
|
|
1239
|
-
basePrice: number;
|
|
1240
|
-
marginPercent: number;
|
|
1241
|
-
pricePerOutcome: number;
|
|
1242
|
-
description?: string | null;
|
|
1243
|
-
isActive?: boolean;
|
|
1244
|
-
/** 1–50 steps; step names and agent keys must be unique. */
|
|
1245
|
-
steps: OutcomeStepInput[];
|
|
1246
|
-
}
|
|
1247
|
-
|
|
1248
|
-
export type UpdateOutcomeInput = CreateOutcomeInput;
|
|
1249
|
-
|
|
1250
|
-
export type UnitPricingType = "FLAT" | "SLAB" | "VOLUME";
|
|
1251
|
-
|
|
1252
|
-
/** A tier for SLAB/VOLUME pricing; only the last tier may have `upTo: null`. */
|
|
1253
|
-
export interface UnitTierInput {
|
|
1254
|
-
id?: string;
|
|
1255
|
-
upTo: number | null;
|
|
1256
|
-
price: number;
|
|
1257
|
-
}
|
|
1258
|
-
|
|
1259
|
-
export interface UnitTier {
|
|
1260
|
-
id: string;
|
|
1261
|
-
upTo: number | null;
|
|
1262
|
-
price: number;
|
|
1263
|
-
order: number;
|
|
1264
|
-
}
|
|
1265
|
-
|
|
1266
|
-
export interface Unit {
|
|
1267
|
-
id: string;
|
|
1268
|
-
/** Stable per-org report key — what `signals.unit({ agentKey })` sends.
|
|
1269
|
-
* The ONLY identifier accepted when reporting unit consumption. */
|
|
1270
|
-
agentKey: string;
|
|
1271
|
-
name: string;
|
|
1272
|
-
description: string | null;
|
|
1273
|
-
pricingType: UnitPricingType;
|
|
1274
|
-
flatPrice: number;
|
|
1275
|
-
tiers: UnitTier[];
|
|
1276
|
-
isActive: boolean;
|
|
1277
|
-
createdAt: string;
|
|
1278
|
-
createdByName: string | null;
|
|
1098
|
+
idempotencyKey?: string;
|
|
1279
1099
|
}
|
|
1280
1100
|
|
|
1281
|
-
/**
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1101
|
+
/**
|
|
1102
|
+
* What every adjust call returns.
|
|
1103
|
+
*
|
|
1104
|
+
* `replayed: true` means this call adjusted NOTHING: an earlier call with the
|
|
1105
|
+
* same `idempotencyKey` already did, at `adjustedAt`. `remaining` is always
|
|
1106
|
+
* the balance as it is now. `customerArchived` is true when the customer is
|
|
1107
|
+
* archived — archived customers follow the same rules (archiving cancels
|
|
1108
|
+
* their plan, so usually only the wallet can still move).
|
|
1109
|
+
*/
|
|
1110
|
+
export interface AdjustResult {
|
|
1290
1111
|
remaining: number;
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
* `createdByName` is inherited from `Unit`. */
|
|
1296
|
-
export interface UnitDetail extends Unit {
|
|
1297
|
-
stats: {
|
|
1298
|
-
planCount: number;
|
|
1299
|
-
customerCount: number;
|
|
1300
|
-
totalRemaining: number;
|
|
1301
|
-
totalUsed: number;
|
|
1302
|
-
};
|
|
1303
|
-
/** First page (≤10) of customers currently metered on this unit. */
|
|
1304
|
-
customers: UnitCustomerRow[];
|
|
1305
|
-
}
|
|
1306
|
-
|
|
1307
|
-
/** Flat per-event pricing — a single `flatPrice` (defaults to 0), no tiers. */
|
|
1308
|
-
export interface FlatUnitInput {
|
|
1309
|
-
name: string;
|
|
1310
|
-
/** Stable per-org report key (`signals.unit({ agentKey })`); `[a-z0-9._-]`. */
|
|
1311
|
-
agentKey: string;
|
|
1312
|
-
pricingType: "FLAT";
|
|
1313
|
-
/** Price per event; defaults to 0. */
|
|
1314
|
-
flatPrice?: number;
|
|
1315
|
-
description?: string | null;
|
|
1316
|
-
isActive?: boolean;
|
|
1317
|
-
}
|
|
1318
|
-
|
|
1319
|
-
/** Tiered pricing (SLAB or VOLUME) — at least one tier is required. */
|
|
1320
|
-
export interface TieredUnitInput {
|
|
1321
|
-
name: string;
|
|
1322
|
-
/** Stable per-org report key (`signals.unit({ agentKey })`); `[a-z0-9._-]`. */
|
|
1323
|
-
agentKey: string;
|
|
1324
|
-
pricingType: "SLAB" | "VOLUME";
|
|
1325
|
-
/** At least one tier (≤50). Only the last tier may have `upTo: null`. */
|
|
1326
|
-
tiers: UnitTierInput[];
|
|
1327
|
-
description?: string | null;
|
|
1328
|
-
isActive?: boolean;
|
|
1112
|
+
replayed: boolean;
|
|
1113
|
+
/** Set only on a replay: when the original adjustment happened (ISO 8601). */
|
|
1114
|
+
adjustedAt?: string;
|
|
1115
|
+
customerArchived: boolean;
|
|
1329
1116
|
}
|
|
1330
1117
|
|
|
1331
1118
|
/**
|
|
1332
|
-
*
|
|
1333
|
-
*
|
|
1334
|
-
*
|
|
1119
|
+
* Change how much a customer is granted every billing cycle. The difference is
|
|
1120
|
+
* applied to the current balance immediately (a shrink is never floored — the
|
|
1121
|
+
* balance may read negative). `quantity` is USD for the wallet and a whole
|
|
1122
|
+
* number for everything else. `agentKey` resolves the same way as the adjust
|
|
1123
|
+
* endpoints: a credit's or unit's `agentKey`, an outcome STEP's `agentKey`, or
|
|
1124
|
+
* a composite's `refId`. The wallet needs none — a customer has at most one.
|
|
1335
1125
|
*/
|
|
1336
|
-
export type
|
|
1126
|
+
export type RecurringGrantInput =
|
|
1127
|
+
| { kind: "wallet"; quantity: number }
|
|
1128
|
+
| {
|
|
1129
|
+
kind: "credit" | "outcome" | "unit" | "composite";
|
|
1130
|
+
agentKey: string;
|
|
1131
|
+
quantity: number;
|
|
1132
|
+
};
|
|
1337
1133
|
|
|
1338
|
-
|
|
1134
|
+
/** Result of `customers.updateRecurringGrant()`. */
|
|
1135
|
+
export interface RecurringGrantResult {
|
|
1136
|
+
kind: RecurringGrantInput["kind"];
|
|
1137
|
+
/** The new per-cycle amount. */
|
|
1138
|
+
quantity: number;
|
|
1139
|
+
/** The wallet balance after the change — only present for `kind: "wallet"`. */
|
|
1140
|
+
balanceUsd?: number;
|
|
1141
|
+
}
|
|
1339
1142
|
|
|
1340
1143
|
// ---------------------------------------------------------------------------
|
|
1341
|
-
// Unit consumption (recorded via signals
|
|
1144
|
+
// Unit consumption (recorded via signals)
|
|
1342
1145
|
// ---------------------------------------------------------------------------
|
|
1343
1146
|
|
|
1344
1147
|
/**
|
|
@@ -1347,8 +1150,7 @@ export type UpdateUnitInput = CreateUnitInput;
|
|
|
1347
1150
|
* the display name is deliberately not accepted, so a rename can never redirect
|
|
1348
1151
|
* a live integration. Keys are matched exactly (they are stored lowercased).
|
|
1349
1152
|
*/
|
|
1350
|
-
export
|
|
1351
|
-
customerId: string;
|
|
1153
|
+
export type UnitInput = CustomerRef & {
|
|
1352
1154
|
agentKey: string;
|
|
1353
1155
|
member?: string;
|
|
1354
1156
|
/**
|
|
@@ -1379,7 +1181,7 @@ export interface UnitInput {
|
|
|
1379
1181
|
* auto key cannot survive.
|
|
1380
1182
|
*/
|
|
1381
1183
|
idempotencyKey?: string;
|
|
1382
|
-
}
|
|
1184
|
+
};
|
|
1383
1185
|
|
|
1384
1186
|
/**
|
|
1385
1187
|
* The result of `signals.unit()`.
|
|
@@ -1409,8 +1211,7 @@ export interface UnitTrackResult {
|
|
|
1409
1211
|
* Input for `signals.completeComposite()` — closes ONE occurrence of a
|
|
1410
1212
|
* composite, which is the moment it is billed.
|
|
1411
1213
|
*/
|
|
1412
|
-
export
|
|
1413
|
-
customerId: string;
|
|
1214
|
+
export type CompositeCompletionInput = CustomerRef & {
|
|
1414
1215
|
/** Which occurrence to close: the composite's `refId` and the correlation
|
|
1415
1216
|
* value the signals were tagged with. */
|
|
1416
1217
|
composite: CompositeTag;
|
|
@@ -1418,79 +1219,12 @@ export interface CompositeCompletionInput {
|
|
|
1418
1219
|
* safe no-op, so this only collapses retries into one recorded attempt
|
|
1419
1220
|
* rather than protecting against a double charge. */
|
|
1420
1221
|
idempotencyKey?: string;
|
|
1421
|
-
}
|
|
1222
|
+
};
|
|
1422
1223
|
|
|
1423
1224
|
// ---------------------------------------------------------------------------
|
|
1424
|
-
//
|
|
1225
|
+
// Composite completion
|
|
1425
1226
|
// ---------------------------------------------------------------------------
|
|
1426
1227
|
|
|
1427
|
-
/** One catalogue item a composite is restricted to. `agentKey` is what a
|
|
1428
|
-
* signal names, so it is the field you actually integrate against. */
|
|
1429
|
-
export interface CompositeCatalogueRef {
|
|
1430
|
-
id: string;
|
|
1431
|
-
name: string;
|
|
1432
|
-
agentKey: string;
|
|
1433
|
-
}
|
|
1434
|
-
|
|
1435
|
-
/** One composite in the org's catalogue — `cnk.composites.list()`. */
|
|
1436
|
-
export interface Composite {
|
|
1437
|
-
id: string;
|
|
1438
|
-
name: string;
|
|
1439
|
-
/** The stable identifier you put in a signal's `composite` block as `ref`. */
|
|
1440
|
-
refId: string;
|
|
1441
|
-
description: string | null;
|
|
1442
|
-
/** USD charged per occurrence WHEN A PLAN SELLS THIS as a composite
|
|
1443
|
-
* component (`quantity × price`, frozen into the purchase at buy time). The
|
|
1444
|
-
* catalogue row alone bills nothing. */
|
|
1445
|
-
price: number;
|
|
1446
|
-
/** False once archived. An archived composite stops NEW signals resolving to
|
|
1447
|
-
* it but keeps every row it already owns. */
|
|
1448
|
-
isActive: boolean;
|
|
1449
|
-
createdAt: string;
|
|
1450
|
-
/**
|
|
1451
|
-
* The credits / outcomes / units this composite is restricted to — only
|
|
1452
|
-
* signals naming one of these may carry its tag.
|
|
1453
|
-
*
|
|
1454
|
-
* All three lists empty means UNRESTRICTED (it accepts any of the org's
|
|
1455
|
-
* traffic under this tag). Nothing created through the API can be
|
|
1456
|
-
* unrestricted, but rows predating that rule exist — so don't assume
|
|
1457
|
-
* non-empty.
|
|
1458
|
-
*/
|
|
1459
|
-
entitlements: {
|
|
1460
|
-
credits: CompositeCatalogueRef[];
|
|
1461
|
-
outcomes: CompositeCatalogueRef[];
|
|
1462
|
-
units: CompositeCatalogueRef[];
|
|
1463
|
-
};
|
|
1464
|
-
}
|
|
1465
|
-
|
|
1466
|
-
/** Input for `cnk.composites.create()`. */
|
|
1467
|
-
export interface CreateCompositeInput {
|
|
1468
|
-
name: string;
|
|
1469
|
-
/**
|
|
1470
|
-
* The tag identifier. Lowercased, and restricted to the same characters as
|
|
1471
|
-
* an `agentKey` — but validated harder than one, because it may not collide
|
|
1472
|
-
* with a field the ingest schemas already own (`customerId`, `usage`,
|
|
1473
|
-
* `agentKey`, `runId`, `member`, `custom`, `composite`, …). A colliding
|
|
1474
|
-
* `refId` is refused at create time rather than silently ignored at ingest.
|
|
1475
|
-
*/
|
|
1476
|
-
refId: string;
|
|
1477
|
-
/** USD per occurrence once a plan sells it. Required — an unpriced composite
|
|
1478
|
-
* put on a plan would bill 0, which is a money bug that is hard to see. */
|
|
1479
|
-
price: number;
|
|
1480
|
-
description?: string | null;
|
|
1481
|
-
/**
|
|
1482
|
-
* What the composite wraps. At least one id across the three lists is
|
|
1483
|
-
* REQUIRED: a composite restricted to nothing would accept every signal in
|
|
1484
|
-
* the org. Get the ids from `credits.list()`, `outcomes.list()` and
|
|
1485
|
-
* `units.list()`.
|
|
1486
|
-
*/
|
|
1487
|
-
entitlements: {
|
|
1488
|
-
creditIds?: string[];
|
|
1489
|
-
outcomeIds?: string[];
|
|
1490
|
-
unitIds?: string[];
|
|
1491
|
-
};
|
|
1492
|
-
}
|
|
1493
|
-
|
|
1494
1228
|
/**
|
|
1495
1229
|
* The result of `signals.completeComposite()`.
|
|
1496
1230
|
*
|
|
@@ -1523,8 +1257,7 @@ export interface CompositeCompletionResult {
|
|
|
1523
1257
|
rawId?: string;
|
|
1524
1258
|
}
|
|
1525
1259
|
|
|
1526
|
-
/** One serialized unit-consumption event — the result of `signals.unit()
|
|
1527
|
-
* each element of `UnitUsageList.events`. */
|
|
1260
|
+
/** One serialized unit-consumption event — the result of `signals.unit()`. */
|
|
1528
1261
|
export interface SerializedUnitUsage {
|
|
1529
1262
|
id: string;
|
|
1530
1263
|
customerId: string;
|
|
@@ -1540,48 +1273,6 @@ export interface SerializedUnitUsage {
|
|
|
1540
1273
|
createdAt: string;
|
|
1541
1274
|
}
|
|
1542
1275
|
|
|
1543
|
-
export interface UnitUsageRow {
|
|
1544
|
-
unit: string;
|
|
1545
|
-
/** The unit's stable agent key — what to send to report against it. */
|
|
1546
|
-
agentKey: string | null;
|
|
1547
|
-
billingMode: BillingMode;
|
|
1548
|
-
granted?: number;
|
|
1549
|
-
used: number;
|
|
1550
|
-
remaining?: number;
|
|
1551
|
-
}
|
|
1552
|
-
|
|
1553
|
-
export interface UnitUsageList {
|
|
1554
|
-
customer: { id: string; name: string };
|
|
1555
|
-
units: UnitUsageRow[];
|
|
1556
|
-
events: SerializedUnitUsage[];
|
|
1557
|
-
}
|
|
1558
|
-
|
|
1559
|
-
// ---------------------------------------------------------------------------
|
|
1560
|
-
// Webhooks (threshold alerts)
|
|
1561
|
-
// ---------------------------------------------------------------------------
|
|
1562
|
-
|
|
1563
|
-
export type ThresholdKind = "CREDIT" | "OUTCOME" | "WALLET";
|
|
1564
|
-
|
|
1565
|
-
export interface Webhook {
|
|
1566
|
-
id: string;
|
|
1567
|
-
kind: ThresholdKind;
|
|
1568
|
-
threshold: number;
|
|
1569
|
-
url: string;
|
|
1570
|
-
isActive: boolean;
|
|
1571
|
-
createdAt: string;
|
|
1572
|
-
updatedAt: string;
|
|
1573
|
-
createdByName: string | null;
|
|
1574
|
-
}
|
|
1575
|
-
|
|
1576
|
-
export interface UpsertWebhookInput {
|
|
1577
|
-
kind: ThresholdKind;
|
|
1578
|
-
/** Fire when the balance crosses this value. */
|
|
1579
|
-
threshold: number;
|
|
1580
|
-
/** http(s) URL to POST the alert to. */
|
|
1581
|
-
url: string;
|
|
1582
|
-
isActive?: boolean;
|
|
1583
|
-
}
|
|
1584
|
-
|
|
1585
1276
|
// ---------------------------------------------------------------------------
|
|
1586
1277
|
// Config & hooks
|
|
1587
1278
|
// ---------------------------------------------------------------------------
|