@iteradian-rpc/sdk 1.0.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.
- package/README.md +631 -0
- package/dist/index.d.mts +893 -0
- package/dist/index.d.ts +893 -0
- package/dist/index.js +810 -0
- package/dist/index.mjs +770 -0
- package/package.json +55 -0
package/README.md
ADDED
|
@@ -0,0 +1,631 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<h1 align="center">Iteradian TypeScript SDK</h1>
|
|
3
|
+
<p align="center">Official TypeScript/JavaScript client library for the Iteradian Control Plane API</p>
|
|
4
|
+
</p>
|
|
5
|
+
|
|
6
|
+
<p align="center">
|
|
7
|
+
<img src="https://img.shields.io/badge/language-TypeScript-3178C6?style=flat-square&logo=typescript&logoColor=white" alt="TypeScript" />
|
|
8
|
+
<img src="https://img.shields.io/badge/node-%3E%3D16.0.0-339933?style=flat-square&logo=node.js&logoColor=white" alt="Node 16+" />
|
|
9
|
+
<img src="https://img.shields.io/badge/version-1.0.0-green?style=flat-square" alt="Version" />
|
|
10
|
+
<img src="https://img.shields.io/badge/license-MIT-blue?style=flat-square" alt="License" />
|
|
11
|
+
<img src="https://img.shields.io/badge/npm-%40iteradian%2Fsdk-CB3837?style=flat-square&logo=npm&logoColor=white" alt="npm" />
|
|
12
|
+
<img src="https://img.shields.io/badge/deps-zero-brightgreen?style=flat-square" alt="Zero Dependencies" />
|
|
13
|
+
<img src="https://img.shields.io/badge/formats-ESM%20%2B%20CJS-blue?style=flat-square" alt="ESM + CJS" />
|
|
14
|
+
</p>
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Features
|
|
19
|
+
|
|
20
|
+
- **Zero runtime dependencies** — uses native `fetch` API only
|
|
21
|
+
- **TypeScript-first** — comprehensive type definitions included (`.d.ts`)
|
|
22
|
+
- **Dual module format** — ships ESM (`.mjs`) and CommonJS (`.js`)
|
|
23
|
+
- **Resource-based API** — clean `client.auth`, `client.organizations`, `client.endpoints` access pattern
|
|
24
|
+
- **Full API coverage** — Auth, Organizations, API Keys, Endpoints, Usage, Dashboard, Alerts, Logs, Subscriptions, Plans, Support
|
|
25
|
+
- **Automatic retry** — exponential backoff on 429 / 5xx responses (configurable)
|
|
26
|
+
- **Timeout support** — via `AbortController` (configurable, default 30s)
|
|
27
|
+
- **Dual auth** — supports both Bearer tokens and `X-API-Key` headers
|
|
28
|
+
- **Tree-shakeable** — individual resource classes can be imported directly
|
|
29
|
+
- **Browser & Node.js** — works anywhere `fetch` is available
|
|
30
|
+
|
|
31
|
+
## Requirements
|
|
32
|
+
|
|
33
|
+
- **Node.js 16** or later (for native `fetch`)
|
|
34
|
+
- **TypeScript 5.3+** (recommended, for type checking)
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npm install @iteradian-rpc/sdk
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
yarn add @iteradian-rpc/sdk
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pnpm add @iteradian-rpc/sdk
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Quick Start
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
import { IteradianClient } from "@iteradian-rpc/sdk";
|
|
54
|
+
|
|
55
|
+
const client = new IteradianClient({
|
|
56
|
+
baseUrl: "https://api.iteradian.com/api/v1",
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// Login — sets the access token automatically
|
|
60
|
+
const tokens = await client.auth.login({
|
|
61
|
+
email: "user@example.com",
|
|
62
|
+
password: "password123",
|
|
63
|
+
});
|
|
64
|
+
console.log(`Logged in as ${tokens.user.email}`);
|
|
65
|
+
|
|
66
|
+
// List organizations
|
|
67
|
+
const orgs = await client.organizations.list();
|
|
68
|
+
console.log(`Organizations: ${orgs.length}`);
|
|
69
|
+
|
|
70
|
+
if (orgs.length > 0) {
|
|
71
|
+
const orgId = orgs[0].id;
|
|
72
|
+
|
|
73
|
+
// List endpoints
|
|
74
|
+
const endpoints = await client.endpoints.list(orgId);
|
|
75
|
+
for (const ep of endpoints) {
|
|
76
|
+
console.log(` ${ep.name}: ${ep.status} (${ep.region})`);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Create API key
|
|
80
|
+
const key = await client.apiKeys.create(orgId, {
|
|
81
|
+
name: "Production Key",
|
|
82
|
+
environment: "live",
|
|
83
|
+
});
|
|
84
|
+
console.log(`Created key: ${key.prefix}`);
|
|
85
|
+
|
|
86
|
+
// Query logs
|
|
87
|
+
const logs = await client.logs.query(orgId, {
|
|
88
|
+
status: "error",
|
|
89
|
+
pageSize: 50,
|
|
90
|
+
});
|
|
91
|
+
console.log(`Total logs: ${logs.total}`);
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### JavaScript (CommonJS)
|
|
96
|
+
|
|
97
|
+
```javascript
|
|
98
|
+
const { IteradianClient } = require("@iteradian-rpc/sdk");
|
|
99
|
+
|
|
100
|
+
const client = new IteradianClient({
|
|
101
|
+
baseUrl: "https://api.iteradian.com/api/v1",
|
|
102
|
+
});
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Using API Key Authentication
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
const client = new IteradianClient({
|
|
109
|
+
baseUrl: "https://api.iteradian.com/api/v1",
|
|
110
|
+
apiKey: "itrd_live_abc123...",
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
const endpoints = await client.endpoints.list("org-id");
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Configuration Options
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
import { IteradianClient, IteradianConfig } from "@iteradian-rpc/sdk";
|
|
120
|
+
|
|
121
|
+
const config: IteradianConfig = {
|
|
122
|
+
baseUrl: "https://api.iteradian.com/api/v1", // API base URL
|
|
123
|
+
accessToken: "existing-token", // Pre-set Bearer token
|
|
124
|
+
apiKey: "itrd_live_...", // API key for X-API-Key header
|
|
125
|
+
timeout: 60_000, // Request timeout in ms (default: 30000)
|
|
126
|
+
retry: true, // Enable auto-retry (default: true)
|
|
127
|
+
maxRetries: 5, // Max retry attempts (default: 3)
|
|
128
|
+
headers: {
|
|
129
|
+
// Custom headers
|
|
130
|
+
"X-Custom-Header": "value",
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const client = new IteradianClient(config);
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## API Reference
|
|
138
|
+
|
|
139
|
+
### Resource Accessors
|
|
140
|
+
|
|
141
|
+
| Resource | Property | Type | Description |
|
|
142
|
+
| ------------- | ---------------------- | ----------------------- | ----------------------------------- |
|
|
143
|
+
| Auth | `client.auth` | `AuthResource` | Authentication & account management |
|
|
144
|
+
| Organizations | `client.organizations` | `OrganizationsResource` | Organization CRUD & members |
|
|
145
|
+
| API Keys | `client.apiKeys` | `ApiKeysResource` | API key management |
|
|
146
|
+
| Endpoints | `client.endpoints` | `EndpointsResource` | Endpoint & network management |
|
|
147
|
+
| Usage | `client.usage` | `UsageResource` | Usage analytics |
|
|
148
|
+
| Dashboard | `client.dashboard` | `DashboardResource` | Dashboard data & health |
|
|
149
|
+
| Alerts | `client.alerts` | `AlertsResource` | Alert management & rules |
|
|
150
|
+
| Logs | `client.logs` | `LogsResource` | Request log querying |
|
|
151
|
+
| Subscriptions | `client.subscriptions` | `SubscriptionsResource` | Subscription & billing |
|
|
152
|
+
| Plans | `client.plans` | `PlansResource` | Plan catalog |
|
|
153
|
+
| Support | `client.support` | `SupportResource` | Support ticket management |
|
|
154
|
+
|
|
155
|
+
### Client Methods
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
// Set/clear access token at runtime
|
|
159
|
+
client.setAccessToken("new-token");
|
|
160
|
+
client.clearAccessToken();
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Authentication (`client.auth`)
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
// Login (token set automatically)
|
|
167
|
+
const tokens = await client.auth.login({ email: "...", password: "..." });
|
|
168
|
+
|
|
169
|
+
// Register
|
|
170
|
+
const tokens = await client.auth.register({
|
|
171
|
+
email: "...",
|
|
172
|
+
password: "...",
|
|
173
|
+
name: "...",
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// Refresh token
|
|
177
|
+
const tokens = await client.auth.refresh(refreshToken);
|
|
178
|
+
|
|
179
|
+
// Logout
|
|
180
|
+
await client.auth.logout();
|
|
181
|
+
|
|
182
|
+
// Two-Factor Authentication
|
|
183
|
+
const setup = await client.auth.enable2FA({ password: "..." });
|
|
184
|
+
console.log(`Secret: ${setup.secret}`);
|
|
185
|
+
console.log(`QR Code: ${setup.qrCode}`);
|
|
186
|
+
await client.auth.verify2FA({ code: "123456" });
|
|
187
|
+
await client.auth.disable2FA({ password: "...", code: "123456" });
|
|
188
|
+
|
|
189
|
+
// Magic Link
|
|
190
|
+
await client.auth.sendMagicLink({ email: "user@example.com" });
|
|
191
|
+
|
|
192
|
+
// Password Reset
|
|
193
|
+
await client.auth.forgotPassword({ email: "user@example.com" });
|
|
194
|
+
await client.auth.resetPassword({ token: "...", newPassword: "..." });
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Organizations (`client.organizations`)
|
|
198
|
+
|
|
199
|
+
```typescript
|
|
200
|
+
// CRUD
|
|
201
|
+
const orgs = await client.organizations.list();
|
|
202
|
+
const org = await client.organizations.create({
|
|
203
|
+
name: "My Org",
|
|
204
|
+
slug: "my-org",
|
|
205
|
+
});
|
|
206
|
+
const org = await client.organizations.get(orgId);
|
|
207
|
+
await client.organizations.delete(orgId);
|
|
208
|
+
|
|
209
|
+
// Members
|
|
210
|
+
const members = await client.organizations.listMembers(orgId);
|
|
211
|
+
const member = await client.organizations.inviteMember(orgId, {
|
|
212
|
+
email: "user@example.com",
|
|
213
|
+
role: "member",
|
|
214
|
+
});
|
|
215
|
+
await client.organizations.removeMember(orgId, memberId);
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### API Keys (`client.apiKeys`)
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
const keys = await client.apiKeys.list(orgId);
|
|
222
|
+
const key = await client.apiKeys.create(orgId, {
|
|
223
|
+
name: "Key Name",
|
|
224
|
+
environment: "live",
|
|
225
|
+
});
|
|
226
|
+
await client.apiKeys.revoke(orgId, keyId);
|
|
227
|
+
const newKey = await client.apiKeys.rotate(orgId, keyId);
|
|
228
|
+
const analytics = await client.apiKeys.getAnalytics(orgId, keyId);
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Endpoints (`client.endpoints`)
|
|
232
|
+
|
|
233
|
+
```typescript
|
|
234
|
+
// Networks
|
|
235
|
+
const networks = await client.endpoints.getNetworks();
|
|
236
|
+
|
|
237
|
+
// Endpoint management
|
|
238
|
+
const endpoints = await client.endpoints.list(orgId);
|
|
239
|
+
const endpoint = await client.endpoints.create(orgId, {
|
|
240
|
+
name: "...",
|
|
241
|
+
networkId: "...",
|
|
242
|
+
region: "us-east-1",
|
|
243
|
+
});
|
|
244
|
+
await client.endpoints.delete(orgId, endpointId);
|
|
245
|
+
const paused = await client.endpoints.pause(orgId, endpointId);
|
|
246
|
+
const resumed = await client.endpoints.resume(orgId, endpointId);
|
|
247
|
+
const health = await client.endpoints.checkHealth(orgId, endpointId);
|
|
248
|
+
const metrics = await client.endpoints.getMetrics(orgId, endpointId);
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### Usage & Dashboard
|
|
252
|
+
|
|
253
|
+
```typescript
|
|
254
|
+
// Usage
|
|
255
|
+
const usage = await client.usage.get(orgId, {
|
|
256
|
+
from: "2024-01-01",
|
|
257
|
+
to: "2024-01-31",
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
// Dashboard
|
|
261
|
+
const data = await client.dashboard.get(orgId, { period: "7d" });
|
|
262
|
+
const health = await client.dashboard.getHealth(orgId);
|
|
263
|
+
const stats = await client.dashboard.getQuickStats(orgId, { period: "24h" });
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Alerts (`client.alerts`)
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
// Alerts
|
|
270
|
+
const alerts = await client.alerts.list(orgId);
|
|
271
|
+
const ack = await client.alerts.acknowledge(orgId, alertId);
|
|
272
|
+
const resolved = await client.alerts.resolve(orgId, alertId);
|
|
273
|
+
|
|
274
|
+
// Alert Rules
|
|
275
|
+
const rules = await client.alerts.listRules(orgId);
|
|
276
|
+
const rule = await client.alerts.createRule(orgId, {
|
|
277
|
+
name: "High Latency",
|
|
278
|
+
metric: "latency_p95",
|
|
279
|
+
condition: "greater_than",
|
|
280
|
+
threshold: 500,
|
|
281
|
+
severity: "warning",
|
|
282
|
+
isEnabled: true,
|
|
283
|
+
cooldownMinutes: 15,
|
|
284
|
+
});
|
|
285
|
+
await client.alerts.deleteRule(orgId, ruleId);
|
|
286
|
+
|
|
287
|
+
// Channels
|
|
288
|
+
const channels = await client.alerts.getChannels(orgId);
|
|
289
|
+
await client.alerts.testChannel(orgId, channelId);
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### Logs (`client.logs`)
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
// Query with filters
|
|
296
|
+
const logs = await client.logs.query(orgId, {
|
|
297
|
+
page: 1,
|
|
298
|
+
pageSize: 50,
|
|
299
|
+
status: "error",
|
|
300
|
+
method: "eth_call",
|
|
301
|
+
network: "ethereum",
|
|
302
|
+
sortBy: "timestamp",
|
|
303
|
+
sortOrder: "desc",
|
|
304
|
+
});
|
|
305
|
+
console.log(`Page ${logs.page}/${logs.totalPages}`);
|
|
306
|
+
for (const log of logs.logs) {
|
|
307
|
+
console.log(` [${log.status}] ${log.method} (${log.latencyMs}ms)`);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Get single log
|
|
311
|
+
const log = await client.logs.get(orgId, logId);
|
|
312
|
+
|
|
313
|
+
// Filter options
|
|
314
|
+
const filters = await client.logs.getFilterOptions(orgId);
|
|
315
|
+
|
|
316
|
+
// Stats
|
|
317
|
+
const stats = await client.logs.getStats(orgId, { period: "24h" });
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### Subscriptions (`client.subscriptions`)
|
|
321
|
+
|
|
322
|
+
```typescript
|
|
323
|
+
const sub = await client.subscriptions.get(orgId);
|
|
324
|
+
const updated = await client.subscriptions.changePlan(orgId, { planId: "pro" });
|
|
325
|
+
const cancelled = await client.subscriptions.cancel(orgId);
|
|
326
|
+
const reactivated = await client.subscriptions.reactivate(orgId);
|
|
327
|
+
const invoices = await client.subscriptions.getInvoices(orgId);
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
### Plans (`client.plans`)
|
|
331
|
+
|
|
332
|
+
```typescript
|
|
333
|
+
const plans = await client.plans.list();
|
|
334
|
+
const plan = await client.plans.get(planId);
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### Support (`client.support`)
|
|
338
|
+
|
|
339
|
+
```typescript
|
|
340
|
+
const tickets = await client.support.listTickets(orgId);
|
|
341
|
+
const ticket = await client.support.createTicket(orgId, {
|
|
342
|
+
subject: "API returning 500 errors",
|
|
343
|
+
category: "technical",
|
|
344
|
+
priority: "high",
|
|
345
|
+
message: "Detailed description...",
|
|
346
|
+
});
|
|
347
|
+
const detail = await client.support.getTicket(orgId, ticketId);
|
|
348
|
+
await client.support.addMessage(orgId, ticketId, {
|
|
349
|
+
content: "Follow-up message...",
|
|
350
|
+
});
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
## Type Definitions
|
|
354
|
+
|
|
355
|
+
All types are exported from the package and defined in `src/types.ts` (538 lines):
|
|
356
|
+
|
|
357
|
+
### Configuration
|
|
358
|
+
|
|
359
|
+
| Type | Fields |
|
|
360
|
+
| ----------------- | -------------------------------------------------------------------------------------- |
|
|
361
|
+
| `IteradianConfig` | `baseUrl?`, `accessToken?`, `apiKey?`, `timeout?`, `retry?`, `maxRetries?`, `headers?` |
|
|
362
|
+
|
|
363
|
+
### Auth Types
|
|
364
|
+
|
|
365
|
+
| Type | Fields |
|
|
366
|
+
| ----------------- | ------------------------------------- |
|
|
367
|
+
| `LoginRequest` | `email`, `password`, `twoFactorCode?` |
|
|
368
|
+
| `RegisterRequest` | `email`, `password`, `name` |
|
|
369
|
+
| `AuthTokens` | `accessToken`, `refreshToken`, `user` |
|
|
370
|
+
| `TwoFASetup` | `secret`, `qrCode` |
|
|
371
|
+
|
|
372
|
+
### Organization Types
|
|
373
|
+
|
|
374
|
+
| Type | Fields |
|
|
375
|
+
| --------------------- | ---------------------------------------------- |
|
|
376
|
+
| `Organization` | `id`, `name`, `slug`, `createdAt`, `updatedAt` |
|
|
377
|
+
| `OrgMember` | `id`, `userId`, `email`, `role`, `joinedAt` |
|
|
378
|
+
| `CreateOrgRequest` | `name`, `slug` |
|
|
379
|
+
| `InviteMemberRequest` | `email`, `role` |
|
|
380
|
+
|
|
381
|
+
### API Key Types
|
|
382
|
+
|
|
383
|
+
| Type | Fields |
|
|
384
|
+
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
385
|
+
| `ApiKey` | `id`, `name`, `prefix`, `key?`, `environment`, `status`, `ipAllowlist?`, `allowedNetworks?`, `rateLimit?`, `dailyLimit?`, `createdAt`, `updatedAt`, `expiresAt?`, `lastUsedAt?` |
|
|
386
|
+
| `CreateApiKeyRequest` | `name`, `environment`, `ipAllowlist?`, `allowedNetworks?`, `rateLimit?`, `dailyLimit?`, `expiresAt?` |
|
|
387
|
+
|
|
388
|
+
### Network & Endpoint Types
|
|
389
|
+
|
|
390
|
+
| Type | Fields |
|
|
391
|
+
| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
|
392
|
+
| `Network` | `id`, `slug`, `name`, `chainId`, `type`, `environment`, `isActive` |
|
|
393
|
+
| `Endpoint` | `id`, `organizationId`, `networkId`, `region`, `name`, `priority`, `status`, `isEnabled`, `timeoutMs`, `retryCount`, metrics |
|
|
394
|
+
| `CreateEndpointRequest` | `name`, `networkId`, `region`, `priority?`, `timeoutMs?`, `retryCount?` |
|
|
395
|
+
|
|
396
|
+
### Logging Types
|
|
397
|
+
|
|
398
|
+
| Type | Fields |
|
|
399
|
+
| ---------------- | ----------------------------------------------------------------------------------------------------------- |
|
|
400
|
+
| `RequestLog` | `id`, `organizationId`, `method`, `status`, `statusCode?`, `latencyMs?`, `network?`, `region?`, `timestamp` |
|
|
401
|
+
| `LogsResponse` | `logs`, `total`, `page`, `pageSize`, `totalPages` |
|
|
402
|
+
| `LogQueryParams` | `page?`, `pageSize?`, `status?`, `method?`, `network?`, `region?`, `from?`, `to?`, `sortBy?`, `sortOrder?` |
|
|
403
|
+
|
|
404
|
+
### Alert Types
|
|
405
|
+
|
|
406
|
+
| Type | Fields |
|
|
407
|
+
| ------------------------ | -------------------------------------------------------------------------------------------------------------- |
|
|
408
|
+
| `Alert` | `id`, `organizationId`, `ruleId?`, `severity`, `status`, `title`, `message`, `metadata?` |
|
|
409
|
+
| `AlertRule` | `id`, `organizationId`, `name`, `metric`, `condition`, `threshold`, `severity`, `isEnabled`, `cooldownMinutes` |
|
|
410
|
+
| `CreateAlertRuleRequest` | `name`, `metric`, `condition`, `threshold`, `severity`, `isEnabled`, `cooldownMinutes` |
|
|
411
|
+
|
|
412
|
+
### Billing Types
|
|
413
|
+
|
|
414
|
+
| Type | Fields |
|
|
415
|
+
| -------------- | --------------------------------------------------------------------------------------- |
|
|
416
|
+
| `Plan` | `id`, `name`, `slug`, `price`, `currency`, `interval`, `features`, `limits`, `isActive` |
|
|
417
|
+
| `Subscription` | `id`, `organizationId`, `planId`, `status`, `cancelAtPeriodEnd`, `plan?` |
|
|
418
|
+
|
|
419
|
+
### Support Types
|
|
420
|
+
|
|
421
|
+
| Type | Fields |
|
|
422
|
+
| --------------------- | ------------------------------------------------------------------- |
|
|
423
|
+
| `SupportTicket` | `id`, `organizationId`, `subject`, `category`, `priority`, `status` |
|
|
424
|
+
| `CreateTicketRequest` | `subject`, `category`, `priority`, `message` |
|
|
425
|
+
|
|
426
|
+
### Error Types
|
|
427
|
+
|
|
428
|
+
| Type | Fields |
|
|
429
|
+
| ---------- | --------------------------------- |
|
|
430
|
+
| `ApiError` | `message`, `statusCode`, `error?` |
|
|
431
|
+
|
|
432
|
+
## Error Handling
|
|
433
|
+
|
|
434
|
+
```typescript
|
|
435
|
+
import { IteradianClient, IteradianError } from "@iteradian-rpc/sdk";
|
|
436
|
+
|
|
437
|
+
const client = new IteradianClient({ baseUrl: "..." });
|
|
438
|
+
|
|
439
|
+
try {
|
|
440
|
+
await client.auth.login({ email: "user@example.com", password: "wrong" });
|
|
441
|
+
} catch (err) {
|
|
442
|
+
if (err instanceof IteradianError) {
|
|
443
|
+
console.log(`Status: ${err.statusCode}`); // 401
|
|
444
|
+
console.log(`Message: ${err.message}`); // "Invalid credentials"
|
|
445
|
+
console.log(`Error: ${err.error}`); // Error code
|
|
446
|
+
} else {
|
|
447
|
+
console.log(`Unexpected error: ${err}`);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
On a gateway call the same error also carries the JSON-RPC detail, which is how
|
|
453
|
+
you tell "wait a second" from "you are out of quota until the period rolls
|
|
454
|
+
over":
|
|
455
|
+
|
|
456
|
+
```typescript
|
|
457
|
+
try {
|
|
458
|
+
await client.rpc.call("tao-mainnet", {
|
|
459
|
+
jsonrpc: "2.0",
|
|
460
|
+
method: "system_health",
|
|
461
|
+
params: [],
|
|
462
|
+
id: 1,
|
|
463
|
+
});
|
|
464
|
+
} catch (err) {
|
|
465
|
+
if (err instanceof IteradianError) {
|
|
466
|
+
if (err.isRateLimited) {
|
|
467
|
+
// -32005. Wait err.retryAfter seconds and try again.
|
|
468
|
+
} else if (err.isQuotaExhausted) {
|
|
469
|
+
// -32006 or -32007. Retrying will not help: err.data.resetsAt says when
|
|
470
|
+
// the allowance returns, and the cap needs a plan change.
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
Pass an `AbortSignal` to cancel a call:
|
|
477
|
+
|
|
478
|
+
```typescript
|
|
479
|
+
const controller = new AbortController();
|
|
480
|
+
setTimeout(() => controller.abort(), 1000);
|
|
481
|
+
|
|
482
|
+
await client.rpc.call("tao-mainnet", request, { signal: controller.signal });
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
### Retry Behavior
|
|
486
|
+
|
|
487
|
+
The SDK automatically retries:
|
|
488
|
+
|
|
489
|
+
- **5xx Server Errors** — with exponential backoff
|
|
490
|
+
- **429 Too Many Requests**, but **only** `-32005` (rate or concurrency limit).
|
|
491
|
+
`-32006` (monthly quota exhausted) and `-32007` (overage spend cap) do not
|
|
492
|
+
recover until the billing period rolls over, so retrying them burns your time
|
|
493
|
+
for a guaranteed 429.
|
|
494
|
+
|
|
495
|
+
Backoff formula: `min(1000 * 2^(attempt-1), 10000)` ms, or the gateway's own
|
|
496
|
+
`retryAfter` hint when it gives one — capped at 30 seconds either way.
|
|
497
|
+
|
|
498
|
+
**Transaction submissions are never retried.** A request whose JSON-RPC method
|
|
499
|
+
submits a transaction (`eth_sendRawTransaction`, `author_submitExtrinsic`,
|
|
500
|
+
`sendTransaction`, and the rest) is sent exactly once: a timeout says nothing
|
|
501
|
+
about whether the node already accepted and gossiped it, and a retry could
|
|
502
|
+
double-submit. The gateway applies the same rule when failing over between
|
|
503
|
+
nodes.
|
|
504
|
+
|
|
505
|
+
**Redirects are not followed.** Neither host redirects, and following one would
|
|
506
|
+
resend your API key to whatever origin the redirect named. A 3xx raises
|
|
507
|
+
`IteradianError` with `error: "UNEXPECTED_REDIRECT"`.
|
|
508
|
+
|
|
509
|
+
Configure via constructor:
|
|
510
|
+
|
|
511
|
+
```typescript
|
|
512
|
+
const client = new IteradianClient({
|
|
513
|
+
baseUrl: "...",
|
|
514
|
+
retry: true, // Enable retry (default: true)
|
|
515
|
+
maxRetries: 5, // Max retry attempts (default: 3)
|
|
516
|
+
timeout: 60_000, // Timeout per request (default: 30000ms)
|
|
517
|
+
});
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
To disable retries:
|
|
521
|
+
|
|
522
|
+
```typescript
|
|
523
|
+
const client = new IteradianClient({
|
|
524
|
+
baseUrl: "...",
|
|
525
|
+
retry: false,
|
|
526
|
+
});
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
## Advanced Usage
|
|
530
|
+
|
|
531
|
+
### Importing Individual Resources
|
|
532
|
+
|
|
533
|
+
For tree-shaking or advanced use cases, you can import resource classes directly:
|
|
534
|
+
|
|
535
|
+
```typescript
|
|
536
|
+
import { AuthResource } from "@iteradian-rpc/sdk";
|
|
537
|
+
import { HttpClient } from "@iteradian-rpc/sdk/http";
|
|
538
|
+
|
|
539
|
+
const http = new HttpClient({ baseUrl: "..." });
|
|
540
|
+
const auth = new AuthResource(http);
|
|
541
|
+
const tokens = await auth.login({ email: "...", password: "..." });
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
### Pre-Authenticated Client
|
|
545
|
+
|
|
546
|
+
```typescript
|
|
547
|
+
const client = new IteradianClient({
|
|
548
|
+
baseUrl: "https://api.iteradian.com/api/v1",
|
|
549
|
+
accessToken: "existing-jwt-token",
|
|
550
|
+
});
|
|
551
|
+
|
|
552
|
+
// No login needed — use the API directly
|
|
553
|
+
const orgs = await client.organizations.list();
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
## Build & Development
|
|
557
|
+
|
|
558
|
+
```bash
|
|
559
|
+
# Build (CJS + ESM + DTS)
|
|
560
|
+
npm run build
|
|
561
|
+
|
|
562
|
+
# Watch mode
|
|
563
|
+
npm run dev
|
|
564
|
+
|
|
565
|
+
# Type check
|
|
566
|
+
npm run lint
|
|
567
|
+
|
|
568
|
+
# Test
|
|
569
|
+
npm run test
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
Built with [tsup](https://github.com/egoist/tsup) — outputs:
|
|
573
|
+
|
|
574
|
+
- `dist/index.js` (CommonJS)
|
|
575
|
+
- `dist/index.mjs` (ESM)
|
|
576
|
+
- `dist/index.d.ts` (TypeScript declarations)
|
|
577
|
+
|
|
578
|
+
## Project Structure
|
|
579
|
+
|
|
580
|
+
```
|
|
581
|
+
sdks/typescript/
|
|
582
|
+
├── package.json # @iteradian-rpc/sdk, zero runtime deps
|
|
583
|
+
├── tsconfig.json # TypeScript config (ES2020, strict)
|
|
584
|
+
├── README.md # This file
|
|
585
|
+
└── src/
|
|
586
|
+
├── index.ts # Re-exports everything
|
|
587
|
+
├── client.ts # IteradianClient class (110 lines)
|
|
588
|
+
├── http.ts # HttpClient + IteradianError (155 lines)
|
|
589
|
+
├── types.ts # All TypeScript interfaces (538 lines)
|
|
590
|
+
└── resources/
|
|
591
|
+
├── auth.ts # AuthResource
|
|
592
|
+
├── organizations.ts
|
|
593
|
+
├── api-keys.ts # ApiKeysResource
|
|
594
|
+
├── endpoints.ts # EndpointsResource
|
|
595
|
+
├── usage.ts # UsageResource
|
|
596
|
+
├── dashboard.ts # DashboardResource
|
|
597
|
+
├── alerts.ts # AlertsResource
|
|
598
|
+
├── logs.ts # LogsResource
|
|
599
|
+
├── subscriptions.ts
|
|
600
|
+
├── plans.ts # PlansResource
|
|
601
|
+
└── support.ts # SupportResource
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
## License
|
|
605
|
+
|
|
606
|
+
MIT © [Iteradian](https://iteradian.com)
|
|
607
|
+
|
|
608
|
+
## RPC gateway, rate limits and quotas
|
|
609
|
+
|
|
610
|
+
The RPC gateway is a **different host** from the control-plane API:
|
|
611
|
+
|
|
612
|
+
| Surface | Base URL |
|
|
613
|
+
| --- | --- |
|
|
614
|
+
| Control plane | `https://api.iteradian.com/api/v1` |
|
|
615
|
+
| RPC gateway | `https://rpc.iteradian.com` |
|
|
616
|
+
|
|
617
|
+
This SDK takes both, and defaults the gateway to `https://rpc.iteradian.com`.
|
|
618
|
+
|
|
619
|
+
- A **batch of N calls costs N** against your per-second rate limit and your
|
|
620
|
+
monthly quota. Batching saves round trips, not allowance.
|
|
621
|
+
- Limits are **per subscription**, aggregated over every API key your
|
|
622
|
+
organization holds. Creating more keys does not raise them.
|
|
623
|
+
- The gateway returns HTTP 429 with a JSON-RPC error body:
|
|
624
|
+
`-32005` rate limited (retry after `error.data.retryAfter`), `-32006` monthly
|
|
625
|
+
quota exhausted, `-32007` overage spend cap reached. The last two do not
|
|
626
|
+
recover until the billing period rolls over, so retrying them is wasted work.
|
|
627
|
+
|
|
628
|
+
Plans: Developer 20 rps / 5M per month, Professional 100 rps / 30M, Dedicated
|
|
629
|
+
per contract. See `sdks/SDK_CONTRACT.md` for the full table.
|
|
630
|
+
|
|
631
|
+
**WebSocket is not available.** The gateway serves HTTPS JSON-RPC only.
|