@drip-sdk/node 1.0.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.
@@ -0,0 +1,1246 @@
1
+ /**
2
+ * Drip SDK - Usage-based billing for Node.js
3
+ *
4
+ * The official SDK for integrating with the Drip billing platform.
5
+ * Provides methods for managing customers, recording usage, handling charges,
6
+ * and configuring webhooks.
7
+ *
8
+ * @packageDocumentation
9
+ */
10
+ /**
11
+ * Configuration options for the Drip SDK client.
12
+ */
13
+ interface DripConfig {
14
+ /**
15
+ * Your Drip API key. Obtain this from the Drip dashboard.
16
+ * @example "drip_live_abc123..."
17
+ */
18
+ apiKey: string;
19
+ /**
20
+ * Base URL for the Drip API. Defaults to production API.
21
+ * Override for staging/development environments.
22
+ * @default "https://api.drip.dev/v1"
23
+ */
24
+ baseUrl?: string;
25
+ /**
26
+ * Request timeout in milliseconds.
27
+ * @default 30000
28
+ */
29
+ timeout?: number;
30
+ }
31
+ /**
32
+ * Parameters for creating a new customer.
33
+ */
34
+ interface CreateCustomerParams {
35
+ /**
36
+ * Your internal customer/user ID for reconciliation.
37
+ * @example "user_12345"
38
+ */
39
+ externalCustomerId?: string;
40
+ /**
41
+ * The customer's Drip Smart Account address (derived from their EOA).
42
+ * @example "0x1234567890abcdef..."
43
+ */
44
+ onchainAddress: string;
45
+ /**
46
+ * Additional metadata to store with the customer.
47
+ */
48
+ metadata?: Record<string, unknown>;
49
+ }
50
+ /**
51
+ * A Drip customer record.
52
+ */
53
+ interface Customer {
54
+ /** Unique customer ID in Drip */
55
+ id: string;
56
+ /** Your business ID */
57
+ businessId: string;
58
+ /** Your external customer ID (if provided) */
59
+ externalCustomerId: string | null;
60
+ /** Customer's on-chain address */
61
+ onchainAddress: string;
62
+ /** Custom metadata */
63
+ metadata: Record<string, unknown> | null;
64
+ /** ISO timestamp of creation */
65
+ createdAt: string;
66
+ /** ISO timestamp of last update */
67
+ updatedAt: string;
68
+ }
69
+ /**
70
+ * Options for listing customers.
71
+ */
72
+ interface ListCustomersOptions {
73
+ /**
74
+ * Maximum number of customers to return (1-100).
75
+ * @default 100
76
+ */
77
+ limit?: number;
78
+ /**
79
+ * Filter by customer status.
80
+ */
81
+ status?: 'ACTIVE' | 'LOW_BALANCE' | 'PAUSED';
82
+ }
83
+ /**
84
+ * Response from listing customers.
85
+ */
86
+ interface ListCustomersResponse {
87
+ /** Array of customers */
88
+ data: Customer[];
89
+ /** Total count returned */
90
+ count: number;
91
+ }
92
+ /**
93
+ * Customer balance information.
94
+ */
95
+ interface BalanceResult {
96
+ /** Customer ID */
97
+ customerId: string;
98
+ /** Balance in USDC (6 decimals) */
99
+ balanceUSDC: string;
100
+ /** Balance in native token */
101
+ balanceToken: string;
102
+ /** ISO timestamp of last balance update */
103
+ lastUpdated: string;
104
+ }
105
+ /**
106
+ * Parameters for recording usage and charging a customer.
107
+ */
108
+ interface ChargeParams {
109
+ /**
110
+ * The Drip customer ID to charge.
111
+ */
112
+ customerId: string;
113
+ /**
114
+ * The usage meter/type to record against.
115
+ * Must match a meter configured in your pricing plan.
116
+ * @example "api_calls", "compute_seconds", "storage_gb"
117
+ */
118
+ meter: string;
119
+ /**
120
+ * The quantity of usage to record.
121
+ * Will be multiplied by the meter's unit price.
122
+ */
123
+ quantity: number;
124
+ /**
125
+ * Unique key to prevent duplicate charges.
126
+ * If provided, retrying with the same key returns the original charge.
127
+ * @example "req_abc123"
128
+ */
129
+ idempotencyKey?: string;
130
+ /**
131
+ * Additional metadata to attach to this usage event.
132
+ */
133
+ metadata?: Record<string, unknown>;
134
+ }
135
+ /**
136
+ * Result of a successful charge operation.
137
+ */
138
+ interface ChargeResult {
139
+ /** Whether the charge was successful */
140
+ success: boolean;
141
+ /** The usage event ID */
142
+ usageEventId: string;
143
+ /** True if this was an idempotent replay (returned cached result from previous request) */
144
+ isReplay: boolean;
145
+ /** Details about the charge */
146
+ charge: {
147
+ /** Unique charge ID */
148
+ id: string;
149
+ /** Amount charged in USDC (6 decimals) */
150
+ amountUsdc: string;
151
+ /** Amount in native token */
152
+ amountToken: string;
153
+ /** Blockchain transaction hash */
154
+ txHash: string;
155
+ /** Current status of the charge */
156
+ status: ChargeStatus;
157
+ };
158
+ }
159
+ /**
160
+ * Possible charge statuses.
161
+ */
162
+ type ChargeStatus = 'PENDING' | 'SUBMITTED' | 'CONFIRMED' | 'FAILED' | 'REFUNDED';
163
+ /**
164
+ * A detailed charge record.
165
+ */
166
+ interface Charge {
167
+ /** Unique charge ID */
168
+ id: string;
169
+ /** Associated usage event ID */
170
+ usageId: string;
171
+ /** Customer ID */
172
+ customerId: string;
173
+ /** Customer details */
174
+ customer: {
175
+ id: string;
176
+ onchainAddress: string;
177
+ externalCustomerId: string | null;
178
+ };
179
+ /** Usage event details */
180
+ usageEvent: {
181
+ id: string;
182
+ type: string;
183
+ quantity: string;
184
+ metadata: Record<string, unknown> | null;
185
+ };
186
+ /** Amount in USDC */
187
+ amountUsdc: string;
188
+ /** Amount in native token */
189
+ amountToken: string;
190
+ /** Transaction hash (if submitted) */
191
+ txHash: string | null;
192
+ /** Block number (if confirmed) */
193
+ blockNumber: string | null;
194
+ /** Current status */
195
+ status: ChargeStatus;
196
+ /** Failure reason (if failed) */
197
+ failureReason: string | null;
198
+ /** ISO timestamp of creation */
199
+ createdAt: string;
200
+ /** ISO timestamp of confirmation */
201
+ confirmedAt: string | null;
202
+ }
203
+ /**
204
+ * Options for listing charges.
205
+ */
206
+ interface ListChargesOptions {
207
+ /**
208
+ * Filter by customer ID.
209
+ */
210
+ customerId?: string;
211
+ /**
212
+ * Filter by charge status.
213
+ */
214
+ status?: ChargeStatus;
215
+ /**
216
+ * Maximum number of charges to return (1-100).
217
+ * @default 100
218
+ */
219
+ limit?: number;
220
+ /**
221
+ * Number of charges to skip (for pagination).
222
+ * @default 0
223
+ */
224
+ offset?: number;
225
+ }
226
+ /**
227
+ * Response from listing charges.
228
+ */
229
+ interface ListChargesResponse {
230
+ /** Array of charges */
231
+ data: Charge[];
232
+ /** Total count returned */
233
+ count: number;
234
+ }
235
+ /**
236
+ * Available webhook event types.
237
+ */
238
+ type WebhookEventType = 'customer.balance.low' | 'usage.recorded' | 'charge.succeeded' | 'charge.failed' | 'customer.deposit.confirmed' | 'customer.withdraw.confirmed' | 'customer.usage_cap.reached' | 'webhook.endpoint.unhealthy' | 'customer.created' | 'api_key.created' | 'pricing_plan.updated' | 'transaction.created' | 'transaction.pending' | 'transaction.confirmed' | 'transaction.failed';
239
+ /**
240
+ * Parameters for creating a webhook.
241
+ */
242
+ interface CreateWebhookParams {
243
+ /**
244
+ * The URL to send webhook events to.
245
+ * Must be HTTPS in production.
246
+ * @example "https://api.yourapp.com/webhooks/drip"
247
+ */
248
+ url: string;
249
+ /**
250
+ * Array of event types to subscribe to.
251
+ * @example ["charge.succeeded", "charge.failed"]
252
+ */
253
+ events: WebhookEventType[];
254
+ /**
255
+ * Optional description for the webhook.
256
+ */
257
+ description?: string;
258
+ }
259
+ /**
260
+ * A webhook configuration.
261
+ */
262
+ interface Webhook {
263
+ /** Unique webhook ID */
264
+ id: string;
265
+ /** Webhook endpoint URL */
266
+ url: string;
267
+ /** Subscribed event types */
268
+ events: string[];
269
+ /** Description */
270
+ description: string | null;
271
+ /** Whether the webhook is active */
272
+ isActive: boolean;
273
+ /** ISO timestamp of creation */
274
+ createdAt: string;
275
+ /** ISO timestamp of last update */
276
+ updatedAt: string;
277
+ /** Delivery statistics */
278
+ stats?: {
279
+ totalDeliveries: number;
280
+ successfulDeliveries: number;
281
+ failedDeliveries: number;
282
+ lastDeliveryAt: string | null;
283
+ };
284
+ }
285
+ /**
286
+ * Response from creating a webhook.
287
+ */
288
+ interface CreateWebhookResponse extends Webhook {
289
+ /**
290
+ * The webhook signing secret.
291
+ * Only returned once at creation time - save it securely!
292
+ */
293
+ secret: string;
294
+ /** Reminder to save the secret */
295
+ message: string;
296
+ }
297
+ /**
298
+ * Response from listing webhooks.
299
+ */
300
+ interface ListWebhooksResponse {
301
+ /** Array of webhooks */
302
+ data: Webhook[];
303
+ /** Total count */
304
+ count: number;
305
+ }
306
+ /**
307
+ * Response from deleting a webhook.
308
+ */
309
+ interface DeleteWebhookResponse {
310
+ /** Whether the deletion was successful */
311
+ success: boolean;
312
+ }
313
+ /**
314
+ * Parameters for creating a checkout session.
315
+ * This is the primary way to get money into a customer's account.
316
+ */
317
+ interface CheckoutParams {
318
+ /**
319
+ * Existing customer ID (optional).
320
+ * If not provided, a new customer is created after payment.
321
+ */
322
+ customerId?: string;
323
+ /**
324
+ * Your internal customer/user ID for new customers.
325
+ * Used to link the Drip customer to your system.
326
+ */
327
+ externalCustomerId?: string;
328
+ /**
329
+ * Amount in cents (e.g., 5000 = $50.00).
330
+ * Minimum: 500 ($5.00)
331
+ * Maximum: 1000000 ($10,000.00)
332
+ */
333
+ amount: number;
334
+ /**
335
+ * URL to redirect after successful payment.
336
+ * Query params will be added: session_id, customer_id, status
337
+ */
338
+ returnUrl: string;
339
+ /**
340
+ * URL to redirect if user cancels (optional).
341
+ */
342
+ cancelUrl?: string;
343
+ /**
344
+ * Custom metadata to attach to this checkout.
345
+ */
346
+ metadata?: Record<string, unknown>;
347
+ }
348
+ /**
349
+ * Result of creating a checkout session.
350
+ */
351
+ interface CheckoutResult {
352
+ /** Checkout session ID */
353
+ id: string;
354
+ /** URL to redirect user to for payment */
355
+ url: string;
356
+ /** ISO timestamp when session expires (30 minutes) */
357
+ expiresAt: string;
358
+ /** Amount in USD */
359
+ amountUsd: number;
360
+ }
361
+ /**
362
+ * Parameters for creating a new workflow.
363
+ */
364
+ interface CreateWorkflowParams {
365
+ /** Human-readable workflow name */
366
+ name: string;
367
+ /** URL-safe identifier (lowercase alphanumeric with underscores/hyphens) */
368
+ slug: string;
369
+ /** Type of workflow */
370
+ productSurface?: 'RPC' | 'WEBHOOK' | 'AGENT' | 'PIPELINE' | 'CUSTOM';
371
+ /** Optional description */
372
+ description?: string;
373
+ /** Additional metadata */
374
+ metadata?: Record<string, unknown>;
375
+ }
376
+ /**
377
+ * A workflow definition.
378
+ */
379
+ interface Workflow {
380
+ id: string;
381
+ name: string;
382
+ slug: string;
383
+ productSurface: string;
384
+ description: string | null;
385
+ isActive: boolean;
386
+ createdAt: string;
387
+ }
388
+ /**
389
+ * Parameters for starting a new agent run.
390
+ */
391
+ interface StartRunParams {
392
+ /** Customer ID this run belongs to */
393
+ customerId: string;
394
+ /** Workflow ID this run executes */
395
+ workflowId: string;
396
+ /** Your external run ID for correlation */
397
+ externalRunId?: string;
398
+ /** Correlation ID for distributed tracing */
399
+ correlationId?: string;
400
+ /** Parent run ID for nested runs */
401
+ parentRunId?: string;
402
+ /** Additional metadata */
403
+ metadata?: Record<string, unknown>;
404
+ }
405
+ /**
406
+ * Result of starting a run.
407
+ */
408
+ interface RunResult {
409
+ id: string;
410
+ customerId: string;
411
+ workflowId: string;
412
+ workflowName: string;
413
+ status: RunStatus;
414
+ correlationId: string | null;
415
+ createdAt: string;
416
+ }
417
+ /**
418
+ * Parameters for ending/updating a run.
419
+ */
420
+ interface EndRunParams {
421
+ /** New status for the run */
422
+ status: 'COMPLETED' | 'FAILED' | 'CANCELLED' | 'TIMEOUT';
423
+ /** Error message if failed */
424
+ errorMessage?: string;
425
+ /** Error code for categorization */
426
+ errorCode?: string;
427
+ /** Additional metadata */
428
+ metadata?: Record<string, unknown>;
429
+ }
430
+ /**
431
+ * Possible run statuses.
432
+ */
433
+ type RunStatus = 'PENDING' | 'RUNNING' | 'COMPLETED' | 'FAILED' | 'CANCELLED' | 'TIMEOUT';
434
+ /**
435
+ * Parameters for emitting an event to a run.
436
+ */
437
+ interface EmitEventParams {
438
+ /** Run ID to attach this event to */
439
+ runId: string;
440
+ /** Event type (e.g., "agent.step", "rpc.request") */
441
+ eventType: string;
442
+ /** Quantity of units consumed */
443
+ quantity?: number;
444
+ /** Human-readable unit label */
445
+ units?: string;
446
+ /** Human-readable description */
447
+ description?: string;
448
+ /** Cost in abstract units */
449
+ costUnits?: number;
450
+ /** Currency for cost */
451
+ costCurrency?: string;
452
+ /** Correlation ID for tracing */
453
+ correlationId?: string;
454
+ /** Parent event ID for trace tree */
455
+ parentEventId?: string;
456
+ /** OpenTelemetry-style span ID */
457
+ spanId?: string;
458
+ /** Idempotency key (auto-generated if not provided) */
459
+ idempotencyKey?: string;
460
+ /** Additional metadata */
461
+ metadata?: Record<string, unknown>;
462
+ }
463
+ /**
464
+ * Result of emitting an event.
465
+ */
466
+ interface EventResult {
467
+ id: string;
468
+ runId: string;
469
+ eventType: string;
470
+ quantity: number;
471
+ costUnits: number | null;
472
+ isDuplicate: boolean;
473
+ timestamp: string;
474
+ }
475
+ /**
476
+ * A meter (usage type) from a pricing plan.
477
+ */
478
+ interface Meter {
479
+ /** Pricing plan ID */
480
+ id: string;
481
+ /** Human-readable name */
482
+ name: string;
483
+ /** The meter/usage type identifier (use this in charge() calls) */
484
+ meter: string;
485
+ /** Price per unit in USD */
486
+ unitPriceUsd: string;
487
+ /** Whether this meter is active */
488
+ isActive: boolean;
489
+ }
490
+ /**
491
+ * Response from listing meters.
492
+ */
493
+ interface ListMetersResponse {
494
+ /** Array of available meters */
495
+ data: Meter[];
496
+ /** Total count */
497
+ count: number;
498
+ }
499
+ /**
500
+ * A single event to record in a run.
501
+ */
502
+ interface RecordRunEvent {
503
+ /** Event type (e.g., "agent.step", "tool.call") */
504
+ eventType: string;
505
+ /** Quantity of units consumed */
506
+ quantity?: number;
507
+ /** Human-readable unit label */
508
+ units?: string;
509
+ /** Human-readable description */
510
+ description?: string;
511
+ /** Cost in abstract units */
512
+ costUnits?: number;
513
+ /** Additional metadata */
514
+ metadata?: Record<string, unknown>;
515
+ }
516
+ /**
517
+ * Parameters for recording a complete run in one call.
518
+ * This is the simplified API that combines workflow, run, and events.
519
+ */
520
+ interface RecordRunParams {
521
+ /** Customer ID this run belongs to */
522
+ customerId: string;
523
+ /**
524
+ * Workflow identifier. Can be:
525
+ * - An existing workflow ID (e.g., "wf_abc123")
526
+ * - A slug that will be auto-created if it doesn't exist (e.g., "my_agent")
527
+ */
528
+ workflow: string;
529
+ /** Events that occurred during the run */
530
+ events: RecordRunEvent[];
531
+ /** Final status of the run */
532
+ status: 'COMPLETED' | 'FAILED' | 'CANCELLED' | 'TIMEOUT';
533
+ /** Error message if status is FAILED */
534
+ errorMessage?: string;
535
+ /** Error code if status is FAILED */
536
+ errorCode?: string;
537
+ /** Your external run ID for correlation */
538
+ externalRunId?: string;
539
+ /** Correlation ID for distributed tracing */
540
+ correlationId?: string;
541
+ /** Additional metadata */
542
+ metadata?: Record<string, unknown>;
543
+ }
544
+ /**
545
+ * Result of recording a run.
546
+ */
547
+ interface RecordRunResult {
548
+ /** The created run */
549
+ run: {
550
+ id: string;
551
+ workflowId: string;
552
+ workflowName: string;
553
+ status: RunStatus;
554
+ durationMs: number | null;
555
+ };
556
+ /** Summary of events created */
557
+ events: {
558
+ created: number;
559
+ duplicates: number;
560
+ };
561
+ /** Total cost computed */
562
+ totalCostUnits: string | null;
563
+ /** Human-readable summary */
564
+ summary: string;
565
+ }
566
+ /**
567
+ * Full run timeline response.
568
+ */
569
+ interface RunTimeline {
570
+ run: {
571
+ id: string;
572
+ customerId: string;
573
+ customerName: string | null;
574
+ workflowId: string;
575
+ workflowName: string;
576
+ status: RunStatus;
577
+ startedAt: string | null;
578
+ endedAt: string | null;
579
+ durationMs: number | null;
580
+ errorMessage: string | null;
581
+ errorCode: string | null;
582
+ correlationId: string | null;
583
+ metadata: Record<string, unknown> | null;
584
+ };
585
+ timeline: Array<{
586
+ id: string;
587
+ eventType: string;
588
+ quantity: number;
589
+ units: string | null;
590
+ description: string | null;
591
+ costUnits: number | null;
592
+ timestamp: string;
593
+ correlationId: string | null;
594
+ parentEventId: string | null;
595
+ charge: {
596
+ id: string;
597
+ amountUsdc: string;
598
+ status: string;
599
+ } | null;
600
+ }>;
601
+ totals: {
602
+ eventCount: number;
603
+ totalQuantity: string;
604
+ totalCostUnits: string;
605
+ totalChargedUsdc: string;
606
+ };
607
+ summary: string;
608
+ }
609
+ /**
610
+ * Error thrown by Drip SDK operations.
611
+ */
612
+ declare class DripError extends Error {
613
+ statusCode: number;
614
+ code?: string | undefined;
615
+ /**
616
+ * Creates a new DripError.
617
+ * @param message - Human-readable error message
618
+ * @param statusCode - HTTP status code from the API
619
+ * @param code - Machine-readable error code
620
+ */
621
+ constructor(message: string, statusCode: number, code?: string | undefined);
622
+ }
623
+ /**
624
+ * The main Drip SDK client.
625
+ *
626
+ * @example
627
+ * ```typescript
628
+ * import { Drip } from '@drip-billing/sdk';
629
+ *
630
+ * const drip = new Drip({
631
+ * apiKey: process.env.DRIP_API_KEY!,
632
+ * });
633
+ *
634
+ * // Create a customer
635
+ * const customer = await drip.createCustomer({
636
+ * onchainAddress: '0x...',
637
+ * externalCustomerId: 'user_123',
638
+ * });
639
+ *
640
+ * // Record usage and charge
641
+ * const result = await drip.charge({
642
+ * customerId: customer.id,
643
+ * meter: 'api_calls',
644
+ * quantity: 100,
645
+ * });
646
+ *
647
+ * console.log(`Charged ${result.charge.amountUsdc} USDC`);
648
+ * ```
649
+ */
650
+ declare class Drip {
651
+ private readonly apiKey;
652
+ private readonly baseUrl;
653
+ private readonly timeout;
654
+ /**
655
+ * Creates a new Drip SDK client.
656
+ *
657
+ * @param config - Configuration options
658
+ * @throws {Error} If apiKey is not provided
659
+ *
660
+ * @example
661
+ * ```typescript
662
+ * const drip = new Drip({
663
+ * apiKey: 'drip_live_abc123...',
664
+ * });
665
+ * ```
666
+ */
667
+ constructor(config: DripConfig);
668
+ /**
669
+ * Makes an authenticated request to the Drip API.
670
+ * @internal
671
+ */
672
+ private request;
673
+ /**
674
+ * Creates a new customer in your Drip account.
675
+ *
676
+ * @param params - Customer creation parameters
677
+ * @returns The created customer
678
+ * @throws {DripError} If creation fails (e.g., duplicate customer)
679
+ *
680
+ * @example
681
+ * ```typescript
682
+ * const customer = await drip.createCustomer({
683
+ * onchainAddress: '0x1234567890abcdef...',
684
+ * externalCustomerId: 'user_123',
685
+ * metadata: { plan: 'pro' },
686
+ * });
687
+ * ```
688
+ */
689
+ createCustomer(params: CreateCustomerParams): Promise<Customer>;
690
+ /**
691
+ * Retrieves a customer by their Drip ID.
692
+ *
693
+ * @param customerId - The Drip customer ID
694
+ * @returns The customer details
695
+ * @throws {DripError} If customer not found (404)
696
+ *
697
+ * @example
698
+ * ```typescript
699
+ * const customer = await drip.getCustomer('cust_abc123');
700
+ * console.log(customer.onchainAddress);
701
+ * ```
702
+ */
703
+ getCustomer(customerId: string): Promise<Customer>;
704
+ /**
705
+ * Lists all customers for your business.
706
+ *
707
+ * @param options - Optional filtering and pagination
708
+ * @returns List of customers
709
+ *
710
+ * @example
711
+ * ```typescript
712
+ * // List all customers
713
+ * const { data: customers } = await drip.listCustomers();
714
+ *
715
+ * // List with filters
716
+ * const { data: activeCustomers } = await drip.listCustomers({
717
+ * status: 'ACTIVE',
718
+ * limit: 50,
719
+ * });
720
+ * ```
721
+ */
722
+ listCustomers(options?: ListCustomersOptions): Promise<ListCustomersResponse>;
723
+ /**
724
+ * Gets the current balance for a customer.
725
+ *
726
+ * @param customerId - The Drip customer ID
727
+ * @returns Current balance in USDC and native token
728
+ *
729
+ * @example
730
+ * ```typescript
731
+ * const balance = await drip.getBalance('cust_abc123');
732
+ * console.log(`Balance: ${balance.balanceUSDC} USDC`);
733
+ * ```
734
+ */
735
+ getBalance(customerId: string): Promise<BalanceResult>;
736
+ /**
737
+ * Records usage and charges a customer.
738
+ *
739
+ * This is the primary method for billing customers. It:
740
+ * 1. Records the usage event
741
+ * 2. Calculates the charge based on your pricing plan
742
+ * 3. Executes the on-chain charge
743
+ *
744
+ * @param params - Charge parameters
745
+ * @returns The charge result
746
+ * @throws {DripError} If charge fails (insufficient balance, invalid customer, etc.)
747
+ *
748
+ * @example
749
+ * ```typescript
750
+ * const result = await drip.charge({
751
+ * customerId: 'cust_abc123',
752
+ * meter: 'api_calls',
753
+ * quantity: 100,
754
+ * idempotencyKey: 'req_unique_123',
755
+ * });
756
+ *
757
+ * if (result.success) {
758
+ * console.log(`Charged ${result.charge.amountUsdc} USDC`);
759
+ * console.log(`TX: ${result.charge.txHash}`);
760
+ * }
761
+ * ```
762
+ */
763
+ charge(params: ChargeParams): Promise<ChargeResult>;
764
+ /**
765
+ * Retrieves a specific charge by ID.
766
+ *
767
+ * @param chargeId - The charge ID
768
+ * @returns The charge details
769
+ * @throws {DripError} If charge not found (404)
770
+ *
771
+ * @example
772
+ * ```typescript
773
+ * const charge = await drip.getCharge('chg_abc123');
774
+ * console.log(`Status: ${charge.status}`);
775
+ * ```
776
+ */
777
+ getCharge(chargeId: string): Promise<Charge>;
778
+ /**
779
+ * Lists charges for your business.
780
+ *
781
+ * @param options - Optional filtering and pagination
782
+ * @returns List of charges
783
+ *
784
+ * @example
785
+ * ```typescript
786
+ * // List all charges
787
+ * const { data: charges } = await drip.listCharges();
788
+ *
789
+ * // List charges for a specific customer
790
+ * const { data: customerCharges } = await drip.listCharges({
791
+ * customerId: 'cust_abc123',
792
+ * status: 'CONFIRMED',
793
+ * });
794
+ * ```
795
+ */
796
+ listCharges(options?: ListChargesOptions): Promise<ListChargesResponse>;
797
+ /**
798
+ * Gets the current status of a charge.
799
+ *
800
+ * Useful for polling charge status after async operations.
801
+ *
802
+ * @param chargeId - The charge ID
803
+ * @returns Current charge status
804
+ *
805
+ * @example
806
+ * ```typescript
807
+ * const status = await drip.getChargeStatus('chg_abc123');
808
+ * if (status.status === 'CONFIRMED') {
809
+ * console.log('Charge confirmed!');
810
+ * }
811
+ * ```
812
+ */
813
+ getChargeStatus(chargeId: string): Promise<{
814
+ status: ChargeStatus;
815
+ txHash?: string;
816
+ }>;
817
+ /**
818
+ * Creates a checkout session to add funds to a customer's account.
819
+ *
820
+ * This is the PRIMARY method for getting money into Drip. It returns a URL
821
+ * to a hosted checkout page where customers can pay via:
822
+ * - Bank transfer (ACH) - $0.50 flat fee, 1-2 business days
823
+ * - Debit card - 1.5% fee, instant
824
+ * - Direct USDC - no fee, instant
825
+ *
826
+ * After payment, the customer is redirected to your returnUrl with:
827
+ * - session_id: The checkout session ID
828
+ * - customer_id: The Drip customer ID
829
+ * - status: "success" or "failed"
830
+ *
831
+ * @param params - Checkout parameters
832
+ * @returns Checkout session with redirect URL
833
+ *
834
+ * @example
835
+ * ```typescript
836
+ * // Basic checkout
837
+ * const { url } = await drip.checkout({
838
+ * customerId: 'cust_abc123',
839
+ * amount: 5000, // $50.00
840
+ * returnUrl: 'https://myapp.com/dashboard',
841
+ * });
842
+ *
843
+ * // Redirect user to checkout
844
+ * res.redirect(url);
845
+ * ```
846
+ *
847
+ * @example
848
+ * ```typescript
849
+ * // Checkout for new customer
850
+ * const { url, id } = await drip.checkout({
851
+ * externalCustomerId: 'user_123', // Your user ID
852
+ * amount: 10000, // $100.00
853
+ * returnUrl: 'https://myapp.com/welcome',
854
+ * metadata: { plan: 'pro' },
855
+ * });
856
+ * ```
857
+ */
858
+ checkout(params: CheckoutParams): Promise<CheckoutResult>;
859
+ /**
860
+ * Creates a new webhook endpoint.
861
+ *
862
+ * The webhook secret is only returned once at creation time.
863
+ * Store it securely for verifying webhook signatures.
864
+ *
865
+ * @param config - Webhook configuration
866
+ * @returns The created webhook with its secret
867
+ *
868
+ * @example
869
+ * ```typescript
870
+ * const webhook = await drip.createWebhook({
871
+ * url: 'https://api.yourapp.com/webhooks/drip',
872
+ * events: ['charge.succeeded', 'charge.failed'],
873
+ * description: 'Main webhook endpoint',
874
+ * });
875
+ *
876
+ * // IMPORTANT: Save this secret securely!
877
+ * console.log(`Webhook secret: ${webhook.secret}`);
878
+ * ```
879
+ */
880
+ createWebhook(config: CreateWebhookParams): Promise<CreateWebhookResponse>;
881
+ /**
882
+ * Lists all webhook endpoints for your business.
883
+ *
884
+ * @returns List of webhooks with delivery statistics
885
+ *
886
+ * @example
887
+ * ```typescript
888
+ * const { data: webhooks } = await drip.listWebhooks();
889
+ * webhooks.forEach(wh => {
890
+ * console.log(`${wh.url}: ${wh.stats?.successfulDeliveries} successful`);
891
+ * });
892
+ * ```
893
+ */
894
+ listWebhooks(): Promise<ListWebhooksResponse>;
895
+ /**
896
+ * Retrieves a specific webhook by ID.
897
+ *
898
+ * @param webhookId - The webhook ID
899
+ * @returns The webhook details with statistics
900
+ * @throws {DripError} If webhook not found (404)
901
+ *
902
+ * @example
903
+ * ```typescript
904
+ * const webhook = await drip.getWebhook('wh_abc123');
905
+ * console.log(`Events: ${webhook.events.join(', ')}`);
906
+ * ```
907
+ */
908
+ getWebhook(webhookId: string): Promise<Webhook>;
909
+ /**
910
+ * Deletes a webhook endpoint.
911
+ *
912
+ * @param webhookId - The webhook ID to delete
913
+ * @returns Success confirmation
914
+ * @throws {DripError} If webhook not found (404)
915
+ *
916
+ * @example
917
+ * ```typescript
918
+ * await drip.deleteWebhook('wh_abc123');
919
+ * console.log('Webhook deleted');
920
+ * ```
921
+ */
922
+ deleteWebhook(webhookId: string): Promise<DeleteWebhookResponse>;
923
+ /**
924
+ * Tests a webhook by sending a test event.
925
+ *
926
+ * @param webhookId - The webhook ID to test
927
+ * @returns Test result
928
+ *
929
+ * @example
930
+ * ```typescript
931
+ * const result = await drip.testWebhook('wh_abc123');
932
+ * console.log(`Test status: ${result.status}`);
933
+ * ```
934
+ */
935
+ testWebhook(webhookId: string): Promise<{
936
+ message: string;
937
+ deliveryId: string | null;
938
+ status: string;
939
+ }>;
940
+ /**
941
+ * Rotates the signing secret for a webhook.
942
+ *
943
+ * After rotation, update your application to use the new secret.
944
+ *
945
+ * @param webhookId - The webhook ID
946
+ * @returns The new secret
947
+ *
948
+ * @example
949
+ * ```typescript
950
+ * const { secret } = await drip.rotateWebhookSecret('wh_abc123');
951
+ * console.log(`New secret: ${secret}`);
952
+ * // Update your application with the new secret!
953
+ * ```
954
+ */
955
+ rotateWebhookSecret(webhookId: string): Promise<{
956
+ secret: string;
957
+ message: string;
958
+ }>;
959
+ /**
960
+ * Creates a new workflow definition.
961
+ *
962
+ * @param params - Workflow creation parameters
963
+ * @returns The created workflow
964
+ *
965
+ * @example
966
+ * ```typescript
967
+ * const workflow = await drip.createWorkflow({
968
+ * name: 'Prescription Intake',
969
+ * slug: 'prescription_intake',
970
+ * productSurface: 'AGENT',
971
+ * });
972
+ * ```
973
+ */
974
+ createWorkflow(params: CreateWorkflowParams): Promise<Workflow>;
975
+ /**
976
+ * Lists all workflows for your business.
977
+ *
978
+ * @returns List of workflows
979
+ */
980
+ listWorkflows(): Promise<{
981
+ data: Workflow[];
982
+ count: number;
983
+ }>;
984
+ /**
985
+ * Starts a new agent run for tracking execution.
986
+ *
987
+ * @param params - Run parameters
988
+ * @returns The started run
989
+ *
990
+ * @example
991
+ * ```typescript
992
+ * const run = await drip.startRun({
993
+ * customerId: 'cust_abc123',
994
+ * workflowId: 'wf_xyz789',
995
+ * correlationId: 'req_unique_123',
996
+ * });
997
+ *
998
+ * // Emit events during execution...
999
+ *
1000
+ * await drip.endRun(run.id, { status: 'COMPLETED' });
1001
+ * ```
1002
+ */
1003
+ startRun(params: StartRunParams): Promise<RunResult>;
1004
+ /**
1005
+ * Ends a run with a final status.
1006
+ *
1007
+ * @param runId - The run ID to end
1008
+ * @param params - End parameters including status
1009
+ * @returns Updated run info
1010
+ *
1011
+ * @example
1012
+ * ```typescript
1013
+ * await drip.endRun(run.id, {
1014
+ * status: 'COMPLETED',
1015
+ * });
1016
+ *
1017
+ * // Or with error:
1018
+ * await drip.endRun(run.id, {
1019
+ * status: 'FAILED',
1020
+ * errorMessage: 'Customer validation failed',
1021
+ * errorCode: 'VALIDATION_ERROR',
1022
+ * });
1023
+ * ```
1024
+ */
1025
+ endRun(runId: string, params: EndRunParams): Promise<{
1026
+ id: string;
1027
+ status: RunStatus;
1028
+ endedAt: string | null;
1029
+ durationMs: number | null;
1030
+ eventCount: number;
1031
+ totalCostUnits: string | null;
1032
+ }>;
1033
+ /**
1034
+ * Gets a run's full timeline with events and computed totals.
1035
+ *
1036
+ * This is the key endpoint for debugging "what happened" in an execution.
1037
+ *
1038
+ * @param runId - The run ID
1039
+ * @returns Full timeline with events and summary
1040
+ *
1041
+ * @example
1042
+ * ```typescript
1043
+ * const { run, timeline, totals, summary } = await drip.getRunTimeline('run_abc123');
1044
+ *
1045
+ * console.log(`Status: ${run.status}`);
1046
+ * console.log(`Summary: ${summary}`);
1047
+ * console.log(`Total cost: ${totals.totalCostUnits}`);
1048
+ *
1049
+ * for (const event of timeline) {
1050
+ * console.log(`${event.eventType}: ${event.quantity} ${event.units}`);
1051
+ * }
1052
+ * ```
1053
+ */
1054
+ getRunTimeline(runId: string): Promise<RunTimeline>;
1055
+ /**
1056
+ * Emits an event to a run.
1057
+ *
1058
+ * Events can be stored idempotently when an `idempotencyKey` is provided.
1059
+ * Use `Drip.generateIdempotencyKey()` for deterministic key generation.
1060
+ * If `idempotencyKey` is omitted, repeated calls may create duplicate events.
1061
+ *
1062
+ * @param params - Event parameters
1063
+ * @returns The created event
1064
+ *
1065
+ * @example
1066
+ * ```typescript
1067
+ * await drip.emitEvent({
1068
+ * runId: run.id,
1069
+ * eventType: 'agent.validate',
1070
+ * quantity: 1,
1071
+ * description: 'Validated prescription format',
1072
+ * costUnits: 0.001,
1073
+ * });
1074
+ * ```
1075
+ */
1076
+ emitEvent(params: EmitEventParams): Promise<EventResult>;
1077
+ /**
1078
+ * Emits multiple events in a single request.
1079
+ *
1080
+ * @param events - Array of events to emit
1081
+ * @returns Summary of created events
1082
+ *
1083
+ * @example
1084
+ * ```typescript
1085
+ * const result = await drip.emitEventsBatch([
1086
+ * { runId: run.id, eventType: 'agent.step1', quantity: 1 },
1087
+ * { runId: run.id, eventType: 'agent.step2', quantity: 100, units: 'tokens' },
1088
+ * ]);
1089
+ *
1090
+ * console.log(`Created: ${result.created}, Duplicates: ${result.duplicates}`);
1091
+ * ```
1092
+ */
1093
+ emitEventsBatch(events: Array<Omit<EmitEventParams, 'runId'> & {
1094
+ runId?: string;
1095
+ customerId?: string;
1096
+ workflowId?: string;
1097
+ }>): Promise<{
1098
+ success: boolean;
1099
+ created: number;
1100
+ duplicates: number;
1101
+ events: Array<{
1102
+ id: string;
1103
+ eventType: string;
1104
+ isDuplicate: boolean;
1105
+ }>;
1106
+ }>;
1107
+ /**
1108
+ * Lists all available meters (usage types) for your business.
1109
+ *
1110
+ * Use this to discover what meter names are valid for the `charge()` method.
1111
+ * Meters are defined by your pricing plans.
1112
+ *
1113
+ * @returns List of available meters with their prices
1114
+ *
1115
+ * @example
1116
+ * ```typescript
1117
+ * const { data: meters } = await drip.listMeters();
1118
+ *
1119
+ * console.log('Available meters:');
1120
+ * for (const meter of meters) {
1121
+ * console.log(` ${meter.meter}: $${meter.unitPriceUsd}/unit`);
1122
+ * }
1123
+ *
1124
+ * // Use in charge():
1125
+ * await drip.charge({
1126
+ * customerId: 'cust_123',
1127
+ * meter: meters[0].meter, // Use a valid meter name
1128
+ * quantity: 100,
1129
+ * });
1130
+ * ```
1131
+ */
1132
+ listMeters(): Promise<ListMetersResponse>;
1133
+ /**
1134
+ * Records a complete agent run in a single call.
1135
+ *
1136
+ * This is the **simplified API** that combines:
1137
+ * - Workflow creation (if needed)
1138
+ * - Run creation
1139
+ * - Event emission
1140
+ * - Run completion
1141
+ *
1142
+ * Use this instead of the individual `startRun()`, `emitEvent()`, `endRun()` calls
1143
+ * when you have all the run data available at once.
1144
+ *
1145
+ * @param params - Run parameters including events
1146
+ * @returns The created run with event summary
1147
+ *
1148
+ * @example
1149
+ * ```typescript
1150
+ * // Record a complete agent run in one call
1151
+ * const result = await drip.recordRun({
1152
+ * customerId: 'cust_123',
1153
+ * workflow: 'prescription_intake', // Auto-creates if doesn't exist
1154
+ * events: [
1155
+ * { eventType: 'agent.start', description: 'Started processing' },
1156
+ * { eventType: 'tool.ocr', quantity: 3, units: 'pages', costUnits: 0.15 },
1157
+ * { eventType: 'tool.validate', quantity: 1, costUnits: 0.05 },
1158
+ * { eventType: 'agent.complete', description: 'Finished successfully' },
1159
+ * ],
1160
+ * status: 'COMPLETED',
1161
+ * });
1162
+ *
1163
+ * console.log(`Run ${result.run.id}: ${result.summary}`);
1164
+ * console.log(`Events: ${result.events.created} created`);
1165
+ * ```
1166
+ *
1167
+ * @example
1168
+ * ```typescript
1169
+ * // Record a failed run with error details
1170
+ * const result = await drip.recordRun({
1171
+ * customerId: 'cust_123',
1172
+ * workflow: 'prescription_intake',
1173
+ * events: [
1174
+ * { eventType: 'agent.start', description: 'Started processing' },
1175
+ * { eventType: 'tool.ocr', quantity: 1, units: 'pages' },
1176
+ * { eventType: 'error', description: 'OCR failed: image too blurry' },
1177
+ * ],
1178
+ * status: 'FAILED',
1179
+ * errorMessage: 'OCR processing failed',
1180
+ * errorCode: 'OCR_QUALITY_ERROR',
1181
+ * });
1182
+ * ```
1183
+ */
1184
+ recordRun(params: RecordRunParams): Promise<RecordRunResult>;
1185
+ /**
1186
+ * Generates a deterministic idempotency key.
1187
+ *
1188
+ * Use this to ensure "one logical action = one event" even with retries.
1189
+ * The key is generated from customerId + runId + stepName + sequence.
1190
+ *
1191
+ * @param params - Key generation parameters
1192
+ * @returns A deterministic idempotency key
1193
+ *
1194
+ * @example
1195
+ * ```typescript
1196
+ * const key = Drip.generateIdempotencyKey({
1197
+ * customerId: 'cust_123',
1198
+ * runId: 'run_456',
1199
+ * stepName: 'validate_prescription',
1200
+ * sequence: 1,
1201
+ * });
1202
+ *
1203
+ * await drip.emitEvent({
1204
+ * runId: 'run_456',
1205
+ * eventType: 'agent.validate',
1206
+ * idempotencyKey: key,
1207
+ * });
1208
+ * ```
1209
+ */
1210
+ static generateIdempotencyKey(params: {
1211
+ customerId: string;
1212
+ runId?: string;
1213
+ stepName: string;
1214
+ sequence?: number;
1215
+ }): string;
1216
+ /**
1217
+ * Verifies a webhook signature.
1218
+ *
1219
+ * Call this when receiving webhook events to ensure they're authentic.
1220
+ *
1221
+ * @param payload - The raw request body (string)
1222
+ * @param signature - The x-drip-signature header value
1223
+ * @param secret - Your webhook secret
1224
+ * @returns Whether the signature is valid
1225
+ *
1226
+ * @example
1227
+ * ```typescript
1228
+ * app.post('/webhooks/drip', (req, res) => {
1229
+ * const isValid = Drip.verifyWebhookSignature(
1230
+ * req.rawBody,
1231
+ * req.headers['x-drip-signature'],
1232
+ * process.env.DRIP_WEBHOOK_SECRET!,
1233
+ * );
1234
+ *
1235
+ * if (!isValid) {
1236
+ * return res.status(401).send('Invalid signature');
1237
+ * }
1238
+ *
1239
+ * // Process the webhook...
1240
+ * });
1241
+ * ```
1242
+ */
1243
+ static verifyWebhookSignature(payload: string, signature: string, secret: string): boolean;
1244
+ }
1245
+
1246
+ export { type BalanceResult, type Charge, type ChargeParams, type ChargeResult, type ChargeStatus, type CheckoutParams, type CheckoutResult, type CreateCustomerParams, type CreateWebhookParams, type CreateWebhookResponse, type CreateWorkflowParams, type Customer, type DeleteWebhookResponse, Drip, type DripConfig, DripError, type EmitEventParams, type EndRunParams, type EventResult, type ListChargesOptions, type ListChargesResponse, type ListCustomersOptions, type ListCustomersResponse, type ListMetersResponse, type ListWebhooksResponse, type Meter, type RecordRunEvent, type RecordRunParams, type RecordRunResult, type RunResult, type RunStatus, type RunTimeline, type StartRunParams, type Webhook, type WebhookEventType, type Workflow, Drip as default };