@clocknext/sdk 0.1.0 → 0.3.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
@@ -30,27 +30,22 @@ interface SignalBase {
30
30
  status?: SignalStatus;
31
31
  /** Free-form metadata. Credit rules can target `custom.<key>` paths. */
32
32
  custom?: Record<string, unknown>;
33
- /**
34
- * Stable, unique id for this logical event. Generated automatically if
35
- * omitted. Pass a deterministic value to dedupe across process restarts.
36
- */
37
- idempotencyKey?: string;
38
33
  }
39
- /** Meters a credit, identified by the credit's stable `key`. */
34
+ /** Meters a credit, identified by the credit's stable `agentKey`. */
40
35
  interface CreditSignal extends SignalBase {
41
36
  type: "credit";
42
- /** The Credit's stable key (assigned when the credit was created). */
43
- key: string;
37
+ /** The Credit's stable agent key (assigned when the credit was created). */
38
+ agentKey: string;
44
39
  }
45
40
  /** Debits the customer's wallet in USD at the model's cost. */
46
41
  interface WalletSignal extends SignalBase {
47
42
  type: "wallet";
48
43
  }
49
- /** Advances one step of a multi-call outcome workflow, by the step's `key`. */
44
+ /** Advances one step of a multi-call outcome workflow, by the step's `agentKey`. */
50
45
  interface OutcomeSignal extends SignalBase {
51
46
  type: "outcome";
52
- /** The OutcomeStep's stable key — identifies the outcome AND the step. */
53
- key: string;
47
+ /** The OutcomeStep's stable agent key — identifies the outcome AND the step. */
48
+ agentKey: string;
54
49
  }
55
50
  type Signal = CreditSignal | WalletSignal | OutcomeSignal;
56
51
  /** Helper input shapes for the per-type convenience methods. */
@@ -91,8 +86,6 @@ interface SerializedUsageLog {
91
86
  }
92
87
  /** Result of a single signal send (sync mode, or `{ wait: true }`). */
