@naturalpay/sdk 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,676 @@
1
+ /**
2
+ * HTTP client for Natural Server API with JWT caching.
3
+ */
4
+ interface HTTPClientOptions {
5
+ apiKey?: string;
6
+ baseUrl?: string;
7
+ timeout?: number;
8
+ }
9
+ interface RequestOptions {
10
+ body?: Record<string, unknown>;
11
+ params?: Record<string, unknown>;
12
+ headers?: Record<string, string>;
13
+ }
14
+ declare class HTTPClient {
15
+ private readonly apiKey;
16
+ private readonly baseUrl;
17
+ private readonly timeout;
18
+ private readonly jwtCache;
19
+ constructor(options?: HTTPClientOptions);
20
+ /**
21
+ * Get a cached JWT or exchange API key for a new one.
22
+ */
23
+ private getJwt;
24
+ /**
25
+ * Build URL with query parameters.
26
+ */
27
+ private buildUrl;
28
+ /**
29
+ * Handle API response and throw appropriate errors.
30
+ */
31
+ private handleResponse;
32
+ /**
33
+ * Make an authenticated request.
34
+ */
35
+ request<T>(method: string, path: string, options?: RequestOptions): Promise<T>;
36
+ get<T>(path: string, options?: Omit<RequestOptions, 'body'>): Promise<T>;
37
+ post<T>(path: string, options?: RequestOptions): Promise<T>;
38
+ put<T>(path: string, options?: RequestOptions): Promise<T>;
39
+ delete<T>(path: string, options?: RequestOptions): Promise<T>;
40
+ }
41
+
42
+ /**
43
+ * Base resource class.
44
+ */
45
+
46
+ declare abstract class BaseResource {
47
+ protected readonly http: HTTPClient;
48
+ constructor(http: HTTPClient);
49
+ }
50
+
51
+ /**
52
+ * Payment types.
53
+ */
54
+ interface PaymentCreateParams {
55
+ /** Agent ID (agt_xxx) for agent-initiated payments. */
56
+ agentId?: string;
57
+ /** Payment amount in minor units (cents). 5000 = $50.00. */
58
+ amount: number;
59
+ customerPartyId: string;
60
+ /** Recipient email, phone number, or party ID (pty_xxx). */
61
+ recipient: string;
62
+ /** Payment memo/description. */
63
+ memo: string;
64
+ /** Currency code (default: USD). */
65
+ currency?: string;
66
+ idempotencyKey: string;
67
+ /** Developer's session/conversation ID for observability grouping. */
68
+ instanceId?: string;
69
+ }
70
+
71
+ /**
72
+ * Transaction types.
73
+ */
74
+ /**
75
+ * Filter for transaction types in list operations.
76
+ */
77
+ declare enum TransactionTypeFilter {
78
+ PAYMENT = "payment",
79
+ TRANSFER = "transfer",
80
+ ALL = "all"
81
+ }
82
+ interface Transaction {
83
+ transactionId: string;
84
+ amount: number;
85
+ currency: string;
86
+ status: string;
87
+ description?: string;
88
+ memo?: string;
89
+ createdAt: string;
90
+ updatedAt?: string;
91
+ isDelegated: boolean;
92
+ customerName?: string;
93
+ customerAgentId?: string;
94
+ senderName?: string;
95
+ recipientName?: string;
96
+ transactionType: string;
97
+ category: string;
98
+ direction: string;
99
+ sourcePartyId?: string;
100
+ destinationPartyId?: string;
101
+ sourceWalletId?: string;
102
+ destinationWalletId?: string;
103
+ /** Internal instance ID (ins_xxx) assigned by server. */
104
+ instanceId?: string;
105
+ /** Claim link URL for unclaimed payments. */
106
+ claimLink?: string;
107
+ }
108
+ interface TransactionGetParams {
109
+ /** Customer party ID (pty_xxx) for delegated transaction lookup. */
110
+ customerPartyId?: string;
111
+ /** Developer's session/conversation ID for observability grouping. */
112
+ instanceId?: string;
113
+ }
114
+ interface TransactionListParams {
115
+ limit?: number;
116
+ cursor?: string;
117
+ agentId?: string;
118
+ /** Filter by transaction type (payment, transfer, or all) */
119
+ type?: TransactionTypeFilter;
120
+ /** Developer's session/conversation ID for observability grouping. */
121
+ instanceId?: string;
122
+ }
123
+ interface TransactionListResponse {
124
+ transactions: Transaction[];
125
+ hasMore: boolean;
126
+ nextCursor?: string | null;
127
+ }
128
+
129
+ /**
130
+ * Payments resource.
131
+ */
132
+
133
+ declare class PaymentsResource extends BaseResource {
134
+ /**
135
+ * Create a payment.
136
+ *
137
+ * @param params - Payment creation parameters
138
+ * @returns Transaction object with transaction_id (txn_*), status, etc.
139
+ */
140
+ create(params: PaymentCreateParams): Promise<Transaction>;
141
+ }
142
+
143
+ /**
144
+ * Wallet types.
145
+ */
146
+ interface AmountInfo {
147
+ amountMinor: number;
148
+ }
149
+ interface BalanceBreakdown {
150
+ operatingFunded: AmountInfo;
151
+ operatingAdvanced: AmountInfo;
152
+ escrowFundedSettled: AmountInfo;
153
+ escrowAdvanced: AmountInfo;
154
+ holdsOutbound: AmountInfo;
155
+ }
156
+ interface AccountBalance {
157
+ walletId: string;
158
+ breakdown: BalanceBreakdown;
159
+ available: AmountInfo;
160
+ pendingClaimAmountMinor?: number;
161
+ pendingClaimCount?: number;
162
+ }
163
+ interface BalanceOptions {
164
+ /** Customer party ID (pty_xxx) when acting on behalf of customer. */
165
+ customerPartyId?: string;
166
+ /** Developer's session/conversation ID for observability grouping. */
167
+ instanceId?: string;
168
+ }
169
+ interface WithdrawParams {
170
+ /** Withdrawal amount in minor units (cents). 5000 = $50.00. */
171
+ amount: number;
172
+ /** ID of the linked bank account (efs_xxx). */
173
+ externalFundingSourceId: string;
174
+ currency?: string;
175
+ description?: string;
176
+ idempotencyKey: string;
177
+ }
178
+ interface WithdrawResponse {
179
+ transferId?: string;
180
+ instructionId?: string;
181
+ status: string;
182
+ amount: number;
183
+ currency: string;
184
+ estimatedSettlement?: string;
185
+ kycRequired: boolean;
186
+ kycStatus?: string;
187
+ kycSessionUrl?: string;
188
+ mfaRequired: boolean;
189
+ mfaChallengeId?: string;
190
+ mfaExpiresAt?: string;
191
+ error?: string;
192
+ errorDetails?: string;
193
+ }
194
+
195
+ /**
196
+ * Wallet resource.
197
+ */
198
+
199
+ declare class WalletResource extends BaseResource {
200
+ /**
201
+ * Get current wallet balance.
202
+ *
203
+ * @returns AccountBalance with available, current, pending amounts
204
+ */
205
+ balance(options?: BalanceOptions): Promise<AccountBalance>;
206
+ /**
207
+ * Initiate a withdrawal to a linked bank account.
208
+ *
209
+ * @param params - Withdrawal parameters
210
+ * @returns WithdrawResponse with transfer status (may require KYC/MFA)
211
+ */
212
+ withdraw(params: WithdrawParams): Promise<WithdrawResponse>;
213
+ }
214
+
215
+ /**
216
+ * Transactions resource.
217
+ */
218
+
219
+ declare class TransactionsResource extends BaseResource {
220
+ /**
221
+ * Get a transaction by ID.
222
+ *
223
+ * @param transactionId - Transaction ID (txn_xxx)
224
+ * @param params - Optional parameters for observability
225
+ * @returns Transaction details
226
+ */
227
+ get(transactionId: string, params?: TransactionGetParams): Promise<Transaction>;
228
+ /**
229
+ * List recent transactions.
230
+ *
231
+ * @param params - List parameters including agent context
232
+ * @returns TransactionListResponse with transactions and pagination info
233
+ */
234
+ list(params?: TransactionListParams): Promise<TransactionListResponse>;
235
+ }
236
+
237
+ /**
238
+ * Agent types.
239
+ */
240
+ type AgentStatus = 'ACTIVE' | 'REVOKED';
241
+ interface TransactionLimits {
242
+ perTransaction?: number;
243
+ }
244
+ interface Agent {
245
+ id: string;
246
+ name: string;
247
+ description?: string;
248
+ status: AgentStatus;
249
+ partyId: string;
250
+ createdAt?: string;
251
+ createdBy?: string;
252
+ updatedAt?: string;
253
+ updatedBy?: string;
254
+ }
255
+ interface AgentCreateParams {
256
+ name: string;
257
+ description?: string;
258
+ limits?: TransactionLimits;
259
+ idempotencyKey?: string;
260
+ /** Developer's session/conversation ID for observability grouping. */
261
+ instanceId?: string;
262
+ }
263
+ /** @deprecated Use Agent instead — server returns full resource for all operations. */
264
+ type AgentCreateResponse = Agent;
265
+ interface AgentUpdateParams {
266
+ name?: string;
267
+ description?: string;
268
+ status?: AgentStatus;
269
+ idempotencyKey?: string;
270
+ /** Developer's session/conversation ID for observability grouping. */
271
+ instanceId?: string;
272
+ }
273
+ /** @deprecated Use Agent instead — server returns full resource for all operations. */
274
+ type AgentUpdateResponse = Agent;
275
+ interface AgentListParams {
276
+ status?: AgentStatus;
277
+ limit?: number;
278
+ cursor?: string;
279
+ /** Developer's session/conversation ID for observability grouping. */
280
+ instanceId?: string;
281
+ }
282
+ interface AgentGetOptions {
283
+ /** Developer's session/conversation ID for observability grouping. */
284
+ instanceId?: string;
285
+ }
286
+ interface AgentDeleteOptions {
287
+ /** Developer's session/conversation ID for observability grouping. */
288
+ instanceId?: string;
289
+ }
290
+ interface AgentListResponse {
291
+ agents: Agent[];
292
+ hasMore: boolean;
293
+ nextCursor?: string | null;
294
+ }
295
+
296
+ /**
297
+ * Agents resource.
298
+ */
299
+
300
+ declare class AgentsResource extends BaseResource {
301
+ /**
302
+ * List agents for the partner.
303
+ *
304
+ * @param params - Filter and pagination parameters
305
+ * @returns AgentListResponse with list of agents
306
+ */
307
+ list(params?: AgentListParams): Promise<AgentListResponse>;
308
+ /**
309
+ * Get agent by ID.
310
+ *
311
+ * @param agentId - The agent ID to retrieve (agt_xxx)
312
+ * @returns Agent details
313
+ */
314
+ get(agentId: string, options?: AgentGetOptions): Promise<Agent>;
315
+ /**
316
+ * Create a new agent.
317
+ *
318
+ * @param params - Agent creation parameters
319
+ * @returns AgentCreateResponse with created agent details
320
+ */
321
+ create(params: AgentCreateParams): Promise<AgentCreateResponse>;
322
+ /**
323
+ * Update an existing agent.
324
+ *
325
+ * @param agentId - The agent ID to update (agt_xxx)
326
+ * @param params - Update parameters
327
+ * @returns AgentUpdateResponse with updated agent details
328
+ */
329
+ update(agentId: string, params: AgentUpdateParams): Promise<AgentUpdateResponse>;
330
+ /**
331
+ * Delete an agent.
332
+ *
333
+ * @param agentId - The agent ID to delete (agt_xxx)
334
+ * @param options - Optional observability parameters
335
+ */
336
+ delete(agentId: string, options?: AgentDeleteOptions): Promise<void>;
337
+ }
338
+
339
+ /**
340
+ * Agent delegation types.
341
+ */
342
+ interface AgentDelegation {
343
+ id: string;
344
+ agentName?: string;
345
+ agentId: string;
346
+ delegationId: string;
347
+ delegatorPartyId?: string;
348
+ delegateePartyId?: string;
349
+ delegatorPartyName?: string;
350
+ delegateePartyName?: string;
351
+ permissions: string[];
352
+ limits?: Record<string, number>;
353
+ expiresAt?: string;
354
+ createdAt: string;
355
+ createdBy?: string;
356
+ updatedAt: string;
357
+ }
358
+ interface AgentDelegationListParams {
359
+ delegationId?: string;
360
+ agentId?: string;
361
+ delegatorPartyId?: string;
362
+ delegateePartyId?: string;
363
+ includeRevoked?: boolean;
364
+ limit?: number;
365
+ cursor?: string;
366
+ /** Developer's session/conversation ID for observability grouping. */
367
+ instanceId?: string;
368
+ }
369
+ interface AgentDelegationListResponse {
370
+ agentDelegations: AgentDelegation[];
371
+ hasMore: boolean;
372
+ nextCursor?: string | null;
373
+ }
374
+
375
+ /**
376
+ * Agent delegations resource.
377
+ */
378
+
379
+ declare class DelegationsResource extends BaseResource {
380
+ /**
381
+ * List agent delegations with optional filters.
382
+ *
383
+ * @param params - Filter parameters
384
+ * @returns AgentDelegationListResponse with list of agent delegations
385
+ */
386
+ list(params?: AgentDelegationListParams): Promise<AgentDelegationListResponse>;
387
+ /**
388
+ * Get agent delegation by ID.
389
+ *
390
+ * @param agentDelegationId - The agent delegation handle (adl_xxx)
391
+ * @returns AgentDelegation details
392
+ */
393
+ get(agentDelegationId: string): Promise<AgentDelegation>;
394
+ }
395
+
396
+ /**
397
+ * Customer types.
398
+ */
399
+ interface CustomerPartyInfo {
400
+ id: string;
401
+ name: string;
402
+ email?: string;
403
+ }
404
+ interface Customer {
405
+ id: string;
406
+ type: 'party' | 'delegationInvitation';
407
+ party?: CustomerPartyInfo;
408
+ email?: string;
409
+ status: string;
410
+ permissions: string[];
411
+ createdAt: string;
412
+ walletAvailableMinor?: number;
413
+ walletAvailableDollars?: string;
414
+ walletAccess: 'granted' | 'denied' | 'noWallet';
415
+ }
416
+ interface CustomerListParams {
417
+ limit?: number;
418
+ cursor?: string;
419
+ /** Developer's session/conversation ID for observability grouping. */
420
+ instanceId?: string;
421
+ }
422
+ interface CustomerListResponse {
423
+ items: Customer[];
424
+ hasMore: boolean;
425
+ nextCursor?: string | null;
426
+ }
427
+
428
+ /**
429
+ * Customers resource.
430
+ */
431
+
432
+ declare class CustomersResource extends BaseResource {
433
+ /**
434
+ * List customers who have delegated access to the partner.
435
+ *
436
+ * @param params - Pagination parameters
437
+ * @returns CustomerListResponse with items, hasMore, nextCursor
438
+ */
439
+ list(params?: CustomerListParams): Promise<CustomerListResponse>;
440
+ }
441
+
442
+ /**
443
+ * Natural Payments SDK client.
444
+ */
445
+
446
+ interface NaturalClientOptions extends HTTPClientOptions {
447
+ }
448
+ /**
449
+ * Natural Payments SDK client.
450
+ *
451
+ * @example
452
+ * ```typescript
453
+ * import { NaturalClient } from 'naturalpay';
454
+ *
455
+ * const client = new NaturalClient({ apiKey: 'sk_ntl_sandbox_xxx' });
456
+ *
457
+ * // Create a payment
458
+ * const payment = await client.payments.create({
459
+ * agentId: 'agt_xxx',
460
+ * amount: 5000,
461
+ * customerPartyId: 'pty_xxx',
462
+ * recipient: 'alice@example.com',
463
+ * memo: 'For consulting',
464
+ * idempotencyKey: 'unique-key-for-this-payment',
465
+ * });
466
+ *
467
+ * // Check balance
468
+ * const balance = await client.wallet.balance();
469
+ * ```
470
+ */
471
+ declare class NaturalClient {
472
+ private readonly http;
473
+ /** Payments API resource. */
474
+ readonly payments: PaymentsResource;
475
+ /** Wallet API resource for balance and withdrawals. */
476
+ readonly wallet: WalletResource;
477
+ /** Transactions API resource. */
478
+ readonly transactions: TransactionsResource;
479
+ /** Agents API resource for managing agents. */
480
+ readonly agents: AgentsResource;
481
+ /** Agent delegations API resource. */
482
+ readonly delegations: DelegationsResource;
483
+ /** Customers API resource for listing parties who delegated access. */
484
+ readonly customers: CustomersResource;
485
+ /**
486
+ * Initialize the Natural client.
487
+ *
488
+ * @param options - Client configuration options
489
+ * @param options.apiKey - API key (defaults to NATURAL_API_KEY env var)
490
+ * @param options.baseUrl - API base URL (defaults to https://api.natural.co)
491
+ * @param options.timeout - Request timeout in milliseconds (default: 30000)
492
+ */
493
+ constructor(options?: NaturalClientOptions);
494
+ }
495
+
496
+ /**
497
+ * Structured logging for Natural Payments SDK.
498
+ *
499
+ * Supports two modes:
500
+ * 1. Plain text logging (default, for local development)
501
+ * 2. JSON logging with Datadog correlation (when NATURAL_LOG_FORMAT=json)
502
+ *
503
+ * Features:
504
+ * - Source info: file, line, function on every log (for error grouping)
505
+ * - Context binding for request_id, agent_id, instance_id
506
+ * - Datadog trace correlation fields
507
+ * - AsyncLocalStorage for proper async context isolation
508
+ */
509
+ type LogLevel = 'debug' | 'info' | 'warning' | 'error';
510
+ /**
511
+ * Get the current logging context.
512
+ * Uses AsyncLocalStorage if available, falls back to global context.
513
+ */
514
+ declare function getContext(): Record<string, unknown>;
515
+ /**
516
+ * Bind additional context to current scope (e.g., request_id, agent_id).
517
+ *
518
+ * Values are sanitized to prevent log injection attacks.
519
+ * Updates both AsyncLocalStorage (if active) and global context.
520
+ *
521
+ * @example
522
+ * bindContext({ requestId: 'req_123', agentId: 'agt_456' });
523
+ * logger.info('Processing payment'); // Will include requestId and agentId
524
+ */
525
+ declare function bindContext(context: Record<string, unknown>): void;
526
+ /**
527
+ * Clear all bound context.
528
+ */
529
+ declare function clearContext(): void;
530
+ /**
531
+ * Run a function with isolated logging context.
532
+ *
533
+ * Context bound within the callback is isolated from other async operations.
534
+ * This is the recommended way to set context for request handling.
535
+ *
536
+ * @example
537
+ * await runWithContext({ requestId: 'req_123' }, async () => {
538
+ * logger.info('Processing request'); // Includes requestId
539
+ * await doAsyncWork();
540
+ * logger.info('Request complete'); // Still includes requestId
541
+ * });
542
+ */
543
+ declare function runWithContext<T>(context: Record<string, unknown>, fn: () => T | Promise<T>): T | Promise<T>;
544
+ /**
545
+ * Configure logging for the Natural SDK.
546
+ *
547
+ * @param options - Logging configuration options
548
+ * @param options.level - Log level (debug, info, warning, error)
549
+ * @param options.jsonFormat - Use JSON format (default: auto-detect from NATURAL_LOG_FORMAT env var)
550
+ * @param options.serviceName - Service name for structured logs
551
+ *
552
+ * Environment variables:
553
+ * - NATURAL_LOG_LEVEL: Override log level (DEBUG, INFO, WARNING, ERROR)
554
+ * - NATURAL_LOG_FORMAT: Set to "json" for JSON output, "text" for plain text
555
+ */
556
+ declare function configureLogging(options?: {
557
+ level?: LogLevel;
558
+ jsonFormat?: boolean;
559
+ serviceName?: string;
560
+ }): void;
561
+ /**
562
+ * Logger instance for a specific module/context.
563
+ */
564
+ declare class Logger {
565
+ private readonly name;
566
+ constructor(name: string);
567
+ private log;
568
+ debug(message: string, extra?: Record<string, unknown>): void;
569
+ info(message: string, extra?: Record<string, unknown>): void;
570
+ warning(message: string, extra?: Record<string, unknown>): void;
571
+ warn(message: string, extra?: Record<string, unknown>): void;
572
+ error(message: string, extra?: Record<string, unknown>): void;
573
+ }
574
+ /**
575
+ * Get a logger for the given module name.
576
+ *
577
+ * @param name - Module name (e.g., 'naturalpay.http')
578
+ * @returns Logger instance
579
+ *
580
+ * @example
581
+ * const logger = getLogger('naturalpay.payments');
582
+ * logger.info('Payment initiated', { amount: 10000 });
583
+ */
584
+ declare function getLogger(name: string): Logger;
585
+ /**
586
+ * Log an error with full context and exception info.
587
+ */
588
+ declare function logError(logger: Logger, message: string, options?: {
589
+ error?: Error;
590
+ statusCode?: number;
591
+ code?: string;
592
+ [key: string]: unknown;
593
+ }): void;
594
+ /**
595
+ * Log an API call with standard fields.
596
+ */
597
+ declare function logApiCall(logger: Logger, method: string, path: string, options?: {
598
+ statusCode?: number;
599
+ durationMs?: number;
600
+ error?: Error;
601
+ [key: string]: unknown;
602
+ }): void;
603
+ /**
604
+ * Log an MCP tool invocation.
605
+ */
606
+ declare function logToolCall(logger: Logger, toolName: string, options?: {
607
+ success?: boolean;
608
+ durationMs?: number;
609
+ error?: Error;
610
+ [key: string]: unknown;
611
+ }): void;
612
+
613
+ /**
614
+ * Natural Payments SDK error classes.
615
+ */
616
+ /**
617
+ * Base error for all Natural SDK errors.
618
+ */
619
+ declare class NaturalError extends Error {
620
+ readonly statusCode?: number;
621
+ readonly code?: string;
622
+ constructor(message: string, options?: {
623
+ statusCode?: number;
624
+ code?: string;
625
+ });
626
+ }
627
+ /**
628
+ * Invalid or missing API key.
629
+ */
630
+ declare class AuthenticationError extends NaturalError {
631
+ constructor(message?: string);
632
+ }
633
+ /**
634
+ * Malformed request parameters.
635
+ */
636
+ declare class InvalidRequestError extends NaturalError {
637
+ constructor(message: string, code?: string);
638
+ }
639
+ /**
640
+ * Payment-specific failure.
641
+ */
642
+ declare class PaymentError extends NaturalError {
643
+ constructor(message: string, code?: string);
644
+ }
645
+ /**
646
+ * Not enough balance for payment.
647
+ */
648
+ declare class InsufficientFundsError extends PaymentError {
649
+ constructor(message?: string);
650
+ }
651
+ /**
652
+ * Invalid recipient.
653
+ */
654
+ declare class RecipientNotFoundError extends PaymentError {
655
+ constructor(message?: string);
656
+ }
657
+ /**
658
+ * Too many requests.
659
+ */
660
+ declare class RateLimitError extends NaturalError {
661
+ readonly retryAfter?: number;
662
+ constructor(message?: string, retryAfter?: number);
663
+ }
664
+ /**
665
+ * Internal server error.
666
+ */
667
+ declare class ServerError extends NaturalError {
668
+ constructor(message?: string);
669
+ }
670
+
671
+ /**
672
+ * Single source of truth for the SDK version string.
673
+ */
674
+ declare const VERSION = "0.1.1";
675
+
676
+ export { type AccountBalance, type Agent, type AgentCreateParams, type AgentCreateResponse, type AgentDelegation, type AgentDelegationListParams, type AgentDelegationListResponse, type AgentDeleteOptions, type AgentGetOptions, type AgentListParams, type AgentListResponse, type AgentStatus, type AgentUpdateParams, type AgentUpdateResponse, type AmountInfo, AuthenticationError, type BalanceBreakdown, type Customer, type CustomerListParams, type CustomerListResponse, type CustomerPartyInfo, InsufficientFundsError, InvalidRequestError, type LogLevel, Logger, NaturalClient, type NaturalClientOptions, NaturalError, type PaymentCreateParams, PaymentError, RateLimitError, RecipientNotFoundError, ServerError, type Transaction, type TransactionGetParams, type TransactionListParams, type TransactionListResponse, TransactionTypeFilter, VERSION, type WithdrawParams, type WithdrawResponse, bindContext, clearContext, configureLogging, getContext, getLogger, logApiCall, logError, logToolCall, runWithContext };