@naturalpay/sdk 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,260 +1,52 @@
1
- # Natural Payments TypeScript SDK
1
+ # Natural Payments SDK
2
2
 
3
- Official TypeScript/Node.js SDK for Natural Payments - AI agent payment infrastructure.
3
+ [![NPM version](https://img.shields.io/npm/v/@naturalpay/sdk.svg)](https://npmjs.org/package/@naturalpay/sdk)
4
+
5
+ The Natural Payments SDK provides access to the [Natural API](https://docs.natural.co) from server-side TypeScript and JavaScript applications, for building AI agents that send, receive, and manage money.
6
+
7
+ ## Documentation
8
+
9
+ Full documentation, guides, and API reference are available at **[docs.natural.co/guides/platform/sdks](https://docs.natural.co/guides/platform/sdks)**.
4
10
 
5
11
  ## Installation
6
12
 
7
- ```bash
13
+ ```sh
8
14
  npm install @naturalpay/sdk
9
- # or
10
- pnpm add @naturalpay/sdk
11
- # or
12
- yarn add @naturalpay/sdk
13
15
  ```
14
16
 
15
- ## Quick Start
17
+ ## Getting started
16
18
 
17
19
  ```typescript
18
20
  import { NaturalClient } from '@naturalpay/sdk';
19
21
 
20
- const client = new NaturalClient({
21
- apiKey: process.env.NATURAL_API_KEY, // or pass directly
22
- });
22
+ const client = new NaturalClient({ apiKey: process.env['NATURAL_API_KEY'] });
23
23
 
24
- // Create a payment
25
24
  const payment = await client.payments.create({
26
- agentId: 'agent_123',
27
- instanceId: 'instance_456',
28
- amount: 5000,
29
- customerPartyId: 'party_456',
30
25
  recipient: 'alice@example.com',
26
+ amount: 5000,
31
27
  memo: 'Payment for consulting',
32
- idempotencyKey: 'unique-key-for-this-payment',
28
+ agentId: 'agt_019cd1798d637a4da75dce386343931d',
29
+ instanceId: 'session-abc123',
30
+ customerPartyId: 'pty_019cd34e27c179bfbbe6870486b11b67',
31
+ idempotencyKey: 'pay_unique_key',
33
32
  });
34
33
 
35
- console.log(`Payment created: ${payment.transactionId}`);
36
-
37
- // Check balance
38
- const balance = await client.wallet.balance();
39
- console.log(`Available: ${balance.available.amountMinor} minor units`);
40
- ```
41
-
42
- ## Configuration
43
-
44
- ### Environment Variables
45
-
46
- - `NATURAL_API_KEY` - Your API key (starts with `sk_ntl_sandbox_` or `sk_ntl_live_`)
47
- - `NATURAL_SERVER_URL` - API base URL (default: `https://api.natural.co`)
48
-
49
- ### Client Options
50
-
51
- ```typescript
52
- const client = new NaturalClient({
53
- apiKey: 'sk_ntl_sandbox_xxx', // API key
54
- baseUrl: 'https://api.natural.co', // Custom base URL
55
- timeout: 30000, // Request timeout in ms
56
- });
34
+ console.log(payment.transactionId);
57
35
  ```
58
36
 
59
- ## Resources
37
+ ## MCP server
60
38
 
61
- ### Payments
62
-
63
- ```typescript
64
- // Create a payment
65
- const payment = await client.payments.create({
66
- agentId: 'agent_123',
67
- instanceId: 'instance_789', // required when agentId is provided
68
- amount: 10000,
69
- customerPartyId: 'party_456',
70
- recipient: 'alice@example.com', // email, phone, or party ID (pty_xxx)
71
- memo: 'Payment description',
72
- idempotencyKey: 'unique-key-for-this-payment',
73
- });
74
- ```
39
+ The SDK ships with an MCP server for AI agent integration with Claude Desktop, Cursor, and other MCP clients:
75
40
 
76
- ### Wallet
77
-
78
- ```typescript
79
- // Get account balance
80
- const balance = await client.wallet.balance();
81
-
82
- // Withdraw funds
83
- const withdrawal = await client.wallet.withdraw({
84
- amount: 50000,
85
- externalFundingSourceId: 'efs_xxx',
86
- idempotencyKey: 'wd_unique_key',
87
- });
88
- ```
89
-
90
- ### Transactions
91
-
92
- ```typescript
93
- import { TransactionTypeFilter } from '@naturalpay/sdk';
94
-
95
- // List all transactions
96
- const transactions = await client.transactions.list({
97
- limit: 100,
98
- agentId: 'agent_123',
99
- instanceId: 'instance_789', // required when agentId is provided
100
- });
101
-
102
- // List only transfers
103
- const transfers = await client.transactions.list({
104
- type: TransactionTypeFilter.TRANSFER,
105
- });
106
-
107
- // List only payments
108
- const payments = await client.transactions.list({
109
- type: TransactionTypeFilter.PAYMENT,
110
- });
111
- ```
112
-
113
- ### Agents
114
-
115
- ```typescript
116
- // List agents
117
- const agents = await client.agents.list({
118
- status: 'ACTIVE',
119
- limit: 50,
120
- });
121
-
122
- // Create an agent
123
- const agent = await client.agents.create({
124
- name: 'Shopping Assistant',
125
- partyId: 'party_123',
126
- description: 'Handles shopping tasks',
127
- });
128
-
129
- // Update an agent
130
- const updated = await client.agents.update('agent_id', {
131
- name: 'Updated Name',
132
- status: 'REVOKED',
133
- });
134
-
135
- // Delete an agent
136
- await client.agents.delete('agent_id');
137
- ```
138
-
139
- ### Delegations
140
-
141
- ```typescript
142
- // List agent delegations
143
- const delegations = await client.delegations.list({
144
- limit: 50,
145
- });
146
-
147
- // Get delegation details
148
- const delegation = await client.delegations.get('adl_xxx');
149
- ```
150
-
151
- ### Customers
152
-
153
- ```typescript
154
- // List customers who have delegated to you
155
- const customers = await client.customers.list({
156
- limit: 50,
157
- });
158
- ```
159
-
160
- ## MCP Server
161
-
162
- The SDK includes an MCP (Model Context Protocol) server for AI agent integration.
163
-
164
- ### CLI Usage
165
-
166
- Use `npx` to run the CLI without global installation:
167
-
168
- ```bash
169
- # Show help
170
- npx @naturalpay/sdk --help
171
-
172
- # Start MCP server with stdio transport
41
+ ```sh
173
42
  npx @naturalpay/sdk mcp serve
174
-
175
- # With explicit options
176
- npx @naturalpay/sdk mcp serve --api-key sk_ntl_sandbox_xxx --mcp-url https://mcp.natural.co
177
43
  ```
178
44
 
179
- > **Note:** We recommend `npx` over global installation to avoid conflicts if you also use the Python SDK (`uvx naturalpay` or `python -m naturalpay`).
180
-
181
- ### Claude Desktop / Cursor Config
182
-
183
- ```json
184
- {
185
- "mcpServers": {
186
- "natural": {
187
- "command": "npx",
188
- "args": ["@naturalpay/sdk", "mcp", "serve"],
189
- "env": { "NATURAL_API_KEY": "sk_ntl_..." }
190
- }
191
- }
192
- }
193
- ```
194
-
195
- ### Available MCP Tools
196
-
197
- | Tool | Description |
198
- |------|-------------|
199
- | `create_payment` | Create a payment to a recipient |
200
- | `get_payment_status` | Check payment status by transfer ID |
201
- | `get_account_balance` | Get current wallet balance |
202
- | `list_transactions` | List recent transactions |
203
- | `list_agents` | List agents for the partner |
204
- | `list_customers` | List customers who delegated to you |
45
+ See [docs.natural.co/guides/platform/sdks#mcp-server](https://docs.natural.co/guides/platform/sdks#mcp-server) for client configuration.
205
46
 
206
- ## Error Handling
47
+ ## Requirements
207
48
 
208
- ```typescript
209
- import {
210
- NaturalError,
211
- AuthenticationError,
212
- InvalidRequestError,
213
- PaymentError,
214
- InsufficientFundsError,
215
- RecipientNotFoundError,
216
- RateLimitError,
217
- ServerError,
218
- } from '@naturalpay/sdk';
219
-
220
- try {
221
- await client.payments.create({ ... });
222
- } catch (error) {
223
- if (error instanceof AuthenticationError) {
224
- // Handle authentication issues (401)
225
- } else if (error instanceof InsufficientFundsError) {
226
- // Handle insufficient balance
227
- } else if (error instanceof RecipientNotFoundError) {
228
- // Handle invalid recipient
229
- } else if (error instanceof RateLimitError) {
230
- // Handle rate limiting (429)
231
- console.log(`Retry after: ${error.retryAfter}s`);
232
- } else if (error instanceof ServerError) {
233
- // Handle server errors (5xx)
234
- } else if (error instanceof NaturalError) {
235
- // Handle other API errors
236
- console.log(`Error: ${error.message}, Code: ${error.code}`);
237
- }
238
- }
239
- ```
240
-
241
- ## TypeScript Support
242
-
243
- This SDK is written in TypeScript and provides full type definitions:
244
-
245
- ```typescript
246
- import type {
247
- PaymentCreateParams,
248
- AccountBalance,
249
- Transaction,
250
- TransactionListResponse,
251
- Agent,
252
- AgentDelegation,
253
- WithdrawResponse,
254
- } from '@naturalpay/sdk';
255
-
256
- import { TransactionTypeFilter } from '@naturalpay/sdk';
257
- ```
49
+ Node.js 18+
258
50
 
259
51
  ## License
260
52
 
package/dist/index.cjs CHANGED
@@ -62,7 +62,7 @@ var ServerError = class extends NaturalError {
62
62
  };
63
63
 
64
64
  // src/version.ts
65
- var VERSION = "0.1.1";
65
+ var VERSION = "0.1.3";
66
66
 
67
67
  // src/logging.ts
68
68
  var LOG_LEVEL_VALUES = {
@@ -312,6 +312,39 @@ function getToolCallHeader() {
312
312
  var logger = getLogger("http");
313
313
  var DEFAULT_BASE_URL = "https://api.natural.co";
314
314
  var DEFAULT_TIMEOUT = 3e4;
315
+ var API_KEY_PREFIX_REGEX = /^sk_ntl_(dev|sandbox|prod)_/;
316
+ function parseApiKeyEnv(key) {
317
+ const match = API_KEY_PREFIX_REGEX.exec(key);
318
+ if (match) {
319
+ return match[1];
320
+ }
321
+ const preview = key.length > 16 ? `${key.slice(0, 16)}...` : key;
322
+ throw new InvalidRequestError(
323
+ `Invalid API key prefix. Expected a key starting with 'sk_ntl_dev_', 'sk_ntl_sandbox_', or 'sk_ntl_prod_'. Got: '${preview}'`
324
+ );
325
+ }
326
+ function validateBaseUrl(baseUrl) {
327
+ let url;
328
+ try {
329
+ url = new URL(baseUrl);
330
+ } catch {
331
+ throw new InvalidRequestError(`Invalid baseUrl: '${baseUrl}'. Must be a valid absolute URL.`);
332
+ }
333
+ if (url.protocol === "https:") {
334
+ return;
335
+ }
336
+ const host = url.hostname;
337
+ if (host === "localhost" || host === "127.0.0.1" || host === "::1" || host === "[::1]") {
338
+ return;
339
+ }
340
+ const allowHttp = process.env["NATURAL_ALLOW_HTTP"];
341
+ if (allowHttp && allowHttp !== "0" && allowHttp.toLowerCase() !== "false") {
342
+ return;
343
+ }
344
+ throw new InvalidRequestError(
345
+ `baseUrl must use HTTPS (got '${baseUrl}'). To allow plaintext HTTP for development, set NATURAL_ALLOW_HTTP=1 or use a localhost host.`
346
+ );
347
+ }
315
348
  function hashString(str) {
316
349
  let hash = 0;
317
350
  for (let i = 0; i < str.length; i++) {
@@ -329,6 +362,10 @@ var HTTPClient = class {
329
362
  constructor(options = {}) {
330
363
  this.apiKey = options.apiKey ?? process.env["NATURAL_API_KEY"] ?? "";
331
364
  this.baseUrl = (options.baseUrl ?? process.env["NATURAL_SERVER_URL"] ?? DEFAULT_BASE_URL).replace(/\/$/, "");
365
+ validateBaseUrl(this.baseUrl);
366
+ if (this.apiKey) {
367
+ parseApiKeyEnv(this.apiKey);
368
+ }
332
369
  this.timeout = options.timeout ?? DEFAULT_TIMEOUT;
333
370
  }
334
371
  /**
@@ -338,9 +375,6 @@ var HTTPClient = class {
338
375
  if (!this.apiKey) {
339
376
  throw new AuthenticationError();
340
377
  }
341
- if (!this.apiKey.startsWith("sk_ntl_")) {
342
- return this.apiKey;
343
- }
344
378
  const cacheKey = hashString(this.apiKey);
345
379
  const cached = this.jwtCache.get(cacheKey);
346
380
  if (cached && Date.now() < cached.expiresAt) {
@@ -1224,6 +1258,8 @@ exports.getLogger = getLogger;
1224
1258
  exports.logApiCall = logApiCall;
1225
1259
  exports.logError = logError;
1226
1260
  exports.logToolCall = logToolCall;
1261
+ exports.parseApiKeyEnv = parseApiKeyEnv;
1227
1262
  exports.runWithContext = runWithContext;
1263
+ exports.validateBaseUrl = validateBaseUrl;
1228
1264
  //# sourceMappingURL=index.cjs.map
1229
1265
  //# sourceMappingURL=index.cjs.map