93
88
  interface TrackResult {
94
- /** The idempotency key the event was sent with. */
95
- idempotencyKey: string;
96
89
  /** True when the signal was buffered (async mode) and not yet sent. */
97
90
  queued: boolean;
98
91
  /** The computed usage log — present only once the signal has been sent. */
@@ -218,6 +211,513 @@ interface PortalToken {
218
211
  /** Seconds until expiry. */
219
212
  expiresIn: number;
220
213
  }
214
+ /** How often a plan bills. `FREE` is a one-time grant; `EVERY_5_MIN` is a test cadence. */
215
+ type BillingCycle = "MONTHLY" | "QUARTERLY" | "SEMI_ANNUAL" | "YEARLY" | "EVERY_5_MIN" | "FREE";
216
+ type PlanType = "WALLET" | "BUNDLE";
217
+ type PlanKind = "FLAT_PRICE" | "PAY_AS_YOU_GO" | "PAY_PER_SEAT";
218
+ /** A plan component's meter type. */
219
+ type ComponentType = "WALLET" | "CREDIT" | "OUTCOME" | "UNIT" | "FLAT";
220
+ /** ADVANCE bills up-front for the cycle; ARREAR bills for what was consumed. */
221
+ 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;
225
+ 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;
233
+ }
234
+ interface CreatePlanInput {
235
+ name: string;
236
+ description?: string | null;
237
+ billingCycle: BillingCycle;
238
+ /** Carry an unused balance into the next cycle. Default true. */
239
+ carryForward?: boolean;
240
+ /** ISO 4217 (3 letters). Default "USD". */
241
+ currencyCode?: string;
242
+ isActive?: boolean;
243
+ /** At least one component. FREE plans must be ADVANCE-only with no FLAT component. */
244
+ components: PlanComponentInput[];
245
+ }
246
+ /** A full-rewrite update carries the complete plan (same shape as create). */
247
+ type UpdatePlanInput = CreatePlanInput;
248
+ interface PlanComponent {
249
+ id: string;
250
+ type: ComponentType;
251
+ billingMode: BillingMode;
252
+ creditId: string | null;
253
+ outcomeId: string | null;
254
+ unitId: string | null;
255
+ targetName: string | null;
256
+ quantity: number | null;
257
+ amount: number | null;
258
+ }
259
+ interface Plan {
260
+ id: string;
261
+ name: string;
262
+ description: string | null;
263
+ type: PlanType;
264
+ kind: PlanKind;
265
+ billingCycle: BillingCycle;
266
+ cost: number;
267
+ currencyCode: string;
268
+ isActive: boolean;
269
+ components: PlanComponent[];
270
+ }
271
+ /** The richer plan returned by `plans.get()` (adds aggregate stats). */
272
+ interface PlanDetail extends Plan {
273
+ createdAt: string;
274
+ createdByName: string | null;
275
+ customerCount: number;
276
+ invoiceCount: number;
277
+ stats: {
278
+ totalInvoiced: number;
279
+ totalCollected: number;
280
+ openBalance: number;
281
+ };
282
+ }
283
+ type PurchaseStatus = "SCHEDULED" | "ACTIVE" | "CANCELLED";
284
+ interface CreatePurchaseInput {
285
+ customerId: string;
286
+ planId: string;
287
+ /** `YYYY-MM-DD`. Defaults to today; must be a valid non-past date. */
288
+ billingDate?: string;
289
+ notes?: string;
290
+ autoPayment?: boolean;
291
+ /** Auto-void the purchase if unpaid after N minutes. */
292
+ voidAfterMinutes?: number;
293
+ }
294
+ interface Purchase {
295
+ id: string;
296
+ purchaseNumber: string;
297
+ customerId: string;
298
+ customerName: string;
299
+ planId: string | null;
300
+ planName: string;
301
+ planType: PlanType;
302
+ hasWallet: boolean;
303
+ hasCredit: boolean;
304
+ hasOutcome: boolean;
305
+ hasUnit: boolean;
306
+ billingCycle: BillingCycle;
307
+ cost: number;
308
+ currencyCode: string;
309
+ billingDate: string;
310
+ status: PurchaseStatus;
311
+ autoPayment: boolean;
312
+ autoPaymentPauseReason: string | null;
313
+ createdAt: string;
314
+ }
315
+ /** The purchase returned by `purchases.get()` — a different, detail-oriented shape. */
316
+ interface PurchaseDetail {
317
+ id: string;
318
+ purchaseNumber: string;
319
+ status: PurchaseStatus;
320
+ cost: number;
321
+ billingCycle: BillingCycle;
322
+ planName: string;
323
+ billingDate: string;
324
+ nextBillingDate: string;
325
+ createdAt: string;
326
+ createdByName: string;
327
+ customer: {
328
+ id: string;
329
+ name: string;
330
+ };
331
+ autoPayment: boolean;
332
+ autoPaymentPauseReason: string | null;
333
+ autoPaymentPausedAt: string | null;
334
+ plan: {
335
+ id: string;
336
+ } | null;
337
+ stats: {
338
+ invoiceCount: number;
339
+ paidCount: number;
340
+ };
341
+ }
342
+ type InvoiceStatus = "OPEN" | "PAID" | "VOID";
343
+ /** Trimmed row from `invoices.list()`. */
344
+ interface InvoiceListRow {
345
+ id: string;
346
+ invoiceNumber: string;
347
+ purchaseNumber: string | null;
348
+ purchaseId: string | null;
349
+ customerId: string;
350
+ customerName: string;
351
+ planName: string;
352
+ billingCycle: BillingCycle;
353
+ cycleIndex: number;
354
+ amount: number;
355
+ currencyCode: string;
356
+ status: InvoiceStatus;
357
+ issuedAt: string;
358
+ paidAt: string | null;
359
+ }
360
+ /** A billing party (your org, or the customer) on an invoice. */
361
+ interface InvoiceParty {
362
+ name: string;
363
+ logoUrl: string | null;
364
+ legalName: string | null;
365
+ email: string | null;
366
+ phone: string | null;
367
+ website: string | null;
368
+ taxId: string | null;
369
+ addressLine1: string | null;
370
+ city: string | null;
371
+ state: string | null;
372
+ country: string | null;
373
+ pincode: string | null;
374
+ }
375
+ interface InvoiceLineItem {
376
+ kind: "credit" | "outcome";
377
+ label: string;
378
+ quantity: number;
379
+ }
380
+ /** The plan snapshot embedded in a full invoice. */
381
+ interface InvoicePlanSnapshot {
382
+ name: string;
383
+ type: PlanType;
384
+ hasWallet: boolean;
385
+ hasCredit: boolean;
386
+ hasOutcome: boolean;
387
+ hasUnit: boolean;
388
+ kind: PlanKind;
389
+ billingCycle: BillingCycle;
390
+ cost: number;
391
+ currencyCode: string;
392
+ spendingLimit: number | null;
393
+ seatScope: "CUSTOMER" | "MEMBER" | null;
394
+ carryForward: boolean;
395
+ billingDate: string;
396
+ status: "SCHEDULED" | "ACTIVE";
397
+ }
398
+ /** The full invoice from `invoices.get()` (also the `payment` in `payments.get()`). */
399
+ interface Invoice {
400
+ id: string;
401
+ invoiceNumber: string;
402
+ paymentNumber: string | null;
403
+ purchaseNumber: string | null;
404
+ customerId: string;
405
+ customerName: string;
406
+ customerSlug: string;
407
+ customerParty: InvoiceParty;
408
+ orgParty: InvoiceParty;
409
+ purchaseId: string | null;
410
+ stream: BillingMode;
411
+ planId: string | null;
412
+ planName: string;
413
+ planType: PlanType;
414
+ plan: InvoicePlanSnapshot | null;
415
+ billingCycle: BillingCycle;
416
+ cycleIndex: number;
417
+ lineItems: InvoiceLineItem[];
418
+ hasWallet: boolean;
419
+ hasCredit: boolean;
420
+ hasOutcome: boolean;
421
+ hasUnit: boolean;
422
+ amount: number;
423
+ currencyCode: string;
424
+ currencyRateUsd: number;
425
+ status: InvoiceStatus;
426
+ issuedAt: string;
427
+ paidAt: string | null;
428
+ voidedAt: string | null;
429
+ /** One of the server `PaymentMode` values (e.g. "CASH", "STRIPE", …). */
430
+ paymentMode: string | null;
431
+ paymentReference: string | null;
432
+ stripePaymentIntentId: string | null;
433
+ autoPaid: boolean;
434
+ notes: string | null;
435
+ createdAt: string;
436
+ createdByName: string;
437
+ paidByName: string | null;
438
+ voidedByName: string | null;
439
+ }
440
+ /** A short `{ id, name }` plan reference alongside a full invoice/payment. */
441
+ interface PlanRef {
442
+ id: string;
443
+ name: string;
444
+ }
445
+ interface InvoiceDetail {
446
+ invoice: Invoice;
447
+ plan: PlanRef | null;
448
+ }
449
+ /** A hosted pay link for an OPEN invoice. */
450
+ interface PayLink {
451
+ url: string;
452
+ invoiceId: string;
453
+ invoiceNumber: string;
454
+ }
455
+ /** Trimmed row from `payments.list()` (a payment is a PAID invoice). */
456
+ interface PaymentRow {
457
+ id: string;
458
+ paymentNumber: string;
459
+ invoiceNumber: string;
460
+ purchaseNumber: string | null;
461
+ customerId: string;
462
+ customerName: string;
463
+ planName: string;
464
+ amount: number;
465
+ currencyCode: string;
466
+ paymentMode: string | null;
467
+ paymentReference: string | null;
468
+ paidAt: string;
469
+ paidByName: string | null;
470
+ }
471
+ interface PaymentDetail {
472
+ payment: Invoice;
473
+ plan: PlanRef | null;
474
+ }
475
+ type MemberRole = "OWNER" | "ADMIN" | "MEMBER";
476
+ interface Member {
477
+ id: string;
478
+ role: MemberRole;
479
+ name: string;
480
+ email: string | null;
481
+ employeeId: string | null;
482
+ phone: string | null;
483
+ /** True once the member has linked a login. */
484
+ isLinked: boolean;
485
+ joinedAt: string;
486
+ }
487
+ interface AddMemberInput {
488
+ name: string;
489
+ role: "ADMIN" | "MEMBER";
490
+ email?: string;
491
+ employeeId?: string;
492
+ phone?: string;
493
+ }
494
+ /** Role is fixed after creation; omit it here. */
495
+ interface UpdateMemberInput {
496
+ name: string;
497
+ email?: string;
498
+ employeeId?: string;
499
+ phone?: string;
500
+ }
501
+ type WalletTransactionType = "CREDIT" | "DEBIT";
502
+ interface WalletTransaction {
503
+ id: string;
504
+ type: WalletTransactionType;
505
+ amount: number;
506
+ amountUsd: number;
507
+ currencyCode: string;
508
+ currencyRateUsd: number;
509
+ notes: string | null;
510
+ batchId: string | null;
511
+ createdAt: string;
512
+ createdByName: string | null;
513
+ }
514
+ interface WalletList {
515
+ balanceUsd: number;
516
+ transactions: WalletTransaction[];
517
+ }
518
+ interface WalletEntryInput {
519
+ /** DEBIT spends, CREDIT tops up. */
520
+ type: WalletTransactionType;
521
+ /** Always positive; the sign comes from `type`. */
522
+ amount: number;
523
+ notes?: string;
524
+ }
525
+ /** Grant (positive) or claw back (negative) a credit balance. `delta` must be a non-zero whole number. */
526
+ interface CreditAdjustInput {
527
+ creditId: string;
528
+ delta: number;
529
+ notes?: string;
530
+ }
531
+ /** Grant/claw an outcome balance. `delta` is a non-zero whole number; floored at 0. */
532
+ interface OutcomeAdjustInput {
533
+ outcomeId: string;
534
+ delta: number;
535
+ notes?: string;
536
+ }
537
+ /** Grant/claw a unit balance. `delta` is non-zero (fractional allowed); floored at 0. */
538
+ interface UnitAdjustInput {
539
+ unitId: string;
540
+ delta: number;
541
+ notes?: string;
542
+ }
543
+ /** A per-model token bundle attached to a credit or outcome step. */
544
+ interface ModelBundleEntry {
545
+ orgModelId: string;
546
+ modelName: string;
547
+ tokens: number;
548
+ input: number;
549
+ output: number;
550
+ cache: number;
551
+ }
552
+ interface Credit {
553
+ id: string;
554
+ name: string;
555
+ agentKey: string;
556
+ description: string | null;
557
+ tokensPerCredit: number;
558
+ basePrice: number;
559
+ marginPercent: number;
560
+ pricePerCredit: number;
561
+ isActive: boolean;
562
+ createdAt: string;
563
+ }
564
+ /** `credits.get()` — adds the model bundle plus usage stats/analytics. */
565
+ interface CreditDetail extends Credit {
566
+ modelBundle: ModelBundleEntry[];
567
+ createdByName: string;
568
+ stats: {
569
+ customerCount: number;
570
+ planCount: number;
571
+ totalGranted: number;
572
+ totalUsed: number;
573
+ revenue: number;
574
+ usageLogCount: number;
575
+ };
576
+ /** Cost-over-time analytics; shape is server-defined. */
577
+ analytics: Record<string, unknown>;
578
+ }
579
+ interface CreateCreditInput {
580
+ name: string;
581
+ /** Lowercased stable key used by `signals.credit({ agentKey })`. */
582
+ agentKey: string;
583
+ basePrice: number;
584
+ marginPercent: number;
585
+ pricePerCredit: number;
586
+ description?: string;
587
+ tokensPerCredit?: number;
588
+ modelBundle?: ModelBundleEntry[];
589
+ }
590
+ type UpdateCreditInput = CreateCreditInput;
591
+ interface OutcomeStepInput {
592
+ id?: string;
593
+ name: string;
594
+ /** Lowercased stable key used by `signals.outcome({ agentKey })`. */
595
+ agentKey: string;
596
+ basePrice: number;
597
+ modelBundle?: ModelBundleEntry[];
598
+ }
599
+ interface Outcome {
600
+ id: string;
601
+ name: string;
602
+ description: string | null;
603
+ isActive: boolean;
604
+ marginPercent: number;
605
+ pricePerOutcome: number;
606
+ createdAt: string;
607
+ steps?: {
608
+ name: string;
609
+ agentKey: string;
610
+ }[];
611
+ }
612
+ /** `outcomes.get()` — adds steps plus in-flight/completed stats. */
613
+ interface OutcomeDetail extends Outcome {
614
+ createdByName: string | null;
615
+ steps: {
616
+ name: string;
617
+ agentKey: string;
618
+ }[];
619
+ stats: {
620
+ stepCount: number;
621
+ customerCount: number;
622
+ inFlight: number;
623
+ completed: number;
624
+ totalRemaining: number;
625
+ };
626
+ analytics: Record<string, unknown>;
627
+ }
628
+ interface CreateOutcomeInput {
629
+ name: string;
630
+ basePrice: number;
631
+ marginPercent: number;
632
+ pricePerOutcome: number;
633
+ description?: string | null;
634
+ isActive?: boolean;
635
+ /** 1–50 steps; step names and agent keys must be unique. */
636
+ steps: OutcomeStepInput[];
637
+ }
638
+ type UpdateOutcomeInput = CreateOutcomeInput;
639
+ type UnitPricingType = "FLAT" | "SLAB" | "VOLUME";
640
+ /** A tier for SLAB/VOLUME pricing; only the last tier may have `upTo: null`. */
641
+ interface UnitTierInput {
642
+ id?: string;
643
+ upTo: number | null;
644
+ price: number;
645
+ }
646
+ interface UnitTier {
647
+ id: string;
648
+ upTo: number | null;
649
+ price: number;
650
+ order: number;
651
+ }
652
+ interface Unit {
653
+ id: string;
654
+ name: string;
655
+ description: string | null;
656
+ pricingType: UnitPricingType;
657
+ flatPrice: number;
658
+ tiers: UnitTier[];
659
+ isActive: boolean;
660
+ createdAt: string;
661
+ }
662
+ /** `units.get()` — adds linked-customer sample plus stats. */
663
+ interface UnitDetail extends Unit {
664
+ createdByName: string | null;
665
+ stats: {
666
+ planCount: number;
667
+ customerCount: number;
668
+ totalRemaining: number;
669
+ totalUsed: number;
670
+ };
671
+ /** First page (≤10) of customers currently metered on this unit. */
672
+ customers: Record<string, unknown>[];
673
+ }
674
+ interface CreateUnitInput {
675
+ name: string;
676
+ pricingType: UnitPricingType;
677
+ /** Required for FLAT pricing. */
678
+ flatPrice?: number;
679
+ /** Required for SLAB/VOLUME pricing (≤50 tiers). */
680
+ tiers?: UnitTierInput[];
681
+ description?: string | null;
682
+ isActive?: boolean;
683
+ }
684
+ type UpdateUnitInput = CreateUnitInput;
685
+ /** Record one unit-metered event. `unit` matches a catalog unit name (case-insensitive). */
686
+ interface UnitInput {
687
+ customerId: string;
688
+ unit: string;
689
+ member?: string;
690
+ }
691
+ interface UnitUsageRow {
692
+ unit: string;
693
+ billingMode: BillingMode;
694
+ granted?: number;
695
+ used: number;
696
+ remaining?: number;
697
+ }
698
+ interface UnitUsageList {
699
+ customer: {
700
+ id: string;
701
+ name: string;
702
+ };
703
+ units: UnitUsageRow[];
704
+ events: unknown[];
705
+ }
706
+ type ThresholdKind = "CREDIT" | "OUTCOME" | "WALLET";
707
+ interface Webhook {
708
+ kind: ThresholdKind;
709
+ threshold: number;
710
+ url: string;
711
+ isActive: boolean;
712
+ }
713
+ interface UpsertWebhookInput {
714
+ kind: ThresholdKind;
715
+ /** Fire when the balance crosses this value. */
716
+ threshold: number;
717
+ /** http(s) URL to POST the alert to. */
718
+ url: string;
719
+ isActive?: boolean;
720
+ }
221
721
  type FetchLike = (input: string, init?: RequestInit) => Promise<Response>;
