@clocknext/sdk 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -8,12 +8,44 @@
8
8
  */
9
9
  type SignalType = "wallet" | "credit" | "outcome";
10
10
  type SignalStatus = "SUCCESS" | "FAILURE" | "PENDING";
11
- /** Token counts for a signal. All default to 0. */
11
+ /**
12
+ * Token counts for a signal. `input` and `output` are required — every metered
13
+ * call has them, and the server requires them. `cache` (provider-specific
14
+ * prompt-cache reads) is optional and defaults to 0 server-side when omitted.
15
+ */
12
16
  interface Tokens {
13
- input?: number;
14
- output?: number;
17
+ input: number;
18
+ output: number;
15
19
  cache?: number;
16
20
  }
21
+ /** The organisation + key behind a request — `cnk.workspace.me()`. */
22
+ interface WorkspaceIdentity {
23
+ organization: {
24
+ id: string;
25
+ name: string;
26
+ slug: string | null;
27
+ /** `sandbox` is a disposable staging twin; `live` bills for real. Check
28
+ * this before sending production traffic. */
29
+ environment: "sandbox" | "live";
30
+ };
31
+ apiKey: {
32
+ prefix: string;
33
+ lastFour: string;
34
+ expiresAt: string | null;
35
+ } | null;
36
+ }
37
+ /** One model the org has enabled — `cnk.workspace.models()`. The `modelId` is
38
+ * what you put in a signal's `model`. Prices are USD per 1,000,000 tokens. */
39
+ interface Model {
40
+ modelId: string;
41
+ modelName: string;
42
+ provider: string;
43
+ providerName: string;
44
+ isActive: boolean;
45
+ inputPrice: number;
46
+ outputPrice: number;
47
+ cachePrice: number;
48
+ }
17
49
  interface SignalBase {
18
50
  /** The customer this usage belongs to (required). */
19
51
  customerId: string;
@@ -22,14 +54,21 @@ interface SignalBase {
22
54
  * (Settings → Models). Matched case-insensitively against `OrgModel.modelId`.
23
55
  */
24
56
  model: string;
25
- /** Token counts for this call. */
26
- tokens?: Tokens;
57
+ /** Token counts for this call — required; every metered signal is priced on
58
+ * tokens. (`cache` within is optional; `input`/`output` are not.) */
59
+ tokens: Tokens;
27
60
  /** Optional member (email) this usage is attributed to. */
28
61
  member?: string;
29
- /** Defaults to SUCCESS. */
30
- status?: SignalStatus;
31
62
  /** Free-form metadata. Credit rules can target `custom.<key>` paths. */
32
63
  custom?: Record<string, unknown>;
64
+ /**
65
+ * Idempotency key for safe retries. **Auto-generated (UUID v4) if omitted**
66
+ * and reused across every retry of this signal, so a retried send is
67
+ * deduplicated server-side instead of double-recording. Supply your own — a
68
+ * stable id for this logical event — to also dedup across process restarts or
69
+ * at-least-once redelivery, which an in-memory auto key can't survive.
70
+ */
71
+ idempotencyKey?: string;
33
72
  }
34
73
  /** Meters a credit, identified by the credit's stable `agentKey`. */
35
74
  interface CreditSignal extends SignalBase {
@@ -150,9 +189,10 @@ interface CustomerProfileInput {
150
189
  /** ISO 4217 (3 letters); must be enabled for the org. */
151
190
  currencyCode?: string;
152
191
  }
153
- /** `name` is required on create. */
192
+ /** `name` and `email` are required on create; every other field is optional. */
154
193
  type CreateCustomerInput = CustomerProfileInput & {
155
194
  name: string;
195
+ email: string;
156
196
  };
157
197
  interface CustomerList {
158
198
  customers: ApiCustomer[];
@@ -219,18 +259,68 @@ type PlanKind = "FLAT_PRICE" | "PAY_AS_YOU_GO" | "PAY_PER_SEAT";
219
259
  type ComponentType = "WALLET" | "CREDIT" | "OUTCOME" | "UNIT" | "FLAT";
220
260
  /** ADVANCE bills up-front for the cycle; ARREAR bills for what was consumed. */
221
261
  type BillingMode = "ADVANCE" | "ARREAR";
222
- /** One entitlement line in a plan. Set the id matching `type` (creditId for CREDIT, …). */
223
- interface PlanComponentInput {
224
- type: ComponentType;
262
+ /** Prepaid USD wallet. `amount` is the funded balance (required). Max one
263
+ * wallet component per plan. */
264
+ interface WalletComponentInput {
265
+ type: "WALLET";
225
266
  billingMode: BillingMode;
226
- creditId?: string | null;
227
- outcomeId?: string | null;
228
- unitId?: string | null;
229
- /** Granted quantity (ADVANCE components). */
230
- quantity?: number | null;
231
- /** Flat amount (FLAT / WALLET components). */
232
- amount?: number | null;
267
+ amount: number;
268
+ }
269
+ /** A one-off flat fee — `amount` is required. Max one flat component per plan;
270
+ * not allowed on FREE plans. */
271
+ interface FlatComponentInput {
272
+ type: "FLAT";
273
+ billingMode: BillingMode;
274
+ amount: number;
233
275
  }
276
+ /** A credit entitlement, referenced by `creditId`. Billed ADVANCE it needs a
277
+ * granted `quantity`; billed ARREAR it meters usage with no upfront grant. */
278
+ type CreditComponentInput = {
279
+ type: "CREDIT";
280
+ billingMode: "ADVANCE";
281
+ creditId: string;
282
+ quantity: number;
283
+ } | {
284
+ type: "CREDIT";
285
+ billingMode: "ARREAR";
286
+ creditId: string;
287
+ quantity?: number | null;
288
+ };
289
+ /** An outcome entitlement, referenced by `outcomeId`. ADVANCE needs a granted
290
+ * `quantity`; ARREAR meters usage. */
291
+ type OutcomeComponentInput = {
292
+ type: "OUTCOME";
293
+ billingMode: "ADVANCE";
294
+ outcomeId: string;
295
+ quantity: number;
296
+ } | {
297
+ type: "OUTCOME";
298
+ billingMode: "ARREAR";
299
+ outcomeId: string;
300
+ quantity?: number | null;
301
+ };
302
+ /** A unit entitlement, referenced by `unitId`. ADVANCE needs a granted
303
+ * `quantity`; ARREAR meters usage. */
304
+ type UnitComponentInput = {
305
+ type: "UNIT";
306
+ billingMode: "ADVANCE";
307
+ unitId: string;
308
+ quantity: number;
309
+ } | {
310
+ type: "UNIT";
311
+ billingMode: "ARREAR";
312
+ unitId: string;
313
+ quantity?: number | null;
314
+ };
315
+ /**
316
+ * One entitlement line in a plan — a discriminated union on `type` (and, where
317
+ * it matters, `billingMode`) so the per-type fields the server requires are
318
+ * enforced at compile time instead of surfacing as runtime 422s:
319
+ * - CREDIT / OUTCOME / UNIT require their matching id;
320
+ * - CREDIT / OUTCOME / UNIT require `quantity` when billed ADVANCE;
321
+ * - WALLET / FLAT require `amount`.
322
+ */
323
+ type PlanComponentInput = WalletComponentInput | FlatComponentInput | CreditComponentInput | OutcomeComponentInput | UnitComponentInput;
234
324
  interface CreatePlanInput {
235
325
  name: string;
236
326
  description?: string | null;
@@ -543,7 +633,8 @@ interface UnitAdjustInput {
543
633
  /** A per-model token bundle attached to a credit or outcome step. */
544
634
  interface ModelBundleEntry {
545
635
  orgModelId: string;
546
- modelName: string;
636
+ /** Display label; the server defaults it from the model when omitted. */
637
+ modelName?: string;
547
638
  tokens: number;
548
639
  input: number;
549
640
  output: number;
@@ -671,25 +762,50 @@ interface UnitDetail extends Unit {
671
762
  /** First page (≤10) of customers currently metered on this unit. */
672
763
  customers: Record<string, unknown>[];
673
764
  }
674
- interface CreateUnitInput {
765
+ /** Flat per-event pricing — a single `flatPrice` (defaults to 0), no tiers. */
766
+ interface FlatUnitInput {
675
767
  name: string;
676
- pricingType: UnitPricingType;
677
- /** Required for FLAT pricing. */
768
+ /** Stable per-org report key (`signals.unit({ agentKey })`); `[a-z0-9._-]`. */
769
+ agentKey: string;
770
+ pricingType: "FLAT";
771
+ /** Price per event; defaults to 0. */
678
772
  flatPrice?: number;
679
- /** Required for SLAB/VOLUME pricing (≤50 tiers). */
680
- tiers?: UnitTierInput[];
681
773
  description?: string | null;
682
774
  isActive?: boolean;
683
775
  }
776
+ /** Tiered pricing (SLAB or VOLUME) — at least one tier is required. */
777
+ interface TieredUnitInput {
778
+ name: string;
779
+ /** Stable per-org report key (`signals.unit({ agentKey })`); `[a-z0-9._-]`. */
780
+ agentKey: string;
781
+ pricingType: "SLAB" | "VOLUME";
782
+ /** At least one tier (≤50). Only the last tier may have `upTo: null`. */
783
+ tiers: UnitTierInput[];
784
+ description?: string | null;
785
+ isActive?: boolean;
786
+ }
787
+ /**
788
+ * Create a unit type — a discriminated union on `pricingType`: `FLAT` takes an
789
+ * optional `flatPrice` (defaults to 0); `SLAB`/`VOLUME` require `tiers`, so the
790
+ * server's "add at least one tier" rule is enforced at compile time.
791
+ */
792
+ type CreateUnitInput = FlatUnitInput | TieredUnitInput;
684
793
  type UpdateUnitInput = CreateUnitInput;
685
- /** Record one unit-metered event. `unit` matches a catalog unit name (case-insensitive). */
794
+ /**
795
+ * Record one unit-metered event. The unit is addressed by its `agentKey` (the
796
+ * stable key set when the unit was created) — the ONLY accepted identifier;
797
+ * the display name is deliberately not accepted, so a rename can never redirect
798
+ * a live integration. Keys are matched exactly (they are stored lowercased).
799
+ */
686
800
  interface UnitInput {
687
801
  customerId: string;
688
- unit: string;
802
+ agentKey: string;
689
803
  member?: string;
690
804
  }
691
805
  interface UnitUsageRow {
692
806
  unit: string;
807
+ /** The unit's stable agent key — what to send to report against it. */
808
+ agentKey: string | null;
693
809
  billingMode: BillingMode;
694
810
  granted?: number;
695
811
  used: number;
@@ -918,10 +1034,6 @@ declare class Customers {
918
1034
  transaction: WalletTransaction;
919
1035
  balanceUsd: number;
920
1036
  }>;
921
- /** Set the customer's currency. `PUT …/:id/currency`. */
922
- setCurrency(id: string, currencyCode: string): Promise<void>;
923
- /** Set which credit types the customer is billed against. `PUT …/:id/credits`. */
924
- setCreditTypes(id: string, creditIds: string[]): Promise<void>;
925
1037
  /** Grant or claw back a credit balance. `POST …/:id/credits/adjust`. */
926
1038
  adjustCredit(id: string, input: CreditAdjustInput): Promise<void>;
927
1039
  /** Grant or claw back an outcome balance. Returns the remaining balance. */
@@ -1122,6 +1234,12 @@ declare class Signals {
1122
1234
  track(signal: Signal, opts?: {
1123
1235
  wait?: boolean;
1124
1236
  }): Promise<TrackResult>;
1237
+ /**
1238
+ * Validate + price a signal WITHOUT recording it (server `dryRun`). Returns
1239
+ * the projected usage log so an integration can preflight before sending real
1240
+ * traffic — no inbox row, wallet / outcome writes, or webhooks fire.
1241
+ */
1242
+ verify(signal: Signal): Promise<SerializedUsageLog | null>;
1125
1243
  /** Meter a named credit. */
1126
1244
  credit(input: CreditInput, opts?: {
1127
1245
  wait?: boolean;
@@ -1140,9 +1258,9 @@ declare class Signals {
1140
1258
  limit?: number;
1141
1259
  }): Promise<UsageList>;
1142
1260
  /**
1143
- * Record one unit-metered event (a fixed-price meter with no tokens), matched
1144
- * to a catalog unit by name. Sent immediately — unit events are not buffered.
1145
- * `POST /api/v1/units`.
1261
+ * Record one unit-metered event (a fixed-price meter with no tokens),
1262
+ * addressed to a catalog unit by its `agentKey`. Sent immediately — unit
1263
+ * events are not buffered. `POST /api/v1/units`.
1146
1264
  */
1147
1265
  unit(input: UnitInput): Promise<{
1148
1266
  unitUsage: Record<string, unknown>;
@@ -1193,6 +1311,23 @@ declare class Webhooks {
1193
1311
  delete(kind: ThresholdKind): Promise<void>;
1194
1312
  }
1195
1313
 
1314
+ /**
1315
+ * The `workspace` resource — read-only introspection of the org behind the API
1316
+ * key. Grounds an integration (which workspace, and is it `sandbox` or `live`?)
1317
+ * and lists the models it may meter against. `/api/v1/me`, `/api/v1/models`.
1318
+ */
1319
+ declare class Workspace {
1320
+ private readonly transport;
1321
+ constructor(transport: Transport);
1322
+ /** Identify the org + key behind the request, incl. `sandbox` | `live`. */
1323
+ me(): Promise<WorkspaceIdentity>;
1324
+ /** The org's enabled models with live prices. `{ active: true }` returns only
1325
+ * the models that can be metered right now. */
1326
+ models(params?: {
1327
+ active?: boolean;
1328
+ }): Promise<Model[]>;
1329
+ }
1330
+
1196
1331
  /**
1197
1332
  * The ClockNext client.
1198
1333
  *
@@ -1233,6 +1368,8 @@ declare class ClockNext {
1233
1368
  readonly webhooks: Webhooks;
1234
1369
  /** Mint customer-portal embed tokens. */
1235
1370
  readonly portal: Portal;
1371
+ /** Identify the workspace (sandbox/live) + list its models. `/me`, `/models`. */
1372
+ readonly workspace: Workspace;
1236
1373
  private readonly cfg;
1237
1374
  private readonly flusher;
1238
1375
  constructor(config: ClockNextConfig);
@@ -1293,4 +1430,4 @@ declare class NetworkError extends ClockNextError {
1293
1430
  constructor(message: string);
1294
1431
  }
1295
1432
 
1296
- export { type AddMemberInput, AllowanceError, type ApiCustomer, AuthError, type BillingCycle, type BillingMode, ClockNext, type ClockNextConfig, ClockNextError, type ComponentType, ConflictError, type CreateCreditInput, type CreateCustomerInput, type CreateOutcomeInput, type CreatePlanInput, type CreatePurchaseInput, type CreateUnitInput, type Credit, type CreditAdjustInput, type CreditDetail, type CreditInput, type CreditSignal, type CustomerBalances, type CustomerList, type CustomerPlan, type CustomerProfileInput, type CustomerRevenue, type DropReason, type FetchLike, type Invoice, type InvoiceDetail, type InvoiceLineItem, type InvoiceListRow, type InvoiceParty, type InvoicePlanSnapshot, type InvoiceStatus, type Logger, type Member, type MemberRole, type ModelBundleEntry, NetworkError, NotFoundError, type Outcome, type OutcomeAdjustInput, type OutcomeDetail, type OutcomeInput, type OutcomeSignal, type OutcomeStepInput, type PayLink, type PaymentDetail, type PaymentRow, type Plan, type PlanComponent, type PlanComponentInput, type PlanDetail, PlanError, type PlanKind, type PlanRef, type PlanType, type PortalToken, type PortalTokenInput, type Purchase, type PurchaseDetail, type PurchaseStatus, RateLimitError, type RevenueRange, type SerializedOutcomeAttribution, type SerializedRuleApplication, type SerializedUsageLog, ServerError, type Signal, type SignalStatus, type SignalType, type ThresholdKind, type Tokens, type TrackResult, type Unit, type UnitAdjustInput, type UnitDetail, type UnitInput, type UnitPricingType, type UnitTier, type UnitTierInput, type UnitUsageList, type UnitUsageRow, type UpdateCreditInput, type UpdateMemberInput, type UpdateOutcomeInput, type UpdatePlanInput, type UpdateUnitInput, type UpsertWebhookInput, type UsageList, ValidationError, type WalletEntryInput, type WalletInput, type WalletList, type WalletSignal, type WalletTransaction, type WalletTransactionType, type Webhook, signalToWire };
1433
+ export { type AddMemberInput, AllowanceError, type ApiCustomer, AuthError, type BillingCycle, type BillingMode, ClockNext, type ClockNextConfig, ClockNextError, type ComponentType, ConflictError, type CreateCreditInput, type CreateCustomerInput, type CreateOutcomeInput, type CreatePlanInput, type CreatePurchaseInput, type CreateUnitInput, type Credit, type CreditAdjustInput, type CreditComponentInput, type CreditDetail, type CreditInput, type CreditSignal, type CustomerBalances, type CustomerList, type CustomerPlan, type CustomerProfileInput, type CustomerRevenue, type DropReason, type FetchLike, type FlatComponentInput, type FlatUnitInput, type Invoice, type InvoiceDetail, type InvoiceLineItem, type InvoiceListRow, type InvoiceParty, type InvoicePlanSnapshot, type InvoiceStatus, type Logger, type Member, type MemberRole, type Model, type ModelBundleEntry, NetworkError, NotFoundError, type Outcome, type OutcomeAdjustInput, type OutcomeComponentInput, type OutcomeDetail, type OutcomeInput, type OutcomeSignal, type OutcomeStepInput, type PayLink, type PaymentDetail, type PaymentRow, type Plan, type PlanComponent, type PlanComponentInput, type PlanDetail, PlanError, type PlanKind, type PlanRef, type PlanType, type PortalToken, type PortalTokenInput, type Purchase, type PurchaseDetail, type PurchaseStatus, RateLimitError, type RevenueRange, type SerializedOutcomeAttribution, type SerializedRuleApplication, type SerializedUsageLog, ServerError, type Signal, type SignalStatus, type SignalType, type ThresholdKind, type TieredUnitInput, type Tokens, type TrackResult, type Unit, type UnitAdjustInput, type UnitComponentInput, type UnitDetail, type UnitInput, type UnitPricingType, type UnitTier, type UnitTierInput, type UnitUsageList, type UnitUsageRow, type UpdateCreditInput, type UpdateMemberInput, type UpdateOutcomeInput, type UpdatePlanInput, type UpdateUnitInput, type UpsertWebhookInput, type UsageList, ValidationError, type WalletComponentInput, type WalletEntryInput, type WalletInput, type WalletList, type WalletSignal, type WalletTransaction, type WalletTransactionType, type Webhook, type WorkspaceIdentity, signalToWire };
package/dist/index.d.ts CHANGED
@@ -8,12 +8,44 @@
8
8
  */
9
9
  type SignalType = "wallet" | "credit" | "outcome";
10
10
  type SignalStatus = "SUCCESS" | "FAILURE" | "PENDING";
11
- /** Token counts for a signal. All default to 0. */
11
+ /**
12
+ * Token counts for a signal. `input` and `output` are required — every metered
13
+ * call has them, and the server requires them. `cache` (provider-specific
14
+ * prompt-cache reads) is optional and defaults to 0 server-side when omitted.
15
+ */
12
16
  interface Tokens {
13
- input?: number;
14
- output?: number;
17
+ input: number;
18
+ output: number;
15
19
  cache?: number;
16
20
  }
21
+ /** The organisation + key behind a request — `cnk.workspace.me()`. */
22
+ interface WorkspaceIdentity {
23
+ organization: {
24
+ id: string;
25
+ name: string;
26
+ slug: string | null;
27
+ /** `sandbox` is a disposable staging twin; `live` bills for real. Check
28
+ * this before sending production traffic. */
29
+ environment: "sandbox" | "live";
30
+ };
31
+ apiKey: {
32
+ prefix: string;
33
+ lastFour: string;
34
+ expiresAt: string | null;
35
+ } | null;
36
+ }
37
+ /** One model the org has enabled — `cnk.workspace.models()`. The `modelId` is
38
+ * what you put in a signal's `model`. Prices are USD per 1,000,000 tokens. */
39
+ interface Model {
40
+ modelId: string;
41
+ modelName: string;
42
+ provider: string;
43
+ providerName: string;
44
+ isActive: boolean;
45
+ inputPrice: number;
46
+ outputPrice: number;
47
+ cachePrice: number;
48
+ }
17
49
  interface SignalBase {
18
50
  /** The customer this usage belongs to (required). */
19
51
  customerId: string;
@@ -22,14 +54,21 @@ interface SignalBase {
22
54
  * (Settings → Models). Matched case-insensitively against `OrgModel.modelId`.
23
55
  */
24
56
  model: string;
25
- /** Token counts for this call. */
26
- tokens?: Tokens;
57
+ /** Token counts for this call — required; every metered signal is priced on
58
+ * tokens. (`cache` within is optional; `input`/`output` are not.) */
59
+ tokens: Tokens;
27
60
  /** Optional member (email) this usage is attributed to. */
28
61
  member?: string;
29
- /** Defaults to SUCCESS. */
30
- status?: SignalStatus;
31
62
  /** Free-form metadata. Credit rules can target `custom.<key>` paths. */
32
63
  custom?: Record<string, unknown>;
64
+ /**
65
+ * Idempotency key for safe retries. **Auto-generated (UUID v4) if omitted**
66
+ * and reused across every retry of this signal, so a retried send is
67
+ * deduplicated server-side instead of double-recording. Supply your own — a
68
+ * stable id for this logical event — to also dedup across process restarts or
69
+ * at-least-once redelivery, which an in-memory auto key can't survive.
70
+ */
71
+ idempotencyKey?: string;
33
72
  }
34
73
  /** Meters a credit, identified by the credit's stable `agentKey`. */
35
74
  interface CreditSignal extends SignalBase {
@@ -150,9 +189,10 @@ interface CustomerProfileInput {
150
189
  /** ISO 4217 (3 letters); must be enabled for the org. */
151
190
  currencyCode?: string;
152
191
  }
153
- /** `name` is required on create. */
192
+ /** `name` and `email` are required on create; every other field is optional. */
154
193
  type CreateCustomerInput = CustomerProfileInput & {
155
194
  name: string;
195
+ email: string;
156
196
  };
157
197
  interface CustomerList {
158
198
  customers: ApiCustomer[];
@@ -219,18 +259,68 @@ type PlanKind = "FLAT_PRICE" | "PAY_AS_YOU_GO" | "PAY_PER_SEAT";
219
259
  type ComponentType = "WALLET" | "CREDIT" | "OUTCOME" | "UNIT" | "FLAT";
220
260
  /** ADVANCE bills up-front for the cycle; ARREAR bills for what was consumed. */
221
261
  type BillingMode = "ADVANCE" | "ARREAR";
222
- /** One entitlement line in a plan. Set the id matching `type` (creditId for CREDIT, …). */
223
- interface PlanComponentInput {
224
- type: ComponentType;
262
+ /** Prepaid USD wallet. `amount` is the funded balance (required). Max one
263
+ * wallet component per plan. */
264
+ interface WalletComponentInput {
265
+ type: "WALLET";
225
266
  billingMode: BillingMode;
226
- creditId?: string | null;
227
- outcomeId?: string | null;
228
- unitId?: string | null;
229
- /** Granted quantity (ADVANCE components). */
230
- quantity?: number | null;
231
- /** Flat amount (FLAT / WALLET components). */
232
- amount?: number | null;
267
+ amount: number;
268
+ }
269
+ /** A one-off flat fee — `amount` is required. Max one flat component per plan;
270
+ * not allowed on FREE plans. */
271
+ interface FlatComponentInput {
272
+ type: "FLAT";
273
+ billingMode: BillingMode;
274
+ amount: number;
233
275
  }
276
+ /** A credit entitlement, referenced by `creditId`. Billed ADVANCE it needs a
277
+ * granted `quantity`; billed ARREAR it meters usage with no upfront grant. */
278
+ type CreditComponentInput = {
279
+ type: "CREDIT";
280
+ billingMode: "ADVANCE";
281
+ creditId: string;
282
+ quantity: number;
283
+ } | {
284
+ type: "CREDIT";
285
+ billingMode: "ARREAR";
286
+ creditId: string;
287
+ quantity?: number | null;
288
+ };
289
+ /** An outcome entitlement, referenced by `outcomeId`. ADVANCE needs a granted
290
+ * `quantity`; ARREAR meters usage. */
291
+ type OutcomeComponentInput = {
292
+ type: "OUTCOME";
293
+ billingMode: "ADVANCE";
294
+ outcomeId: string;
295
+ quantity: number;
296
+ } | {
297
+ type: "OUTCOME";
298
+ billingMode: "ARREAR";
299
+ outcomeId: string;
300
+ quantity?: number | null;
301
+ };
302
+ /** A unit entitlement, referenced by `unitId`. ADVANCE needs a granted
303
+ * `quantity`; ARREAR meters usage. */
304
+ type UnitComponentInput = {
305
+ type: "UNIT";
306
+ billingMode: "ADVANCE";
307
+ unitId: string;
308
+ quantity: number;
309
+ } | {
310
+ type: "UNIT";
311
+ billingMode: "ARREAR";
312
+ unitId: string;
313
+ quantity?: number | null;
314
+ };
315
+ /**
316
+ * One entitlement line in a plan — a discriminated union on `type` (and, where
317
+ * it matters, `billingMode`) so the per-type fields the server requires are
318
+ * enforced at compile time instead of surfacing as runtime 422s:
319
+ * - CREDIT / OUTCOME / UNIT require their matching id;
320
+ * - CREDIT / OUTCOME / UNIT require `quantity` when billed ADVANCE;
321
+ * - WALLET / FLAT require `amount`.
322
+ */
323
+ type PlanComponentInput = WalletComponentInput | FlatComponentInput | CreditComponentInput | OutcomeComponentInput | UnitComponentInput;
234
324
  interface CreatePlanInput {
235
325
  name: string;
236
326
  description?: string | null;
@@ -543,7 +633,8 @@ interface UnitAdjustInput {
543
633
  /** A per-model token bundle attached to a credit or outcome step. */
544
634
  interface ModelBundleEntry {
545
635
  orgModelId: string;
546
- modelName: string;
636
+ /** Display label; the server defaults it from the model when omitted. */
637
+ modelName?: string;
547
638
  tokens: number;
548
639
  input: number;
549
640
  output: number;
@@ -671,25 +762,50 @@ interface UnitDetail extends Unit {
671
762
  /** First page (≤10) of customers currently metered on this unit. */
672
763
  customers: Record<string, unknown>[];
673
764
  }
674
- interface CreateUnitInput {
765
+ /** Flat per-event pricing — a single `flatPrice` (defaults to 0), no tiers. */
766
+ interface FlatUnitInput {
675
767
  name: string;
676
- pricingType: UnitPricingType;
677
- /** Required for FLAT pricing. */
768
+ /** Stable per-org report key (`signals.unit({ agentKey })`); `[a-z0-9._-]`. */
769
+ agentKey: string;
770
+ pricingType: "FLAT";
771
+ /** Price per event; defaults to 0. */
678
772
  flatPrice?: number;
679
- /** Required for SLAB/VOLUME pricing (≤50 tiers). */
680
- tiers?: UnitTierInput[];
681
773
  description?: string | null;
682
774
  isActive?: boolean;
683
775
  }
776
+ /** Tiered pricing (SLAB or VOLUME) — at least one tier is required. */
777
+ interface TieredUnitInput {
778
+ name: string;
779
+ /** Stable per-org report key (`signals.unit({ agentKey })`); `[a-z0-9._-]`. */
780
+ agentKey: string;
781
+ pricingType: "SLAB" | "VOLUME";
782
+ /** At least one tier (≤50). Only the last tier may have `upTo: null`. */
783
+ tiers: UnitTierInput[];
784
+ description?: string | null;
785
+ isActive?: boolean;
786
+ }
787
+ /**
788
+ * Create a unit type — a discriminated union on `pricingType`: `FLAT` takes an
789
+ * optional `flatPrice` (defaults to 0); `SLAB`/`VOLUME` require `tiers`, so the
790
+ * server's "add at least one tier" rule is enforced at compile time.
791
+ */
792
+ type CreateUnitInput = FlatUnitInput | TieredUnitInput;
684
793
  type UpdateUnitInput = CreateUnitInput;
685
- /** Record one unit-metered event. `unit` matches a catalog unit name (case-insensitive). */
794
+ /**
795
+ * Record one unit-metered event. The unit is addressed by its `agentKey` (the
796
+ * stable key set when the unit was created) — the ONLY accepted identifier;
797
+ * the display name is deliberately not accepted, so a rename can never redirect
798
+ * a live integration. Keys are matched exactly (they are stored lowercased).
799
+ */
686
800
  interface UnitInput {
687
801
  customerId: string;
688
- unit: string;
802
+ agentKey: string;
689
803
  member?: string;
690
804
  }
691
805
  interface UnitUsageRow {
692
806
  unit: string;
807
+ /** The unit's stable agent key — what to send to report against it. */
808
+ agentKey: string | null;
693
809
  billingMode: BillingMode;
694
810
  granted?: number;
695
811
  used: number;
@@ -918,10 +1034,6 @@ declare class Customers {
918
1034
  transaction: WalletTransaction;
919
1035
  balanceUsd: number;
920
1036
  }>;
921
- /** Set the customer's currency. `PUT …/:id/currency`. */
922
- setCurrency(id: string, currencyCode: string): Promise<void>;
923
- /** Set which credit types the customer is billed against. `PUT …/:id/credits`. */
924
- setCreditTypes(id: string, creditIds: string[]): Promise<void>;
925
1037
  /** Grant or claw back a credit balance. `POST …/:id/credits/adjust`. */
926
1038
  adjustCredit(id: string, input: CreditAdjustInput): Promise<void>;
927
1039
  /** Grant or claw back an outcome balance. Returns the remaining balance. */
@@ -1122,6 +1234,12 @@ declare class Signals {
1122
1234
  track(signal: Signal, opts?: {
1123
1235
  wait?: boolean;
1124
1236
  }): Promise<TrackResult>;
1237
+ /**
1238
+ * Validate + price a signal WITHOUT recording it (server `dryRun`). Returns
1239
+ * the projected usage log so an integration can preflight before sending real
1240
+ * traffic — no inbox row, wallet / outcome writes, or webhooks fire.
1241
+ */
1242
+ verify(signal: Signal): Promise<SerializedUsageLog | null>;
1125
1243
  /** Meter a named credit. */
1126
1244
  credit(input: CreditInput, opts?: {
1127
1245
  wait?: boolean;
@@ -1140,9 +1258,9 @@ declare class Signals {
1140
1258
  limit?: number;
1141
1259
  }): Promise<UsageList>;
1142
1260
  /**
1143
- * Record one unit-metered event (a fixed-price meter with no tokens), matched
1144
- * to a catalog unit by name. Sent immediately — unit events are not buffered.
1145
- * `POST /api/v1/units`.
1261
+ * Record one unit-metered event (a fixed-price meter with no tokens),
1262
+ * addressed to a catalog unit by its `agentKey`. Sent immediately — unit
1263
+ * events are not buffered. `POST /api/v1/units`.
1146
1264
  */
1147
1265
  unit(input: UnitInput): Promise<{
1148
1266
  unitUsage: Record<string, unknown>;
@@ -1193,6 +1311,23 @@ declare class Webhooks {
1193
1311
  delete(kind: ThresholdKind): Promise<void>;
1194
1312
  }
1195
1313
 
1314
+ /**
1315
+ * The `workspace` resource — read-only introspection of the org behind the API
1316
+ * key. Grounds an integration (which workspace, and is it `sandbox` or `live`?)
1317
+ * and lists the models it may meter against. `/api/v1/me`, `/api/v1/models`.
1318
+ */
1319
+ declare class Workspace {
1320
+ private readonly transport;
1321
+ constructor(transport: Transport);
1322
+ /** Identify the org + key behind the request, incl. `sandbox` | `live`. */
1323
+ me(): Promise<WorkspaceIdentity>;
1324
+ /** The org's enabled models with live prices. `{ active: true }` returns only
1325
+ * the models that can be metered right now. */
1326
+ models(params?: {
1327
+ active?: boolean;
1328
+ }): Promise<Model[]>;
1329
+ }
1330
+
1196
1331
  /**
1197
1332
  * The ClockNext client.
1198
1333
  *
@@ -1233,6 +1368,8 @@ declare class ClockNext {
1233
1368
  readonly webhooks: Webhooks;
1234
1369
  /** Mint customer-portal embed tokens. */
1235
1370
  readonly portal: Portal;
1371
+ /** Identify the workspace (sandbox/live) + list its models. `/me`, `/models`. */
1372
+ readonly workspace: Workspace;
1236
1373
  private readonly cfg;
1237
1374
  private readonly flusher;
1238
1375
  constructor(config: ClockNextConfig);
@@ -1293,4 +1430,4 @@ declare class NetworkError extends ClockNextError {
1293
1430
  constructor(message: string);
1294
1431
  }
1295
1432
 
1296
- export { type AddMemberInput, AllowanceError, type ApiCustomer, AuthError, type BillingCycle, type BillingMode, ClockNext, type ClockNextConfig, ClockNextError, type ComponentType, ConflictError, type CreateCreditInput, type CreateCustomerInput, type CreateOutcomeInput, type CreatePlanInput, type CreatePurchaseInput, type CreateUnitInput, type Credit, type CreditAdjustInput, type CreditDetail, type CreditInput, type CreditSignal, type CustomerBalances, type CustomerList, type CustomerPlan, type CustomerProfileInput, type CustomerRevenue, type DropReason, type FetchLike, type Invoice, type InvoiceDetail, type InvoiceLineItem, type InvoiceListRow, type InvoiceParty, type InvoicePlanSnapshot, type InvoiceStatus, type Logger, type Member, type MemberRole, type ModelBundleEntry, NetworkError, NotFoundError, type Outcome, type OutcomeAdjustInput, type OutcomeDetail, type OutcomeInput, type OutcomeSignal, type OutcomeStepInput, type PayLink, type PaymentDetail, type PaymentRow, type Plan, type PlanComponent, type PlanComponentInput, type PlanDetail, PlanError, type PlanKind, type PlanRef, type PlanType, type PortalToken, type PortalTokenInput, type Purchase, type PurchaseDetail, type PurchaseStatus, RateLimitError, type RevenueRange, type SerializedOutcomeAttribution, type SerializedRuleApplication, type SerializedUsageLog, ServerError, type Signal, type SignalStatus, type SignalType, type ThresholdKind, type Tokens, type TrackResult, type Unit, type UnitAdjustInput, type UnitDetail, type UnitInput, type UnitPricingType, type UnitTier, type UnitTierInput, type UnitUsageList, type UnitUsageRow, type UpdateCreditInput, type UpdateMemberInput, type UpdateOutcomeInput, type UpdatePlanInput, type UpdateUnitInput, type UpsertWebhookInput, type UsageList, ValidationError, type WalletEntryInput, type WalletInput, type WalletList, type WalletSignal, type WalletTransaction, type WalletTransactionType, type Webhook, signalToWire };
1433
+ export { type AddMemberInput, AllowanceError, type ApiCustomer, AuthError, type BillingCycle, type BillingMode, ClockNext, type ClockNextConfig, ClockNextError, type ComponentType, ConflictError, type CreateCreditInput, type CreateCustomerInput, type CreateOutcomeInput, type CreatePlanInput, type CreatePurchaseInput, type CreateUnitInput, type Credit, type CreditAdjustInput, type CreditComponentInput, type CreditDetail, type CreditInput, type CreditSignal, type CustomerBalances, type CustomerList, type CustomerPlan, type CustomerProfileInput, type CustomerRevenue, type DropReason, type FetchLike, type FlatComponentInput, type FlatUnitInput, type Invoice, type InvoiceDetail, type InvoiceLineItem, type InvoiceListRow, type InvoiceParty, type InvoicePlanSnapshot, type InvoiceStatus, type Logger, type Member, type MemberRole, type Model, type ModelBundleEntry, NetworkError, NotFoundError, type Outcome, type OutcomeAdjustInput, type OutcomeComponentInput, type OutcomeDetail, type OutcomeInput, type OutcomeSignal, type OutcomeStepInput, type PayLink, type PaymentDetail, type PaymentRow, type Plan, type PlanComponent, type PlanComponentInput, type PlanDetail, PlanError, type PlanKind, type PlanRef, type PlanType, type PortalToken, type PortalTokenInput, type Purchase, type PurchaseDetail, type PurchaseStatus, RateLimitError, type RevenueRange, type SerializedOutcomeAttribution, type SerializedRuleApplication, type SerializedUsageLog, ServerError, type Signal, type SignalStatus, type SignalType, type ThresholdKind, type TieredUnitInput, type Tokens, type TrackResult, type Unit, type UnitAdjustInput, type UnitComponentInput, type UnitDetail, type UnitInput, type UnitPricingType, type UnitTier, type UnitTierInput, type UnitUsageList, type UnitUsageRow, type UpdateCreditInput, type UpdateMemberInput, type UpdateOutcomeInput, type UpdatePlanInput, type UpdateUnitInput, type UpsertWebhookInput, type UsageList, ValidationError, type WalletComponentInput, type WalletEntryInput, type WalletInput, type WalletList, type WalletSignal, type WalletTransaction, type WalletTransactionType, type Webhook, type WorkspaceIdentity, signalToWire };