222
722
  interface Logger {
223
723
  debug?: (...args: unknown[]) => void;
@@ -228,7 +728,7 @@ type DropReason = "queue_full" | "send_failed";
228
728
  interface ClockNextConfig {
229
729
  /** The org API key (`cnk_…`). Required. */
230
730
  apiKey: string;
231
- /** API base URL. Defaults to https://app.clocknext.com */
731
+ /** API base URL. Defaults to https://payments.clocknext.com */
232
732
  baseUrl?: string;
233
733
  /**
234
734
  * "async" (default) buffers signals and flushes in the background.
@@ -303,20 +803,23 @@ interface ResolvedConfig {
303
803
  }
304
804
 
305
805
  interface RequestOptions {
306
- method: "GET" | "POST" | "PATCH" | "DELETE";
806
+ method: "GET" | "POST" | "PATCH" | "PUT" | "DELETE";
307
807
  path: string;
308
808
  query?: Record<string, string | number | undefined>;
309
809
  body?: unknown;
310
- /** Reused across retries — what makes a retried write safe. */
311
- idempotencyKey?: string;
312
- /** Disable retries for this call (rarely needed). */
810
+ /**
811
+ * Whether this call may be auto-retried on a transient failure. Defaults to
812
+ * method-based safety: reads (GET), idempotent replaces (PUT), and DELETE are
813
+ * replay-safe. Non-idempotent writes (POST/PATCH) default to NOT retried so a
814
+ * transient failure can't duplicate the write; callers that tolerate a retry
815
+ * opt in explicitly.
816
+ */
313
817
  retry?: boolean;
314
818
  }
315
819
  /**
316
820
  * The single HTTP seam. Builds the authenticated request, enforces a timeout,
317
821
  * unwraps the `{ ok, ... }` envelope, maps failures to typed errors, and retries
318
- * transient ones with backoff + jitter — reusing the same idempotency key on
319
- * every attempt.
822
+ * transient ones with backoff + jitter.
320
823
  */
321
824
  declare class Transport {
322
825
  private readonly cfg;
@@ -328,6 +831,30 @@ declare class Transport {
328
831
  private buildUrl;
329
832
  }
330
833
 
834
+ /**
835
+ * The `credits` resource — manage the org's credit *types* (the catalog). A
836
+ * credit's stable `agentKey` is what you pass to `signals.credit()` when
837
+ * recording usage against it. `/api/v1/credits`.
838
+ */
839
+ declare class Credits {
840
+ private readonly transport;
841
+ constructor(transport: Transport);
842
+ /** List credit types. Pass `{ active: true }` to only return active ones. */
843
+ list(params?: {
844
+ active?: boolean;
845
+ }): Promise<Credit[]>;
846
+ /** Create a credit type. `POST /api/v1/credits`. */
847
+ create(input: CreateCreditInput): Promise<void>;
848
+ /** Fetch one credit type with usage stats. `GET /api/v1/credits/:id`. */
849
+ get(id: string): Promise<CreditDetail>;
850
+ /** Update a credit type's definition. `PATCH /api/v1/credits/:id`. */
851
+ update(id: string, input: UpdateCreditInput): Promise<void>;
852
+ /** Activate or deactivate a credit type. */
853
+ setActive(id: string, isActive: boolean): Promise<Credit>;
854
+ /** Delete a credit type. Refused while a customer is linked to it. */
855
+ delete(id: string): Promise<void>;
856
+ }
857
+
331
858
  /**
332
859
  * The `customers` resource — full CRUD over the org's customers plus the
333
860
  * read-only insight endpoints (usage / balances / plan / revenue). Every call
@@ -371,6 +898,127 @@ declare class Customers {
371
898
  revenue(id: string, params?: {
372
899
  range?: RevenueRange;
373
900
  }): Promise<CustomerRevenue>;
901
+ /** List a customer's members. `GET …/:id/members`. */
902
+ listMembers(id: string): Promise<Member[]>;
903
+ /** Add a member to a customer. Duplicate `employeeId` → ConflictError. */
904
+ addMember(id: string, input: AddMemberInput): Promise<Member>;
905
+ /** Update a member's profile (role is fixed). `PATCH …/:id/members/:memberId`. */
906
+ updateMember(id: string, memberId: string, input: UpdateMemberInput): Promise<Member>;
907
+ /** Remove a member from a customer. `DELETE …/:id/members/:memberId`. */
908
+ removeMember(id: string, memberId: string): Promise<void>;
909
+ /** The customer's wallet balance + transactions. `GET …/:id/wallet`. */
910
+ wallet(id: string, params?: {
911
+ limit?: number;
912
+ }): Promise<WalletList>;
913
+ /**
914
+ * Record a manual wallet entry (top-up or deduction). `amount` is always
915
+ * positive; the sign comes from `type`. `POST …/:id/wallet`.
916
+ */
917
+ addWalletEntry(id: string, input: WalletEntryInput): Promise<{
918
+ transaction: WalletTransaction;
919
+ balanceUsd: number;
920
+ }>;
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
+ /** Grant or claw back a credit balance. `POST …/:id/credits/adjust`. */
926
+ adjustCredit(id: string, input: CreditAdjustInput): Promise<void>;
927
+ /** Grant or claw back an outcome balance. Returns the remaining balance. */
928
+ adjustOutcome(id: string, input: OutcomeAdjustInput): Promise<{
929
+ remaining: number;
930
+ }>;
931
+ /** Grant or claw back a unit balance. Returns the remaining balance. */
932
+ adjustUnit(id: string, input: UnitAdjustInput): Promise<{
933
+ remaining: number;
934
+ }>;
935
+ }
936
+
937
+ /**
938
+ * The `invoices` resource — read-only. Invoices are generated by the billing
939
+ * engine from purchases; you list them, read one, or mint a hosted pay link for
940
+ * an OPEN invoice. `/api/v1/invoices`.
941
+ */
942
+ declare class Invoices {
943
+ private readonly transport;
944
+ constructor(transport: Transport);
945
+ /** List invoices, most-recent first. Filter by customer and/or status. */
946
+ list(params?: {
947
+ customerId?: string;
948
+ status?: InvoiceStatus;
949
+ limit?: number;
950
+ }): Promise<InvoiceListRow[]>;
951
+ /** Fetch one full invoice + its plan snapshot. `GET /api/v1/invoices/:id`. */
952
+ get(id: string): Promise<InvoiceDetail>;
953
+ /**
954
+ * Mint a hosted pay link for an OPEN invoice. PAID/VOID invoices are rejected
955
+ * with a `ConflictError`. `GET /api/v1/invoices/:id/pay-link`.
956
+ */
957
+ payLink(id: string): Promise<PayLink>;
958
+ }
959
+
960
+ /**
961
+ * The `outcomes` resource — manage the org's outcome *types* (the catalog). An
962
+ * outcome is a multi-step workflow; each step has a stable `agentKey` you pass
963
+ * to `signals.outcome()`. `/api/v1/outcomes`.
964
+ */
965
+ declare class Outcomes {
966
+ private readonly transport;
967
+ constructor(transport: Transport);
968
+ /** List outcome types. Pass `{ active: true }` to only return active ones. */
969
+ list(params?: {
970
+ active?: boolean;
971
+ }): Promise<Outcome[]>;
972
+ /** Create an outcome type with its steps. `POST /api/v1/outcomes`. */
973
+ create(input: CreateOutcomeInput): Promise<Outcome>;
974
+ /** Fetch one outcome type with steps + stats. `GET /api/v1/outcomes/:id`. */
975
+ get(id: string): Promise<OutcomeDetail>;
976
+ /** Update an outcome type's definition. `PATCH /api/v1/outcomes/:id`. */
977
+ update(id: string, input: UpdateOutcomeInput): Promise<Outcome>;
978
+ /** Activate or deactivate an outcome type. */
979
+ setActive(id: string, isActive: boolean): Promise<void>;
980
+ /** Delete an outcome type. */
981
+ delete(id: string): Promise<void>;
982
+ }
983
+
984
+ /**
985
+ * The `payments` resource — read-only. A payment is a PAID invoice; the `id`
986
+ * used here is that underlying invoice id. `/api/v1/payments`.
987
+ */
988
+ declare class Payments {
989
+ private readonly transport;
990
+ constructor(transport: Transport);
991
+ /** List payments (paid invoices), most-recent first. Filter by customer. */
992
+ list(params?: {
993
+ customerId?: string;
994
+ limit?: number;
995
+ }): Promise<PaymentRow[]>;
996
+ /** Fetch one payment + its plan snapshot. `GET /api/v1/payments/:id`. */
997
+ get(id: string): Promise<PaymentDetail>;
998
+ }
999
+
1000
+ /**
1001
+ * The `plans` resource — define and manage the billing plans customers
1002
+ * subscribe to. Each plan is a set of entitlement components (wallet / credit /
1003
+ * outcome / unit / flat) billed on a cycle. `/api/v1/plans`.
1004
+ */
1005
+ declare class Plans {
1006
+ private readonly transport;
1007
+ constructor(transport: Transport);
1008
+ /** List plans, oldest-first. Pass `{ active: true }` to only return active plans. */
1009
+ list(params?: {
1010
+ active?: boolean;
1011
+ }): Promise<Plan[]>;
1012
+ /** Create a plan. `POST /api/v1/plans`. */
1013
+ create(input: CreatePlanInput): Promise<Plan>;
1014
+ /** Fetch one plan with aggregate subscriber/invoice stats. `GET /api/v1/plans/:id`. */
1015
+ get(id: string): Promise<PlanDetail>;
1016
+ /** Replace a plan's definition (components + settings). `PATCH /api/v1/plans/:id`. */
1017
+ update(id: string, input: UpdatePlanInput): Promise<Plan>;
1018
+ /** Activate or deactivate a plan without rewriting it. */
1019
+ setActive(id: string, isActive: boolean): Promise<Plan>;
1020
+ /** Delete a plan. Refused once any customer has purchased it. */
1021
+ delete(id: string): Promise<void>;
374
1022
  }
375
1023
 
376
1024
  /**
@@ -385,25 +1033,44 @@ declare class Portal {
385
1033
  createToken(input: PortalTokenInput): Promise<PortalToken>;
386
1034
  }
387
1035
 
1036
+ /**
1037
+ * The `purchases` resource — a purchase is a customer's subscription to a plan.
1038
+ * Creating one auto-cancels the customer's existing scheduled/active purchase
1039
+ * (this is also how you "change plan"). `/api/v1/purchases`.
1040
+ */
1041
+ declare class Purchases {
1042
+ private readonly transport;
1043
+ constructor(transport: Transport);
1044
+ /** List purchases, most-recent first. Filter by customer and/or status. */
1045
+ list(params?: {
1046
+ customerId?: string;
1047
+ status?: PurchaseStatus;
1048
+ limit?: number;
1049
+ }): Promise<Purchase[]>;
1050
+ /** Subscribe a customer to a plan. `POST /api/v1/purchases`. */
1051
+ create(input: CreatePurchaseInput): Promise<Purchase>;
1052
+ /** Fetch one purchase. `GET /api/v1/purchases/:id`. */
1053
+ get(id: string): Promise<PurchaseDetail>;
1054
+ /**
1055
+ * Turn automatic billing on or off for a purchase. When pausing, an optional
1056
+ * `pauseReason` is recorded. `PATCH /api/v1/purchases/:id`.
1057
+ */
1058
+ setAutoPayment(id: string, autoPayment: boolean, opts?: {
1059
+ pauseReason?: string;
1060
+ }): Promise<{
1061
+ autoPayment: boolean;
1062
+ }>;
1063
+ /** Cancel a purchase (voids any open invoice). `POST /api/v1/purchases/:id/cancel`. */
1064
+ cancel(id: string): Promise<void>;
1065
+ }
1066
+
388
1067
  /** One buffered, wire-ready signal awaiting a background flush. */
389
1068
  interface QueuedSignal {
390
1069
  /** The exact JSON body to POST to /api/v1/usage. */
391
1070
  body: Record<string, unknown>;
392
- /** Reused across retries. */
393
- idempotencyKey: string;
394
1071
  /** The original signal — passed to onError/onDrop hooks. */
395
1072
  signal: Signal;
396
1073
  }
397
- /**
398
- * Pluggable buffer. The default is in-memory; a host that needs to survive a
399
- * crash *before* send can implement this against disk/Redis/SQLite.
400
- */
401
- interface QueueStore {
402
- push(item: QueuedSignal): void;
403
- /** Remove and return up to `n` items (FIFO). */
404
- take(n: number): QueuedSignal[];
405
- size(): number;
406
- }
407
1074
 
408
1075
  /**
409
1076
  * Background send engine for async-mode signals. Buffers wire-ready signals and
@@ -472,6 +1139,58 @@ declare class Signals {
472
1139
  customerId: string;
473
1140
  limit?: number;
474
1141
  }): Promise<UsageList>;
1142
+ /**
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`.
1146
+ */
1147
+ unit(input: UnitInput): Promise<{
1148
+ unitUsage: Record<string, unknown>;
1149
+ }>;
1150
+ /** A customer's unit balances + recent unit events. `GET /api/v1/units`. */
1151
+ unitUsage(params: {
1152
+ customerId: string;
1153
+ limit?: number;
1154
+ }): Promise<UnitUsageList>;
1155
+ }
1156
+
1157
+ /**
1158
+ * The `units` resource — manage the org's unit *types* (the catalog): named,
1159
+ * quantity-priced meters (FLAT / SLAB / VOLUME). Record consumption against a
1160
+ * unit with `signals.unit()`. `/api/v1/units-catalog`.
1161
+ */
1162
+ declare class Units {
1163
+ private readonly transport;
1164
+ constructor(transport: Transport);
1165
+ /** List unit types. Pass `{ active: true }` to only return active ones. */
1166
+ list(params?: {
1167
+ active?: boolean;
1168
+ }): Promise<Unit[]>;
1169
+ /** Create a unit type. `POST /api/v1/units-catalog`. */
1170
+ create(input: CreateUnitInput): Promise<Unit>;
1171
+ /** Fetch one unit type with stats. `GET /api/v1/units-catalog/:id`. */
1172
+ get(id: string): Promise<UnitDetail>;
1173
+ /** Update a unit type's definition. `PATCH /api/v1/units-catalog/:id`. */
1174
+ update(id: string, input: UpdateUnitInput): Promise<Unit>;
1175
+ /** Activate or deactivate a unit type. */
1176
+ setActive(id: string, isActive: boolean): Promise<Unit>;
1177
+ /** Delete a unit type. */
1178
+ delete(id: string): Promise<void>;
1179
+ }
1180
+
1181
+ /**
1182
+ * The `webhooks` resource — threshold alerts. At most one webhook per kind
1183
+ * (CREDIT / OUTCOME / WALLET); posting a kind again upserts it. `/api/v1/webhooks`.
1184
+ */
1185
+ declare class Webhooks {
1186
+ private readonly transport;
1187
+ constructor(transport: Transport);
1188
+ /** List configured webhooks. `GET /api/v1/webhooks`. */
1189
+ list(): Promise<Webhook[]>;
1190
+ /** Create or replace the webhook for a kind. `POST /api/v1/webhooks`. */
1191
+ upsert(input: UpsertWebhookInput): Promise<Webhook>;
1192
+ /** Delete the webhook for a kind (idempotent). `DELETE /api/v1/webhooks/:kind`. */
1193
+ delete(kind: ThresholdKind): Promise<void>;
475
1194
  }
476
1195
 
477
1196
  /**
@@ -483,7 +1202,7 @@ declare class Signals {
483
1202
  * await cnk.signals.credit({
484
1203
  * customerId: "cus_123",
485
1204
  * model: "gpt-4o", // catalog model id
486
- * key: "api_credit", // the credit's stable key
1205
+ * agentKey: "api_credit", // the credit's stable agent key
487
1206
  * tokens: { input: 1200, output: 340 },
488
1207
  * });
489
1208
  *
@@ -492,10 +1211,26 @@ declare class Signals {
492
1211
  * ```
493
1212
  */
494
1213
  declare class ClockNext {
495
- /** Record + read usage signals. */
1214
+ /** Record + read usage signals (credit / wallet / outcome / unit). */
496
1215
  readonly signals: Signals;
497
- /** Manage customers and read their insights. */
1216
+ /** Manage customers, their members, wallet, and balances. */
498
1217
  readonly customers: Customers;
1218
+ /** Define and manage billing plans. */
1219
+ readonly plans: Plans;
1220
+ /** Subscribe customers to plans (purchases). */
1221
+ readonly purchases: Purchases;
1222
+ /** Read invoices and mint hosted pay links. */
1223
+ readonly invoices: Invoices;
1224
+ /** Read payments (paid invoices). */
1225
+ readonly payments: Payments;
1226
+ /** Manage the credit-type catalog. */
1227
+ readonly credits: Credits;
1228
+ /** Manage the outcome-type catalog. */
1229
+ readonly outcomes: Outcomes;
1230
+ /** Manage the unit-type catalog. */
1231
+ readonly units: Units;
1232
+ /** Configure threshold webhooks. */
1233
+ readonly webhooks: Webhooks;
499
1234
  /** Mint customer-portal embed tokens. */
500
1235
  readonly portal: Portal;
501
1236
  private readonly cfg;
@@ -518,13 +1253,10 @@ declare class ClockNext {
518
1253
  declare class ClockNextError extends Error {
519
1254
  /** HTTP status, when the failure came from a server response. */
520
1255
  readonly status?: number;
521
- /** The idempotency key of the offending signal, when applicable. */
522
- readonly idempotencyKey?: string;
523
1256
  /** Whether the SDK considers this failure worth retrying. */
524
1257
  readonly retryable: boolean;
525
1258
  constructor(message: string, opts?: {
526
1259
  status?: number;
527
- idempotencyKey?: string;
528
1260
  retryable?: boolean;
529
1261
  });
530
1262
  }
@@ -543,14 +1275,13 @@ declare class PlanError extends ClockNextError {
543
1275
  /** 422 — insufficient credits / units / outcomes for the call. */
544
1276
  declare class AllowanceError extends ClockNextError {
545
1277
  }
546
- /** 409 — conflict (e.g. idempotency-key reuse with a different payload). */
1278
+ /** 409 — conflict. */
547
1279
  declare class ConflictError extends ClockNextError {
548
1280
  }
549
1281
  /** 429 — rate limited. */
550
1282
  declare class RateLimitError extends ClockNextError {
551
1283
  readonly retryAfterMs?: number;
552
1284
  constructor(message: string, opts?: {
553
- idempotencyKey?: string;
554
1285
  retryAfterMs?: number;
555
1286
  });
556
1287
  }
@@ -559,22 +1290,7 @@ declare class ServerError extends ClockNextError {
559
1290
  }
560
1291
  /** fetch threw / request timed out — request never completed. */
561
1292
  declare class NetworkError extends ClockNextError {
562
- constructor(message: string, opts?: {
563
- idempotencyKey?: string;
564
- });
1293
+ constructor(message: string);
565
1294
  }
566
1295
 
567
- /**
568
- * Generates a stable idempotency key for one logical event. Generated ONCE at
569
- * enqueue/track time and reused across every retry of that event — regenerating
570
- * per HTTP attempt would defeat dedup (the documented foot-gun in most usage
571
- * SDKs).
572
- *
573
- * Uses the Web Crypto global (`globalThis.crypto`), which is present on Node 18+
574
- * and every edge runtime — and, unlike a static `node:crypto` import, never
575
- * fails to load on runtimes that lack Node built-ins. Degrades through
576
- * `getRandomValues` to `Math.random` so it always returns a v4 UUID.
577
- */
578
- declare function newIdempotencyKey(): string;
579
-
580
- export { AllowanceError, type ApiCustomer, AuthError, ClockNext, type ClockNextConfig, ClockNextError, ConflictError, type CreateCustomerInput, type CreditInput, type CreditSignal, type CustomerBalances, type CustomerList, type CustomerPlan, type CustomerProfileInput, type CustomerRevenue, type DropReason, type FetchLike, type Logger, NetworkError, NotFoundError, type OutcomeInput, type OutcomeSignal, PlanError, type PortalToken, type PortalTokenInput, type QueueStore, type QueuedSignal, RateLimitError, type RevenueRange, type SerializedOutcomeAttribution, type SerializedRuleApplication, type SerializedUsageLog, ServerError, type Signal, type SignalStatus, type SignalType, type Tokens, type TrackResult, type UsageList, ValidationError, type WalletInput, type WalletSignal, newIdempotencyKey, signalToWire };
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 };